Advertisement
Guest User

Untitled

a guest
Sep 19th, 2018
267
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.12 KB | None | 0 0
  1. // DetectPlates.cpp
  2.  
  3. #include "DetectPlates.h"
  4.  
  5. ///////////////////////////////////////////////////////////////////////////////////////////////////
  6. std::vector<PossiblePlate> detectPlatesInScene(cv::Mat &imgOriginalScene) {
  7.     std::vector<PossiblePlate> vectorOfPossiblePlates;          // this will be the return value
  8.  
  9.     cv::Mat imgGrayscaleScene;
  10.     cv::Mat imgThreshScene;
  11.     cv::Mat imgContours(imgOriginalScene.size(), CV_8UC3, SCALAR_BLACK);
  12.  
  13.     cv::RNG rng;
  14.  
  15.     //cv::destroyAllWindows();
  16.  
  17. #ifdef SHOW_STEPS
  18.     cv::imshow("0", imgOriginalScene);
  19. #endif  // SHOW_STEPS
  20.  
  21.     preprocess(imgOriginalScene, imgGrayscaleScene, imgThreshScene);        // preprocess to get grayscale and threshold images
  22.  
  23. #ifdef SHOW_STEPS
  24.     cv::imshow("1a", imgGrayscaleScene);
  25.     cv::imshow("1b", imgThreshScene);
  26. #endif  // SHOW_STEPS
  27.  
  28.     // find all possible chars in the scene,
  29.     // this function first finds all contours, then only includes contours that could be chars (without comparison to other chars yet)
  30.     std::vector<PossibleChar> vectorOfPossibleCharsInScene = findPossibleCharsInScene(imgThreshScene);
  31.  
  32. #ifdef SHOW_STEPS
  33.     std::cout << "step 2 - vectorOfPossibleCharsInScene.Count = " << vectorOfPossibleCharsInScene.size() << std::endl;        // 131 with MCLRNF1 image
  34.  
  35.     imgContours = cv::Mat(imgOriginalScene.size(), CV_8UC3, SCALAR_BLACK);
  36.     std::vector<std::vector<cv::Point> > contours;
  37.  
  38.     for (auto &possibleChar : vectorOfPossibleCharsInScene) {
  39.         contours.push_back(possibleChar.contour);
  40.     }
  41.     cv::drawContours(imgContours, contours, -1, SCALAR_WHITE);
  42.     cv::imshow("2b", imgContours);
  43. #endif  // SHOW_STEPS
  44.  
  45.     // given a vector of all possible chars, find groups of matching chars
  46.     // in the next steps each group of matching chars will attempt to be recognized as a plate
  47.     std::vector<std::vector<PossibleChar> > vectorOfVectorsOfMatchingCharsInScene = findVectorOfVectorsOfMatchingChars(vectorOfPossibleCharsInScene);
  48.  
  49. #ifdef SHOW_STEPS
  50.     std::cout << "step 3 - vectorOfVectorsOfMatchingCharsInScene.size() = " << vectorOfVectorsOfMatchingCharsInScene.size() << std::endl;        // 13 with MCLRNF1 image
  51.  
  52.     imgContours = cv::Mat(imgOriginalScene.size(), CV_8UC3, SCALAR_BLACK);
  53.  
  54.     for (auto &vectorOfMatchingChars : vectorOfVectorsOfMatchingCharsInScene) {
  55.         int intRandomBlue = rng.uniform(0, 256);
  56.         int intRandomGreen = rng.uniform(0, 256);
  57.         int intRandomRed = rng.uniform(0, 256);
  58.  
  59.         std::vector<std::vector<cv::Point> > contours;
  60.  
  61.         for (auto &matchingChar : vectorOfMatchingChars) {
  62.             contours.push_back(matchingChar.contour);
  63.         }
  64.         cv::drawContours(imgContours, contours, -1, cv::Scalar((double)intRandomBlue, (double)intRandomGreen, (double)intRandomRed));
  65.     }
  66.     cv::imshow("3", imgContours);
  67. #endif  // SHOW_STEPS
  68.  
  69.     for (auto &vectorOfMatchingChars : vectorOfVectorsOfMatchingCharsInScene) {                     // for each group of matching chars
  70.         PossiblePlate possiblePlate = extractPlate(imgOriginalScene, vectorOfMatchingChars);        // attempt to extract plate
  71.  
  72.         if (possiblePlate.imgPlate.empty() == false) {                                              // if plate was found
  73.             vectorOfPossiblePlates.push_back(possiblePlate);                                        // add to vector of possible plates
  74.         }
  75.     }
  76.  
  77.     std::cout << std::endl << vectorOfPossiblePlates.size() << " possible plates found" << std::endl;       // 13 with MCLRNF1 image
  78.  
  79. #ifdef SHOW_STEPS
  80.     std::cout << std::endl;
  81.     cv::imshow("4a", imgContours);
  82.  
  83.     for (unsigned int i = 0; i < vectorOfPossiblePlates.size(); i++) {
  84.         cv::Point2f p2fRectPoints[4];
  85.  
  86.         vectorOfPossiblePlates[i].rrLocationOfPlateInScene.points(p2fRectPoints);
  87.  
  88.         for (int j = 0; j < 4; j++) {
  89.             cv::line(imgContours, p2fRectPoints[j], p2fRectPoints[(j + 1) % 4], SCALAR_RED, 2);
  90.         }
  91.         cv::imshow("4a", imgContours);
  92.  
  93.         std::cout << "possible plate " << i << ", click on any image and press a key to continue . . ." << std::endl;
  94.  
  95.         cv::imshow("4b", vectorOfPossiblePlates[i].imgPlate);
  96.         cv::waitKey(0);
  97.     }
  98.     std::cout << std::endl << "plate detection complete, click on any image and press a key to begin char recognition . . ." << std::endl << std::endl;
  99.     cv::waitKey(0);
  100. #endif  // SHOW_STEPS
  101.  
  102.     return vectorOfPossiblePlates;
  103. }
  104.  
  105. ///////////////////////////////////////////////////////////////////////////////////////////////////
  106. std::vector<PossibleChar> findPossibleCharsInScene(cv::Mat &imgThresh) {
  107.     std::vector<PossibleChar> vectorOfPossibleChars;            // this will be the return value
  108.  
  109.     cv::Mat imgContours(imgThresh.size(), CV_8UC3, SCALAR_BLACK);
  110.     int intCountOfPossibleChars = 0;
  111.  
  112.     cv::Mat imgThreshCopy = imgThresh.clone();
  113.  
  114.     std::vector<std::vector<cv::Point> > contours;
  115.  
  116.     cv::findContours(imgThreshCopy, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);        // find all contours
  117.  
  118.     for (unsigned int i = 0; i < contours.size(); i++) {                // for each contour
  119. #ifdef SHOW_STEPS
  120.         cv::drawContours(imgContours, contours, i, SCALAR_WHITE);
  121. #endif  // SHOW_STEPS
  122.         PossibleChar possibleChar(contours[i]);
  123.  
  124.         if (checkIfPossibleChar(possibleChar)) {                // if contour is a possible char, note this does not compare to other chars (yet) . . .
  125.             intCountOfPossibleChars++;                          // increment count of possible chars
  126.             vectorOfPossibleChars.push_back(possibleChar);      // and add to vector of possible chars
  127.         }
  128.     }
  129.  
  130. #ifdef SHOW_STEPS
  131.     std::cout << std::endl << "contours.size() = " << contours.size() << std::endl;                         // 2362 with MCLRNF1 image
  132.     std::cout << "step 2 - intCountOfValidPossibleChars = " << intCountOfPossibleChars << std::endl;        // 131 with MCLRNF1 image
  133.     cv::imshow("2a", imgContours);
  134. #endif  // SHOW_STEPS
  135.  
  136.     return(vectorOfPossibleChars);
  137. }
  138.  
  139. ///////////////////////////////////////////////////////////////////////////////////////////////////
  140. PossiblePlate extractPlate(cv::Mat &imgOriginal, std::vector<PossibleChar> &vectorOfMatchingChars) {
  141.     PossiblePlate possiblePlate;            // this will be the return value
  142.  
  143.                                             // sort chars from left to right based on x position
  144.     std::sort(vectorOfMatchingChars.begin(), vectorOfMatchingChars.end(), PossibleChar::sortCharsLeftToRight);
  145.  
  146.     // calculate the center point of the plate
  147.     double dblPlateCenterX = (double)(vectorOfMatchingChars[0].intCenterX + vectorOfMatchingChars[vectorOfMatchingChars.size() - 1].intCenterX) / 2.0;
  148.     double dblPlateCenterY = (double)(vectorOfMatchingChars[0].intCenterY + vectorOfMatchingChars[vectorOfMatchingChars.size() - 1].intCenterY) / 2.0;
  149.     cv::Point2d p2dPlateCenter(dblPlateCenterX, dblPlateCenterY);
  150.  
  151.     // calculate plate width and height
  152.     int intPlateWidth = (int)((vectorOfMatchingChars[vectorOfMatchingChars.size() - 1].boundingRect.x + vectorOfMatchingChars[vectorOfMatchingChars.size() - 1].boundingRect.width - vectorOfMatchingChars[0].boundingRect.x) * PLATE_WIDTH_PADDING_FACTOR);
  153.  
  154.     double intTotalOfCharHeights = 0;
  155.  
  156.     for (auto &matchingChar : vectorOfMatchingChars) {
  157.         intTotalOfCharHeights = intTotalOfCharHeights + matchingChar.boundingRect.height;
  158.     }
  159.  
  160.     double dblAverageCharHeight = (double)intTotalOfCharHeights / vectorOfMatchingChars.size();
  161.  
  162.     int intPlateHeight = (int)(dblAverageCharHeight * PLATE_HEIGHT_PADDING_FACTOR);
  163.  
  164.     // calculate correction angle of plate region
  165.     double dblOpposite = vectorOfMatchingChars[vectorOfMatchingChars.size() - 1].intCenterY - vectorOfMatchingChars[0].intCenterY;
  166.     double dblHypotenuse = distanceBetweenChars(vectorOfMatchingChars[0], vectorOfMatchingChars[vectorOfMatchingChars.size() - 1]);
  167.     double dblCorrectionAngleInRad = asin(dblOpposite / dblHypotenuse);
  168.     double dblCorrectionAngleInDeg = dblCorrectionAngleInRad * (180.0 / CV_PI);
  169.  
  170.     // assign rotated rect member variable of possible plate
  171.     possiblePlate.rrLocationOfPlateInScene = cv::RotatedRect(p2dPlateCenter, cv::Size2f((float)intPlateWidth, (float)intPlateHeight), (float)dblCorrectionAngleInDeg);
  172.  
  173.     cv::Mat rotationMatrix;             // final steps are to perform the actual rotation
  174.     cv::Mat imgRotated;
  175.     cv::Mat imgCropped;
  176.  
  177.     rotationMatrix = cv::getRotationMatrix2D(p2dPlateCenter, dblCorrectionAngleInDeg, 1.0);         // get the rotation matrix for our calculated correction angle
  178.  
  179.     cv::warpAffine(imgOriginal, imgRotated, rotationMatrix, imgOriginal.size());            // rotate the entire image
  180.  
  181.                                                                                             // crop out the actual plate portion of the rotated image
  182.     cv::getRectSubPix(imgRotated, possiblePlate.rrLocationOfPlateInScene.size, possiblePlate.rrLocationOfPlateInScene.center, imgCropped);
  183.  
  184.     possiblePlate.imgPlate = imgCropped;            // copy the cropped plate image into the applicable member variable of the possible plate
  185.  
  186.     return(possiblePlate);
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement