From be99e8219b563e1079444cea899fe64f15b98def Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Sun, 19 Oct 2014 19:08:00 -0400 Subject: [PATCH] Updated segmentation to work with multiline text --- .../segmentation/charactersegmenter.cpp | 149 ++++++++---------- .../segmentation/charactersegmenter.h | 1 - 2 files changed, 68 insertions(+), 82 deletions(-) diff --git a/src/openalpr/segmentation/charactersegmenter.cpp b/src/openalpr/segmentation/charactersegmenter.cpp index 3ca2e5c..7e3f771 100644 --- a/src/openalpr/segmentation/charactersegmenter.cpp +++ b/src/openalpr/segmentation/charactersegmenter.cpp @@ -37,6 +37,8 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data) timespec startTime; getTime(&startTime); + pipeline_data->clearThresholds(); + pipeline_data->thresholds = produceThresholds(pipeline_data->crop_gray, config); medianBlur(pipeline_data->crop_gray, pipeline_data->crop_gray, 3); @@ -44,71 +46,56 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data) if (pipeline_data->plate_inverted) bitwise_not(pipeline_data->crop_gray, pipeline_data->crop_gray); - charAnalysis = new CharacterAnalysis(pipeline_data); - charAnalysis->analyze(); if (this->config->debugCharSegmenter) { displayImage(config, "CharacterSegmenter Thresholds", drawImageDashboard(pipeline_data->thresholds, CV_8U, 3)); } - if (this->config->debugCharSegmenter && pipeline_data->textLines.size() > 0) +// if (this->config->debugCharSegmenter && pipeline_data->textLines.size() > 0) +// { +// Mat img_contours(charAnalysis->bestThreshold.size(), CV_8U); +// charAnalysis->bestThreshold.copyTo(img_contours); +// cvtColor(img_contours, img_contours, CV_GRAY2RGB); +// +// vector > allowedContours; +// for (uint i = 0; i < charAnalysis->bestContours.size(); i++) +// { +// if (charAnalysis->bestContours.goodIndices[i]) +// allowedContours.push_back(charAnalysis->bestContours.contours[i]); +// } +// +// drawContours(img_contours, charAnalysis->bestContours.contours, +// -1, // draw all contours +// cv::Scalar(255,0,0), // in blue +// 1); // with a thickness of 1 +// +// drawContours(img_contours, allowedContours, +// -1, // draw all contours +// cv::Scalar(0,255,0), // in green +// 1); // with a thickness of 1 +// +// +// line(img_contours, pipeline_data->textLines[0].linePolygon[0], pipeline_data->textLines[0].linePolygon[1], Scalar(255, 0, 255), 1); +// line(img_contours, pipeline_data->textLines[0].linePolygon[3], pipeline_data->textLines[0].linePolygon[2], Scalar(255, 0, 255), 1); +// +// +// Mat bordered = addLabel(img_contours, "Best Contours"); +// imgDbgGeneral.push_back(bordered); +// } + + for (uint lineidx = 0; lineidx < pipeline_data->textLines.size(); lineidx++) { - Mat img_contours(charAnalysis->bestThreshold.size(), CV_8U); - charAnalysis->bestThreshold.copyTo(img_contours); - cvtColor(img_contours, img_contours, CV_GRAY2RGB); + this->top = pipeline_data->textLines[lineidx].topLine; + this->bottom = pipeline_data->textLines[lineidx].bottomLine; + - vector > allowedContours; - for (uint i = 0; i < charAnalysis->bestContours.size(); i++) - { - if (charAnalysis->bestContours.goodIndices[i]) - allowedContours.push_back(charAnalysis->bestContours.contours[i]); - } + float avgCharHeight = pipeline_data->textLines[lineidx].lineHeight; + float height_to_width_ratio = pipeline_data->config->charHeightMM / pipeline_data->config->charWidthMM; + float avgCharWidth = avgCharHeight / height_to_width_ratio; + //float avgCharWidth = median(charWidths.data(), charWidths.size()); - drawContours(img_contours, charAnalysis->bestContours.contours, - -1, // draw all contours - cv::Scalar(255,0,0), // in blue - 1); // with a thickness of 1 - - drawContours(img_contours, allowedContours, - -1, // draw all contours - cv::Scalar(0,255,0), // in green - 1); // with a thickness of 1 - - - line(img_contours, pipeline_data->textLines[0].linePolygon[0], pipeline_data->textLines[0].linePolygon[1], Scalar(255, 0, 255), 1); - line(img_contours, pipeline_data->textLines[0].linePolygon[3], pipeline_data->textLines[0].linePolygon[2], Scalar(255, 0, 255), 1); - - - Mat bordered = addLabel(img_contours, "Best Contours"); - imgDbgGeneral.push_back(bordered); - } - - if (pipeline_data->textLines.size() > 0) - { - this->top = LineSegment(pipeline_data->textLines[0].linePolygon[0].x, pipeline_data->textLines[0].linePolygon[0].y, - pipeline_data->textLines[0].linePolygon[1].x, pipeline_data->textLines[0].linePolygon[1].y); - this->bottom = LineSegment(pipeline_data->textLines[0].linePolygon[3].x, pipeline_data->textLines[0].linePolygon[3].y, - pipeline_data->textLines[0].linePolygon[2].x, pipeline_data->textLines[0].linePolygon[2].y); - - vector charWidths; - vector charHeights; - - for (uint i = 0; i < charAnalysis->bestContours.size(); i++) - { - if (charAnalysis->bestContours.goodIndices[i] == false) - continue; - - Rect mr = boundingRect(charAnalysis->bestContours.contours[i]); - - charWidths.push_back(mr.width); - charHeights.push_back(mr.height); - } - - float avgCharWidth = median(charWidths.data(), charWidths.size()); - float avgCharHeight = median(charHeights.data(), charHeights.size()); - - removeSmallContours(pipeline_data->thresholds, charAnalysis->allTextContours, avgCharWidth, avgCharHeight); + //removeSmallContours(pipeline_data->thresholds, charAnalysis->allTextContours, avgCharWidth, avgCharHeight); // Do the histogram analysis to figure out char regions @@ -118,11 +105,11 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data) vector allHistograms; vector allBoxes; - for (uint i = 0; i < charAnalysis->allTextContours.size(); i++) + for (uint i = 0; i < pipeline_data->thresholds.size(); i++) { Mat histogramMask = Mat::zeros(pipeline_data->thresholds[i].size(), CV_8U); - fillConvexPoly(histogramMask, pipeline_data->textLines[0].linePolygon.data(), pipeline_data->textLines[0].linePolygon.size(), Scalar(255,255,255)); + fillConvexPoly(histogramMask, pipeline_data->textLines[lineidx].linePolygon.data(), pipeline_data->textLines[lineidx].linePolygon.size(), Scalar(255,255,255)); VerticalHistogram vertHistogram(pipeline_data->thresholds[i], histogramMask); @@ -239,7 +226,7 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data) CharacterSegmenter::~CharacterSegmenter() { - delete charAnalysis; + } // Given a histogram and the horizontal line boundaries, respond with an array of boxes where the characters are @@ -445,28 +432,28 @@ vector CharacterSegmenter::get1DHits(Mat img, int yOffset) return hits; } -void CharacterSegmenter::removeSmallContours(vector thresholds, vector contours, float avgCharWidth, float avgCharHeight) -{ - //const float MIN_CHAR_AREA = 0.02 * avgCharWidth * avgCharHeight; // To clear out the tiny specks - const float MIN_CONTOUR_HEIGHT = 0.3 * avgCharHeight; - - for (uint i = 0; i < thresholds.size(); i++) - { - for (uint c = 0; c < contours[i].contours.size(); c++) - { - if (contours[i].contours[c].size() == 0) - continue; - - Rect mr = boundingRect(contours[i].contours[c]); - if (mr.height < MIN_CONTOUR_HEIGHT) - { - // Erase it - drawContours(thresholds[i], contours[i].contours, c, Scalar(0, 0, 0), -1); - continue; - } - } - } -} +//void CharacterSegmenter::removeSmallContours(vector thresholds, vector contours, float avgCharWidth, float avgCharHeight) +//{ +// //const float MIN_CHAR_AREA = 0.02 * avgCharWidth * avgCharHeight; // To clear out the tiny specks +// const float MIN_CONTOUR_HEIGHT = 0.3 * avgCharHeight; +// +// for (uint i = 0; i < thresholds.size(); i++) +// { +// for (uint c = 0; c < contours[i].contours.size(); c++) +// { +// if (contours[i].contours[c].size() == 0) +// continue; +// +// Rect mr = boundingRect(contours[i].contours[c]); +// if (mr.height < MIN_CONTOUR_HEIGHT) +// { +// // Erase it +// drawContours(thresholds[i], contours[i].contours, c, Scalar(0, 0, 0), -1); +// continue; +// } +// } +// } +//} vector CharacterSegmenter::combineCloseBoxes( vector charBoxes, float biggestCharWidth) { diff --git a/src/openalpr/segmentation/charactersegmenter.h b/src/openalpr/segmentation/charactersegmenter.h index 319dced..5540b76 100644 --- a/src/openalpr/segmentation/charactersegmenter.h +++ b/src/openalpr/segmentation/charactersegmenter.h @@ -55,7 +55,6 @@ class CharacterSegmenter Config* config; PipelineData* pipeline_data; - CharacterAnalysis* charAnalysis; LineSegment top; LineSegment bottom;