diff --git a/src/openalpr/detection/detector.cpp b/src/openalpr/detection/detector.cpp index 905eb09..edf10f7 100644 --- a/src/openalpr/detection/detector.cpp +++ b/src/openalpr/detection/detector.cpp @@ -64,9 +64,80 @@ namespace alpr vector Detector::detect(Mat frame, std::vector regionsOfInterest) { - // Must be implemented by subclass - std::vector rois; - return rois; + + Mat frame_gray; + + if (frame.channels() > 2) + { + cvtColor( frame, frame_gray, CV_BGR2GRAY ); + } + else + { + frame.copyTo(frame_gray); + } + + // Apply the detection mask if it has been specified by the user + if (detector_mask.mask_loaded) + frame_gray = detector_mask.apply_mask(frame_gray); + + vector detectedRegions; + for (int i = 0; i < regionsOfInterest.size(); i++) + { + Rect roi = regionsOfInterest[i]; + + // Adjust the ROI to be inside the detection mask (if it exists) + if (detector_mask.mask_loaded) + roi = detector_mask.getRoiInsideMask(roi); + + // Sanity check. If roi width or height is less than minimum possible plate size, + // then skip it + if ((roi.width < config->minPlateSizeWidthPx) || + (roi.height < config->minPlateSizeHeightPx)) + continue; + + Mat cropped = frame_gray(roi); + + int w = cropped.size().width; + int h = cropped.size().height; + int offset_x = roi.x; + int offset_y = roi.y; + float scale_factor = computeScaleFactor(w, h); + + if (scale_factor != 1.0) + resize(cropped, cropped, Size(w * scale_factor, h * scale_factor)); + + + float maxWidth = ((float) w) * (config->maxPlateWidthPercent / 100.0f) * scale_factor; + float maxHeight = ((float) h) * (config->maxPlateHeightPercent / 100.0f) * scale_factor; + Size minPlateSize(config->minPlateSizeWidthPx * scale_factor, config->minPlateSizeHeightPx * scale_factor); + Size maxPlateSize(maxWidth, maxHeight); + + vector allRegions = find_plates(cropped, minPlateSize, maxPlateSize); + + // Aggregate the Rect regions into a hierarchical representation + for( unsigned int i = 0; i < allRegions.size(); i++ ) + { + allRegions[i].x = (allRegions[i].x / scale_factor); + allRegions[i].y = (allRegions[i].y / scale_factor); + allRegions[i].width = allRegions[i].width / scale_factor; + allRegions[i].height = allRegions[i].height / scale_factor; + + // Ensure that the rectangle isn't < 0 or > maxWidth/Height + allRegions[i] = expandRect(allRegions[i], 0, 0, w, h); + + allRegions[i].x = allRegions[i].x + offset_x; + allRegions[i].y = allRegions[i].y + offset_y; + } + + vector orderedRegions = aggregateRegions(allRegions); + + + + for (int j = 0; j < orderedRegions.size(); j++) + detectedRegions.push_back(orderedRegions[j]); + } + + return detectedRegions; } std::string Detector::get_detector_file() { diff --git a/src/openalpr/detection/detector.h b/src/openalpr/detection/detector.h index 5457530..b2be755 100644 --- a/src/openalpr/detection/detector.h +++ b/src/openalpr/detection/detector.h @@ -45,9 +45,9 @@ namespace alpr bool isLoaded(); std::vector detect(cv::Mat frame); - virtual std::vector detect(cv::Mat frame, std::vector regionsOfInterest); + std::vector detect(cv::Mat frame, std::vector regionsOfInterest); - //virtual std::vector find_plates(cv::Mat frame)=0; + virtual std::vector find_plates(cv::Mat frame, cv::Size min_plate_size, cv::Size max_plate_size)=0; void setMask(cv::Mat mask); diff --git a/src/openalpr/detection/detectorcpu.cpp b/src/openalpr/detection/detectorcpu.cpp index 14d25e5..d34b333 100644 --- a/src/openalpr/detection/detectorcpu.cpp +++ b/src/openalpr/detection/detectorcpu.cpp @@ -45,77 +45,24 @@ namespace alpr DetectorCPU::~DetectorCPU() { } - vector DetectorCPU::detect(Mat frame, std::vector regionsOfInterest) - { - Mat frame_gray; - - if (frame.channels() > 2) - { - cvtColor( frame, frame_gray, CV_BGR2GRAY ); - } - else - { - frame.copyTo(frame_gray); - } - - // Apply the detection mask if it has been specified by the user - if (detector_mask.mask_loaded) - frame_gray = detector_mask.apply_mask(frame_gray); - - vector detectedRegions; - for (int i = 0; i < regionsOfInterest.size(); i++) - { - Rect roi = regionsOfInterest[i]; - - // Adjust the ROI to be inside the detection mask (if it exists) - if (detector_mask.mask_loaded) - roi = detector_mask.getRoiInsideMask(roi); - - // Sanity check. If roi width or height is less than minimum possible plate size, - // then skip it - if ((roi.width < config->minPlateSizeWidthPx) || - (roi.height < config->minPlateSizeHeightPx)) - continue; - - Mat cropped = frame_gray(roi); - vector subRegions = doCascade(cropped, roi.x, roi.y); - - for (int j = 0; j < subRegions.size(); j++) - detectedRegions.push_back(subRegions[j]); - } - return detectedRegions; - } - vector DetectorCPU::doCascade(Mat frame, int offset_x, int offset_y) + vector DetectorCPU::find_plates(Mat frame, cv::Size min_plate_size, cv::Size max_plate_size) { - int w = frame.size().width; - int h = frame.size().height; - - float scale_factor = computeScaleFactor(w, h); - vector plates; - - equalizeHist( frame, frame ); - - if (scale_factor != 1.0) - resize(frame, frame, Size(w * scale_factor, h * scale_factor)); - + //-- Detect plates timespec startTime; getTimeMonotonic(&startTime); - float maxWidth = ((float) w) * (config->maxPlateWidthPercent / 100.0f) * scale_factor; - float maxHeight = ((float) h) * (config->maxPlateHeightPercent / 100.0f) * scale_factor; - Size minSize(config->minPlateSizeWidthPx * scale_factor, config->minPlateSizeHeightPx * scale_factor); - Size maxSize(maxWidth, maxHeight); + equalizeHist( frame, frame ); plate_cascade.detectMultiScale( frame, plates, config->detection_iteration_increase, config->detectionStrictness, CV_HAAR_DO_CANNY_PRUNING, //0|CV_HAAR_SCALE_IMAGE, - minSize, maxSize ); + min_plate_size, max_plate_size ); if (config->debugTiming) @@ -125,23 +72,7 @@ namespace alpr cout << "LBP Time: " << diffclock(startTime, endTime) << "ms." << endl; } - for( unsigned int i = 0; i < plates.size(); i++ ) - { - plates[i].x = (plates[i].x / scale_factor); - plates[i].y = (plates[i].y / scale_factor); - plates[i].width = plates[i].width / scale_factor; - plates[i].height = plates[i].height / scale_factor; - - // Ensure that the rectangle isn't < 0 or > maxWidth/Height - plates[i] = expandRect(plates[i], 0, 0, w, h); - - plates[i].x = plates[i].x + offset_x; - plates[i].y = plates[i].y + offset_y; - } - - vector orderedRegions = aggregateRegions(plates); - - return orderedRegions; + return plates; } diff --git a/src/openalpr/detection/detectorcpu.h b/src/openalpr/detection/detectorcpu.h index 25fdd85..9e776bd 100644 --- a/src/openalpr/detection/detectorcpu.h +++ b/src/openalpr/detection/detectorcpu.h @@ -39,13 +39,12 @@ namespace alpr DetectorCPU(Config* config, PreWarp* prewarp); virtual ~DetectorCPU(); - std::vector detect(cv::Mat frame, std::vector regionsOfInterest); - + std::vector find_plates(cv::Mat frame, cv::Size min_plate_size, cv::Size max_plate_size); + private: cv::CascadeClassifier plate_cascade; - std::vector doCascade(cv::Mat frame, int offset_x, int offset_y); }; } diff --git a/src/openalpr/detection/detectorcuda.cpp b/src/openalpr/detection/detectorcuda.cpp index e6fd704..df9b2c2 100644 --- a/src/openalpr/detection/detectorcuda.cpp +++ b/src/openalpr/detection/detectorcuda.cpp @@ -19,7 +19,6 @@ #include "detectorcuda.h" - #ifdef COMPILE_GPU using namespace cv; @@ -49,60 +48,22 @@ namespace alpr DetectorCUDA::~DetectorCUDA() { } - vector DetectorCUDA::detect(Mat frame, std::vector regionsOfInterest) + vector DetectorCUDA::find_plates(Mat frame, cv::Size min_plate_size, cv::Size max_plate_size) { - - Mat frame_gray; - - if (frame.channels() > 2) - { - cvtColor( frame, frame_gray, CV_BGR2GRAY ); - } - else - { - frame.copyTo(frame_gray); - } - - vector detectedRegions; - for (int i = 0; i < regionsOfInterest.size(); i++) - { - Mat cropped = frame_gray(regionsOfInterest[i]); - vector subRegions = doCascade(cropped, regionsOfInterest[i].x, regionsOfInterest[i].y); - - for (int j = 0; j < subRegions.size(); j++) - detectedRegions.push_back(subRegions[j]); - } - return detectedRegions; - } - - vector DetectorCUDA::doCascade(Mat frame, int offset_x, int offset_y) - { - - int w = frame.size().width; - int h = frame.size().height; - - float scale_factor = computeScaleFactor(w, h); - - vector plates; - - equalizeHist( frame, frame ); - - if (scale_factor != 1.0) - resize(frame, frame, Size(w * scale_factor, h * scale_factor)); - //-- Detect plates + vector plates; + timespec startTime; getTimeMonotonic(&startTime); - float maxWidth = ((float) w) * (config->maxPlateWidthPercent / 100.0f) * scale_factor; - float maxHeight = ((float) h) * (config->maxPlateHeightPercent / 100.0f) * scale_factor; - Size minSize(config->minPlateSizeWidthPx * scale_factor, config->minPlateSizeHeightPx * scale_factor); - gpu::GpuMat cudaFrame, plateregions_buffer; Mat plateregions_downloaded; cudaFrame.upload(frame); - int numdetected = cuda_cascade.detectMultiScale(cudaFrame, plateregions_buffer, (double) config->detection_iteration_increase, config->detectionStrictness, minSize); + int numdetected = cuda_cascade.detectMultiScale(cudaFrame, plateregions_buffer, + (double) config->detection_iteration_increase, config->detectionStrictness, + min_plate_size); + plateregions_buffer.colRange(0, numdetected).download(plateregions_downloaded); for (int i = 0; i < numdetected; ++i) @@ -110,33 +71,14 @@ namespace alpr plates.push_back(plateregions_downloaded.ptr()[i]); } - - if (config->debugTiming) { timespec endTime; getTimeMonotonic(&endTime); cout << "LBP Time: " << diffclock(startTime, endTime) << "ms." << endl; } - - for( unsigned int i = 0; i < plates.size(); i++ ) - { - plates[i].x = (plates[i].x / scale_factor); - plates[i].y = (plates[i].y / scale_factor); - plates[i].width = plates[i].width / scale_factor; - plates[i].height = plates[i].height / scale_factor; - - // Ensure that the rectangle isn't < 0 or > maxWidth/Height - plates[i] = expandRect(plates[i], 0, 0, w, h); - - plates[i].x = plates[i].x + offset_x; - plates[i].y = plates[i].y + offset_y; - } - - vector orderedRegions = aggregateRegions(plates); - - return orderedRegions; - + + return plates; } } diff --git a/src/openalpr/detection/detectorcuda.h b/src/openalpr/detection/detectorcuda.h index f422821..c093626 100644 --- a/src/openalpr/detection/detectorcuda.h +++ b/src/openalpr/detection/detectorcuda.h @@ -46,13 +46,12 @@ namespace alpr DetectorCUDA(Config* config, PreWarp* prewarp); virtual ~DetectorCUDA(); - std::vector detect(cv::Mat frame, std::vector regionsOfInterest); + std::vector find_plates(cv::Mat frame, cv::Size min_plate_size, cv::Size max_plate_size); private: cv::gpu::CascadeClassifier_GPU cuda_cascade; - std::vector doCascade(cv::Mat frame, int offset_x, int offset_y); }; } diff --git a/src/openalpr/detection/detectormorph.cpp b/src/openalpr/detection/detectormorph.cpp index a6aa9b8..1f355c1 100644 --- a/src/openalpr/detection/detectormorph.cpp +++ b/src/openalpr/detection/detectormorph.cpp @@ -47,171 +47,160 @@ namespace alpr { } - vector DetectorMorph::detect(Mat frame, std::vector regionsOfInterest) { - - Mat frame_gray,frame_gray_cp; - - if (frame.channels() > 2) - { - cvtColor( frame, frame_gray, CV_BGR2GRAY ); - } - else - { - frame.copyTo(frame_gray); - } + std::vector DetectorMorph::find_plates(cv::Mat frame_gray, cv::Size min_plate_size, cv::Size max_plate_size) + { + Mat frame_gray_cp(frame_gray.size(), frame_gray.type()); frame_gray.copyTo(frame_gray_cp); blur(frame_gray, frame_gray, Size(5, 5)); - vector detectedRegions; - for (int i = 0; i < regionsOfInterest.size(); i++) { - Mat img_open, img_result; - Mat element = getStructuringElement(MORPH_RECT, Size(30, 4)); - morphologyEx(frame_gray, img_open, CV_MOP_OPEN, element, cv::Point(-1, -1)); + vector plates; + + Mat img_open, img_result; + Mat element = getStructuringElement(MORPH_RECT, Size(30, 4)); + morphologyEx(frame_gray, img_open, CV_MOP_OPEN, element, cv::Point(-1, -1)); - img_result = frame_gray - img_open; + img_result = frame_gray - img_open; - if (config->debugDetector && config->debugShowImages) { - imshow("Opening", img_result); + if (config->debugDetector && config->debugShowImages) { + imshow("Opening", img_result); + } + + //threshold image using otsu thresholding + Mat img_threshold, img_open2; + threshold(img_result, img_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); + + if (config->debugDetector && config->debugShowImages) { + imshow("Threshold Detector", img_threshold); + } + + Mat diamond(5, 5, CV_8U, cv::Scalar(1)); + + diamond.at(0, 0) = 0; + diamond.at(0, 1) = 0; + diamond.at(1, 0) = 0; + diamond.at(4, 4) = 0; + diamond.at(3, 4) = 0; + diamond.at(4, 3) = 0; + diamond.at(4, 0) = 0; + diamond.at(4, 1) = 0; + diamond.at(3, 0) = 0; + diamond.at(0, 4) = 0; + diamond.at(0, 3) = 0; + diamond.at(1, 4) = 0; + + morphologyEx(img_threshold, img_open2, CV_MOP_OPEN, diamond, cv::Point(-1, -1)); + Mat rectElement = getStructuringElement(cv::MORPH_RECT, Size(13, 4)); + morphologyEx(img_open2, img_threshold, CV_MOP_CLOSE, rectElement, cv::Point(-1, -1)); + + if (config->debugDetector && config->debugShowImages) { + imshow("Close", img_threshold); + waitKey(0); + } + + //Find contours of possibles plates + vector< vector< Point> > contours; + findContours(img_threshold, + contours, // a vector of contours + CV_RETR_EXTERNAL, // retrieve the external contours + CV_CHAIN_APPROX_NONE); // all pixels of each contours + + //Start to iterate to each contour founded + vector >::iterator itc = contours.begin(); + vector rects; + + //Remove patch that are no inside limits of aspect ratio and area. + while (itc != contours.end()) { + //Create bounding rect of object + RotatedRect mr = minAreaRect(Mat(*itc)); + + if (mr.angle < -45.) { + mr.angle += 90.0; + swap(mr.size.width, mr.size.height); + } + + if (!CheckSizes(mr)) + itc = contours.erase(itc); + else { + ++itc; + rects.push_back(mr); + } + } + + //Now prunning based on checking all candidate plates for a min/max number of blobsc + Mat img_crop, img_crop_b, img_crop_th, img_crop_th_inv; + vector< vector< Point> > plateBlobs; + vector< vector< Point> > plateBlobsInv; + double thresholds[] = { 10, 40, 80, 120, 160, 200, 240 }; + const int num_thresholds = 7; + int numValidChars = 0; + Mat rotated; + for (int i = 0; i < rects.size(); i++) { + numValidChars = 0; + RotatedRect PlateRect = rects[i]; + Size rect_size = PlateRect.size; + + // get the rotation matrix + Mat M = getRotationMatrix2D(PlateRect.center, PlateRect.angle, 1.0); + // perform the affine transformation + warpAffine(frame_gray_cp, rotated, M, frame_gray_cp.size(), INTER_CUBIC); + //Crop area around candidate plate + getRectSubPix(rotated, rect_size, PlateRect.center, img_crop); + + if (config->debugDetector && config->debugShowImages) { + imshow("Tilt Correction", img_crop); + waitKey(0); } - //threshold image using otsu thresholding - Mat img_threshold, img_open2; - threshold(img_result, img_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); + for (int z = 0; z < num_thresholds; z++) { - if (config->debugDetector && config->debugShowImages) { - imshow("Threshold Detector", img_threshold); - } + cv::threshold(img_crop, img_crop_th, thresholds[z], 255, cv::THRESH_BINARY); + cv::threshold(img_crop, img_crop_th_inv, thresholds[z], 255, cv::THRESH_BINARY_INV); - Mat diamond(5, 5, CV_8U, cv::Scalar(1)); + findContours(img_crop_th, + plateBlobs, // a vector of contours + CV_RETR_LIST, // retrieve the contour list + CV_CHAIN_APPROX_NONE); // all pixels of each contours - diamond.at(0, 0) = 0; - diamond.at(0, 1) = 0; - diamond.at(1, 0) = 0; - diamond.at(4, 4) = 0; - diamond.at(3, 4) = 0; - diamond.at(4, 3) = 0; - diamond.at(4, 0) = 0; - diamond.at(4, 1) = 0; - diamond.at(3, 0) = 0; - diamond.at(0, 4) = 0; - diamond.at(0, 3) = 0; - diamond.at(1, 4) = 0; - - morphologyEx(img_threshold, img_open2, CV_MOP_OPEN, diamond, cv::Point(-1, -1)); - Mat rectElement = getStructuringElement(cv::MORPH_RECT, Size(13, 4)); - morphologyEx(img_open2, img_threshold, CV_MOP_CLOSE, rectElement, cv::Point(-1, -1)); + findContours(img_crop_th_inv, + plateBlobsInv, // a vector of contours + CV_RETR_LIST, // retrieve the contour list + CV_CHAIN_APPROX_NONE); // all pixels of each contours - if (config->debugDetector && config->debugShowImages) { - imshow("Close", img_threshold); - waitKey(0); - } + int numBlobs = plateBlobs.size(); + int numBlobsInv = plateBlobsInv.size(); - //Find contours of possibles plates - vector< vector< Point> > contours; - findContours(img_threshold, - contours, // a vector of contours - CV_RETR_EXTERNAL, // retrieve the external contours - CV_CHAIN_APPROX_NONE); // all pixels of each contours + float idealAspect = config->avgCharWidthMM / config->avgCharHeightMM; + for (int j = 0; j < numBlobs; j++) { + cv::Rect r0 = cv::boundingRect(cv::Mat(plateBlobs[j])); - //Start to iterate to each contour founded - vector >::iterator itc = contours.begin(); - vector rects; + if (ValidateCharAspect(r0, idealAspect)) + numValidChars++; + } - //Remove patch that are no inside limits of aspect ratio and area. - while (itc != contours.end()) { - //Create bounding rect of object - RotatedRect mr = minAreaRect(Mat(*itc)); - - if (mr.angle < -45.) { - mr.angle += 90.0; - swap(mr.size.width, mr.size.height); - } - - if (!CheckSizes(mr)) - itc = contours.erase(itc); - else { - ++itc; - rects.push_back(mr); - } - } - - //Now prunning based on checking all candidate plates for a min/max number of blobsc -Mat img_crop, img_crop_b, img_crop_th, img_crop_th_inv; -vector< vector< Point> > plateBlobs; -vector< vector< Point> > plateBlobsInv; -double thresholds[] = { 10, 40, 80, 120, 160, 200, 240 }; -const int num_thresholds = 7; -int numValidChars = 0; -Mat rotated; -for (int i = 0; i < rects.size(); i++) { - numValidChars = 0; - RotatedRect PlateRect = rects[i]; - Size rect_size = PlateRect.size; - - // get the rotation matrix - Mat M = getRotationMatrix2D(PlateRect.center, PlateRect.angle, 1.0); - // perform the affine transformation - warpAffine(frame_gray_cp, rotated, M, frame_gray_cp.size(), INTER_CUBIC); - //Crop area around candidate plate - getRectSubPix(rotated, rect_size, PlateRect.center, img_crop); - - if (config->debugDetector && config->debugShowImages) { - imshow("Tilt Correction", img_crop); - waitKey(0); - } - - for (int z = 0; z < num_thresholds; z++) { - - cv::threshold(img_crop, img_crop_th, thresholds[z], 255, cv::THRESH_BINARY); - cv::threshold(img_crop, img_crop_th_inv, thresholds[z], 255, cv::THRESH_BINARY_INV); - - findContours(img_crop_th, - plateBlobs, // a vector of contours - CV_RETR_LIST, // retrieve the contour list - CV_CHAIN_APPROX_NONE); // all pixels of each contours - - findContours(img_crop_th_inv, - plateBlobsInv, // a vector of contours - CV_RETR_LIST, // retrieve the contour list - CV_CHAIN_APPROX_NONE); // all pixels of each contours - - int numBlobs = plateBlobs.size(); - int numBlobsInv = plateBlobsInv.size(); - - float idealAspect = config->avgCharWidthMM / config->avgCharHeightMM; - for (int j = 0; j < numBlobs; j++) { - cv::Rect r0 = cv::boundingRect(cv::Mat(plateBlobs[j])); - - if (ValidateCharAspect(r0, idealAspect)) - numValidChars++; - } - - for (int j = 0; j < numBlobsInv; j++) { - cv::Rect r0 = cv::boundingRect(cv::Mat(plateBlobsInv[j])); - if (ValidateCharAspect(r0, idealAspect)) - numValidChars++; - } - - } - //If too much or too lcittle might not be a true plate - //if (numBlobs < 3 || numBlobs > 50) continue; - if (numValidChars < 4 || numValidChars > 50) continue; - - PlateRegion PlateReg; - - // Ensure that the rectangle isn't < 0 or > maxWidth/Height - Rect bounding_rect = PlateRect.boundingRect(); - PlateReg.rect = expandRect(bounding_rect, 0, 0, frame.cols, frame.rows); - - - detectedRegions.push_back(PlateReg); + for (int j = 0; j < numBlobsInv; j++) { + cv::Rect r0 = cv::boundingRect(cv::Mat(plateBlobsInv[j])); + if (ValidateCharAspect(r0, idealAspect)) + numValidChars++; + } } + //If too much or too lcittle might not be a true plate + //if (numBlobs < 3 || numBlobs > 50) continue; + if (numValidChars < 4 || numValidChars > 50) continue; + + PlateRegion PlateReg; + + // Ensure that the rectangle isn't < 0 or > maxWidth/Height + Rect bounding_rect = PlateRect.boundingRect(); + + Rect rect_expanded = expandRect(bounding_rect, 0, 0, frame_gray.cols, frame_gray.rows); + + plates.push_back(rect_expanded); } - return detectedRegions; + return plates; } bool DetectorMorph::CheckSizes(RotatedRect& mr) { diff --git a/src/openalpr/detection/detectormorph.h b/src/openalpr/detection/detectormorph.h index c19af95..5d4040b 100644 --- a/src/openalpr/detection/detectormorph.h +++ b/src/openalpr/detection/detectormorph.h @@ -38,7 +38,7 @@ namespace alpr { DetectorMorph(Config* config, PreWarp* prewarp); virtual ~DetectorMorph(); - std::vector detect(cv::Mat frame, std::vector regionsOfInterest); + std::vector find_plates(cv::Mat frame, cv::Size min_plate_size, cv::Size max_plate_size); private: bool CheckSizes(cv::RotatedRect& mr); diff --git a/src/openalpr/detection/detectorocl.cpp b/src/openalpr/detection/detectorocl.cpp index 016385d..42c6630 100644 --- a/src/openalpr/detection/detectorocl.cpp +++ b/src/openalpr/detection/detectorocl.cpp @@ -98,47 +98,10 @@ namespace alpr DetectorOCL::~DetectorOCL() { } - vector DetectorOCL::detect(Mat frame, std::vector regionsOfInterest) + + vector DetectorOCL::find_plates(Mat orig_frame, cv::Size min_plate_size, cv::Size max_plate_size) { - Mat frame_gray; - - if (frame.channels() > 2) - { - cvtColor( frame, frame_gray, CV_BGR2GRAY ); - } - else - { - frame.copyTo(frame_gray); - } - - - vector detectedRegions; - for (int i = 0; i < regionsOfInterest.size(); i++) - { - // Sanity check. If roi width or height is less than minimum possible plate size, - // then skip it - if ((regionsOfInterest[i].width < config->minPlateSizeWidthPx) || - (regionsOfInterest[i].height < config->minPlateSizeHeightPx)) - continue; - - Mat cropped = frame_gray(regionsOfInterest[i]); - vector subRegions = doCascade(cropped, regionsOfInterest[i].x, regionsOfInterest[i].y); - - for (int j = 0; j < subRegions.size(); j++) - detectedRegions.push_back(subRegions[j]); - } - return detectedRegions; - } - - vector DetectorOCL::doCascade(Mat orig_frame, int offset_x, int offset_y) - { - - - int w = orig_frame.size().width; - int h = orig_frame.size().height; - - float scale_factor = computeScaleFactor(w, h); vector plates; @@ -146,12 +109,6 @@ namespace alpr timespec startTime; getTimeMonotonic(&startTime); - float maxWidth = ((float) w) * (config->maxPlateWidthPercent / 100.0f) * scale_factor; - float maxHeight = ((float) h) * (config->maxPlateHeightPercent / 100.0f) * scale_factor; - - Size minSize(config->minPlateSizeWidthPx * scale_factor, config->minPlateSizeHeightPx * scale_factor); - Size maxSize(maxWidth, maxHeight); - // If we have an OpenCL core available, use it. Otherwise use CPU if (ocl_detector_mutex_m.try_lock()) { @@ -160,12 +117,9 @@ namespace alpr equalizeHist( openclFrame, openclFrame ); - if (scale_factor != 1.0) - resize(openclFrame, openclFrame, Size(w * scale_factor, h * scale_factor)); - plate_cascade.detectMultiScale( openclFrame, plates, config->detection_iteration_increase, config->detectionStrictness, 0, - minSize, maxSize ); + min_plate_size, max_plate_size ); ocl_detector_mutex_m.unlock(); } @@ -173,18 +127,12 @@ namespace alpr { equalizeHist( orig_frame, orig_frame ); - if (scale_factor != 1.0) - resize(orig_frame, orig_frame, Size(w * scale_factor, h * scale_factor)); - plate_cascade.detectMultiScale( orig_frame, plates, config->detection_iteration_increase, config->detectionStrictness, 0, - minSize, maxSize ); + min_plate_size, max_plate_size ); } - - - if (config->debugTiming) { timespec endTime; @@ -192,23 +140,8 @@ namespace alpr cout << "LBP Time: " << diffclock(startTime, endTime) << "ms." << endl; } - for( unsigned int i = 0; i < plates.size(); i++ ) - { - plates[i].x = (plates[i].x / scale_factor); - plates[i].y = (plates[i].y / scale_factor); - plates[i].width = plates[i].width / scale_factor; - plates[i].height = plates[i].height / scale_factor; + return plates; - // Ensure that the rectangle isn't < 0 or > maxWidth/Height - plates[i] = expandRect(plates[i], 0, 0, w, h); - - plates[i].x = plates[i].x + offset_x; - plates[i].y = plates[i].y + offset_y; - } - - vector orderedRegions = aggregateRegions(plates); - - return orderedRegions; } diff --git a/src/openalpr/detection/detectorocl.h b/src/openalpr/detection/detectorocl.h index aded432..5e9109d 100644 --- a/src/openalpr/detection/detectorocl.h +++ b/src/openalpr/detection/detectorocl.h @@ -42,13 +42,12 @@ namespace alpr DetectorOCL(Config* config, PreWarp* prewarp); virtual ~DetectorOCL(); - std::vector detect(cv::Mat frame, std::vector regionsOfInterest); + std::vector find_plates(cv::Mat frame, cv::Size min_plate_size, cv::Size max_plate_size); private: cv::CascadeClassifier plate_cascade; - std::vector doCascade(cv::Mat frame, int offset_x, int offset_y); }; }