Rearranged threshold data to be contained in pipeline_data

This commit is contained in:
Matt Hill
2014-07-01 18:52:53 -04:00
parent a0af4093d6
commit 7e12ca1500
13 changed files with 82 additions and 75 deletions

View File

@@ -130,7 +130,7 @@ int main( int argc, const char** argv )
} }
CharacterSegmenter charSegmenter(&pipeline_data); CharacterSegmenter charSegmenter(&pipeline_data);
ocr->performOCR(charSegmenter.getThresholds(), charSegmenter.characters); ocr->performOCR(&pipeline_data);
ocr->postProcessor->analyze(statecode, 25); ocr->postProcessor->analyze(statecode, 25);
cout << files[i] << "," << statecode << "," << ocr->postProcessor->bestChars << endl; cout << files[i] << "," << statecode << "," << ocr->postProcessor->bestChars << endl;
@@ -237,7 +237,7 @@ int main( int argc, const char** argv )
lpAnalysisPositiveTimes.push_back(analysisTime); lpAnalysisPositiveTimes.push_back(analysisTime);
getTime(&startTime); getTime(&startTime);
ocr.performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters); ocr.performOCR(&pipeline_data);
getTime(&endTime); getTime(&endTime);
double ocrTime = diffclock(startTime, endTime); double ocrTime = diffclock(startTime, endTime);
cout << "\tRegion " << z << ": OCR time: " << ocrTime << "ms." << endl; cout << "\tRegion " << z << ": OCR time: " << ocrTime << "ms." << endl;

View File

@@ -151,12 +151,12 @@ int main( int argc, const char** argv )
//ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters); //ocr.cleanCharRegions(charSegmenter.thresholds, charSegmenter.characters);
ocr.performOCR(charSegmenter.getThresholds(), charSegmenter.characters); ocr.performOCR(&pipeline_data);
ocr.postProcessor->analyze(statecodestr, 25); ocr.postProcessor->analyze(statecodestr, 25);
cout << "OCR results: " << ocr.postProcessor->bestChars << endl; cout << "OCR results: " << ocr.postProcessor->bestChars << endl;
vector<bool> selectedBoxes(charSegmenter.getThresholds().size()); vector<bool> selectedBoxes(pipeline_data.thresholds.size());
for (int z = 0; z < charSegmenter.getThresholds().size(); z++) for (int z = 0; z < pipeline_data.thresholds.size(); z++)
selectedBoxes[z] = false; selectedBoxes[z] = false;
int curDashboardSelection = 0; int curDashboardSelection = 0;
@@ -166,7 +166,7 @@ int main( int argc, const char** argv )
for (int z = 0; z < charSegmenter.characters.size(); z++) for (int z = 0; z < charSegmenter.characters.size(); z++)
humanInputs[z] = ' '; humanInputs[z] = ' ';
showDashboard(charSegmenter.getThresholds(), selectedBoxes, 0); showDashboard(pipeline_data.thresholds, selectedBoxes, 0);
char waitkey = (char) waitKey(50); char waitkey = (char) waitKey(50);
@@ -176,50 +176,50 @@ int main( int argc, const char** argv )
{ {
if (curDashboardSelection > 0) if (curDashboardSelection > 0)
curDashboardSelection--; curDashboardSelection--;
showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
} }
else if (waitkey == RIGHT_ARROW_KEY) // right arrow key else if (waitkey == RIGHT_ARROW_KEY) // right arrow key
{ {
if (curDashboardSelection < charSegmenter.getThresholds().size() - 1) if (curDashboardSelection < pipeline_data.thresholds.size() - 1)
curDashboardSelection++; curDashboardSelection++;
showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
} }
else if (waitkey == DOWN_ARROW_KEY) else if (waitkey == DOWN_ARROW_KEY)
{ {
if (curDashboardSelection + DASHBOARD_COLUMNS <= charSegmenter.getThresholds().size() - 1) if (curDashboardSelection + DASHBOARD_COLUMNS <= pipeline_data.thresholds.size() - 1)
curDashboardSelection += DASHBOARD_COLUMNS; curDashboardSelection += DASHBOARD_COLUMNS;
showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
} }
else if (waitkey == UP_ARROW_KEY) else if (waitkey == UP_ARROW_KEY)
{ {
if (curDashboardSelection - DASHBOARD_COLUMNS >= 0) if (curDashboardSelection - DASHBOARD_COLUMNS >= 0)
curDashboardSelection -= DASHBOARD_COLUMNS; curDashboardSelection -= DASHBOARD_COLUMNS;
showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
} }
else if (waitkey == ENTER_KEY) else if (waitkey == ENTER_KEY)
{ {
vector<char> tempdata = showCharSelection(charSegmenter.getThresholds()[curDashboardSelection], charSegmenter.characters, statecodestr); vector<char> tempdata = showCharSelection(pipeline_data.thresholds[curDashboardSelection], charSegmenter.characters, statecodestr);
for (int c = 0; c < charSegmenter.characters.size(); c++) for (int c = 0; c < charSegmenter.characters.size(); c++)
humanInputs[c] = tempdata[c]; humanInputs[c] = tempdata[c];
} }
else if (waitkey == SPACE_KEY) else if (waitkey == SPACE_KEY)
{ {
selectedBoxes[curDashboardSelection] = !selectedBoxes[curDashboardSelection]; selectedBoxes[curDashboardSelection] = !selectedBoxes[curDashboardSelection];
showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
} }
else if (waitkey == 's' || waitkey == 'S' || waitkey == 'W') else if (waitkey == 's' || waitkey == 'S' || waitkey == 'W')
{ {
if (waitkey == 'W') if (waitkey == 'W')
{ {
selectedBoxes[curDashboardSelection] = true; selectedBoxes[curDashboardSelection] = true;
showDashboard(charSegmenter.getThresholds(), selectedBoxes, curDashboardSelection); showDashboard(pipeline_data.thresholds, selectedBoxes, curDashboardSelection);
const std::string& ocr_str = ocr.postProcessor->bestChars; const std::string& ocr_str = ocr.postProcessor->bestChars;
humanInputs.assign(ocr_str.begin(), ocr_str.end()); humanInputs.assign(ocr_str.begin(), ocr_str.end());
} }
bool somethingSelected = false; bool somethingSelected = false;
bool chardataTagged = false; bool chardataTagged = false;
for (int c = 0; c < charSegmenter.getThresholds().size(); c++) for (int c = 0; c < pipeline_data.thresholds.size(); c++)
{ {
if (selectedBoxes[c]) if (selectedBoxes[c])
{ {
@@ -243,13 +243,13 @@ int main( int argc, const char** argv )
if (humanInputs[c] == ' ') if (humanInputs[c] == ' ')
continue; continue;
for (int t = 0; t < charSegmenter.getThresholds().size(); t++) for (int t = 0; t < pipeline_data.thresholds.size(); t++)
{ {
if (selectedBoxes[t] == false) if (selectedBoxes[t] == false)
continue; continue;
stringstream filename; stringstream filename;
Mat cropped = charSegmenter.getThresholds()[t](charSegmenter.characters[c]); Mat cropped = pipeline_data.thresholds[t](charSegmenter.characters[c]);
filename << outDir << "/" << humanInputs[c] << "-" << t << "-" << files[i]; filename << outDir << "/" << humanInputs[c] << "-" << t << "-" << files[i];
imwrite(filename.str(), cropped); imwrite(filename.str(), cropped);
cout << "Writing char image: " << filename.str() << endl; cout << "Writing char image: " << filename.str() << endl;

View File

@@ -230,7 +230,7 @@ void plateAnalysisThread(void* arg)
// Tesseract OCR does not appear to be threadsafe // Tesseract OCR does not appear to be threadsafe
dispatcher->ocrMutex.lock(); dispatcher->ocrMutex.lock();
dispatcher->ocr->performOCR(lp.charSegmenter->getThresholds(), lp.charSegmenter->characters); dispatcher->ocr->performOCR(&pipeline_data);
dispatcher->ocr->postProcessor->analyze(plateResult.region, dispatcher->topN); dispatcher->ocr->postProcessor->analyze(plateResult.region, dispatcher->topN);
const vector<PPResult> ppResults = dispatcher->ocr->postProcessor->getResults(); const vector<PPResult> ppResults = dispatcher->ocr->postProcessor->getResults();
dispatcher->ocrMutex.unlock(); dispatcher->ocrMutex.unlock();

View File

@@ -36,29 +36,26 @@ CharacterAnalysis::CharacterAnalysis(PipelineData* pipeline_data)
CharacterAnalysis::~CharacterAnalysis() CharacterAnalysis::~CharacterAnalysis()
{ {
for (int i = 0; i < thresholds.size(); i++)
{
thresholds[i].release();
}
thresholds.clear();
} }
void CharacterAnalysis::analyze() void CharacterAnalysis::analyze()
{ {
thresholds = produceThresholds(pipeline_data->crop_gray, config); pipeline_data->clearThresholds();
pipeline_data->thresholds = produceThresholds(pipeline_data->crop_gray, config);
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
for (int i = 0; i < thresholds.size(); i++) for (int i = 0; i < pipeline_data->thresholds.size(); i++)
{ {
vector<vector<Point> > contours; vector<vector<Point> > contours;
vector<Vec4i> hierarchy; vector<Vec4i> hierarchy;
Mat tempThreshold(thresholds[i].size(), CV_8U); Mat tempThreshold(pipeline_data->thresholds[i].size(), CV_8U);
thresholds[i].copyTo(tempThreshold); pipeline_data->thresholds[i].copyTo(tempThreshold);
findContours(tempThreshold, findContours(tempThreshold,
contours, // a vector of contours contours, // a vector of contours
hierarchy, hierarchy,
@@ -79,9 +76,9 @@ void CharacterAnalysis::analyze()
getTime(&startTime); getTime(&startTime);
for (int i = 0; i < thresholds.size(); i++) for (int i = 0; i < pipeline_data->thresholds.size(); i++)
{ {
vector<bool> goodIndices = this->filter(thresholds[i], allContours[i], allHierarchy[i]); vector<bool> goodIndices = this->filter(pipeline_data->thresholds[i], allContours[i], allHierarchy[i]);
charSegments.push_back(goodIndices); charSegments.push_back(goodIndices);
if (config->debugCharAnalysis) if (config->debugCharAnalysis)
@@ -100,7 +97,7 @@ void CharacterAnalysis::analyze()
if (hasPlateMask) if (hasPlateMask)
{ {
// Filter out bad contours now that we have an outer box mask... // Filter out bad contours now that we have an outer box mask...
for (int i = 0; i < thresholds.size(); i++) for (int i = 0; i < pipeline_data->thresholds.size(); i++)
{ {
charSegments[i] = filterByOuterMask(allContours[i], allHierarchy[i], charSegments[i]); charSegments[i] = filterByOuterMask(allContours[i], allHierarchy[i], charSegments[i]);
} }
@@ -108,7 +105,7 @@ void CharacterAnalysis::analyze()
int bestFitScore = -1; int bestFitScore = -1;
int bestFitIndex = -1; int bestFitIndex = -1;
for (int i = 0; i < thresholds.size(); i++) for (int i = 0; i < pipeline_data->thresholds.size(); i++)
{ {
//vector<bool> goodIndices = this->filter(thresholds[i], allContours[i], allHierarchy[i]); //vector<bool> goodIndices = this->filter(thresholds[i], allContours[i], allHierarchy[i]);
//charSegments.push_back(goodIndices); //charSegments.push_back(goodIndices);
@@ -120,7 +117,7 @@ void CharacterAnalysis::analyze()
bestFitScore = segmentCount; bestFitScore = segmentCount;
bestFitIndex = i; bestFitIndex = i;
bestCharSegments = charSegments[i]; bestCharSegments = charSegments[i];
bestThreshold = thresholds[i]; bestThreshold = pipeline_data->thresholds[i];
bestContours = allContours[i]; bestContours = allContours[i];
bestHierarchy = allHierarchy[i]; bestHierarchy = allHierarchy[i];
bestCharSegmentsCount = segmentCount; bestCharSegmentsCount = segmentCount;
@@ -272,7 +269,7 @@ Mat CharacterAnalysis::findOuterBoxMask()
} }
} }
Mat mask = Mat::zeros(thresholds[winningIndex].size(), CV_8U); Mat mask = Mat::zeros(pipeline_data->thresholds[winningIndex].size(), CV_8U);
// get rid of the outline by drawing a 1 pixel width black line // get rid of the outline by drawing a 1 pixel width black line
drawContours(mask, allContours[winningIndex], drawContours(mask, allContours[winningIndex],
@@ -316,7 +313,7 @@ Mat CharacterAnalysis::findOuterBoxMask()
if (biggestContourIndex != -1) if (biggestContourIndex != -1)
{ {
mask = Mat::zeros(thresholds[winningIndex].size(), CV_8U); mask = Mat::zeros(pipeline_data->thresholds[winningIndex].size(), CV_8U);
vector<Point> smoothedMaskPoints; vector<Point> smoothedMaskPoints;
approxPolyDP(contoursSecondRound[biggestContourIndex], smoothedMaskPoints, 2, true); approxPolyDP(contoursSecondRound[biggestContourIndex], smoothedMaskPoints, 2, true);
@@ -337,12 +334,12 @@ Mat CharacterAnalysis::findOuterBoxMask()
if (this->config->debugCharAnalysis) if (this->config->debugCharAnalysis)
{ {
vector<Mat> debugImgs; vector<Mat> debugImgs;
Mat debugImgMasked = Mat::zeros(thresholds[winningIndex].size(), CV_8U); Mat debugImgMasked = Mat::zeros(pipeline_data->thresholds[winningIndex].size(), CV_8U);
thresholds[winningIndex].copyTo(debugImgMasked, mask); pipeline_data->thresholds[winningIndex].copyTo(debugImgMasked, mask);
debugImgs.push_back(mask); debugImgs.push_back(mask);
debugImgs.push_back(thresholds[winningIndex]); debugImgs.push_back(pipeline_data->thresholds[winningIndex]);
debugImgs.push_back(debugImgMasked); debugImgs.push_back(debugImgMasked);
Mat dashboard = drawImageDashboard(debugImgs, CV_8U, 1); Mat dashboard = drawImageDashboard(debugImgs, CV_8U, 1);
@@ -354,7 +351,7 @@ Mat CharacterAnalysis::findOuterBoxMask()
} }
hasPlateMask = false; hasPlateMask = false;
Mat fullMask = Mat::zeros(thresholds[0].size(), CV_8U); Mat fullMask = Mat::zeros(pipeline_data->thresholds[0].size(), CV_8U);
bitwise_not(fullMask, fullMask); bitwise_not(fullMask, fullMask);
return fullMask; return fullMask;
} }

View File

@@ -54,7 +54,6 @@ class CharacterAnalysis
bool thresholdsInverted; bool thresholdsInverted;
std::vector<cv::Mat> thresholds;
std::vector<std::vector<std::vector<cv::Point> > > allContours; std::vector<std::vector<std::vector<cv::Point> > > allContours;
std::vector<std::vector<cv::Vec4i> > allHierarchy; std::vector<std::vector<cv::Vec4i> > allHierarchy;
std::vector<std::vector<bool> > charSegments; std::vector<std::vector<bool> > charSegments;

View File

@@ -43,10 +43,10 @@ CharacterRegion::CharacterRegion(PipelineData* pipeline_data)
if (this->debug && charAnalysis->linePolygon.size() > 0) if (this->debug && charAnalysis->linePolygon.size() > 0)
{ {
vector<Mat> tempDash; vector<Mat> tempDash;
for (int z = 0; z < charAnalysis->thresholds.size(); z++) for (int z = 0; z < pipeline_data->thresholds.size(); z++)
{ {
Mat tmp(charAnalysis->thresholds[z].size(), charAnalysis->thresholds[z].type()); Mat tmp(pipeline_data->thresholds[z].size(), pipeline_data->thresholds[z].type());
charAnalysis->thresholds[z].copyTo(tmp); pipeline_data->thresholds[z].copyTo(tmp);
cvtColor(tmp, tmp, CV_GRAY2BGR); cvtColor(tmp, tmp, CV_GRAY2BGR);
tempDash.push_back(tmp); tempDash.push_back(tmp);

View File

@@ -48,7 +48,7 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data)
if (this->config->debugCharSegmenter) if (this->config->debugCharSegmenter)
{ {
displayImage(config, "CharacterSegmenter Thresholds", drawImageDashboard(charAnalysis->thresholds, CV_8U, 3)); displayImage(config, "CharacterSegmenter Thresholds", drawImageDashboard(pipeline_data->thresholds, CV_8U, 3));
} }
if (this->config->debugCharSegmenter && charAnalysis->linePolygon.size() > 0) if (this->config->debugCharSegmenter && charAnalysis->linePolygon.size() > 0)
@@ -106,7 +106,7 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data)
float avgCharWidth = median(charWidths.data(), charWidths.size()); float avgCharWidth = median(charWidths.data(), charWidths.size());
float avgCharHeight = median(charHeights.data(), charHeights.size()); float avgCharHeight = median(charHeights.data(), charHeights.size());
removeSmallContours(charAnalysis->thresholds, charAnalysis->allContours, avgCharWidth, avgCharHeight); removeSmallContours(pipeline_data->thresholds, charAnalysis->allContours, avgCharWidth, avgCharHeight);
// Do the histogram analysis to figure out char regions // Do the histogram analysis to figure out char regions
@@ -118,11 +118,11 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data)
vector<Rect> allBoxes; vector<Rect> allBoxes;
for (int i = 0; i < charAnalysis->allContours.size(); i++) for (int i = 0; i < charAnalysis->allContours.size(); i++)
{ {
Mat histogramMask = Mat::zeros(charAnalysis->thresholds[i].size(), CV_8U); Mat histogramMask = Mat::zeros(pipeline_data->thresholds[i].size(), CV_8U);
fillConvexPoly(histogramMask, charAnalysis->linePolygon.data(), charAnalysis->linePolygon.size(), Scalar(255,255,255)); fillConvexPoly(histogramMask, charAnalysis->linePolygon.data(), charAnalysis->linePolygon.size(), Scalar(255,255,255));
VerticalHistogram vertHistogram(charAnalysis->thresholds[i], histogramMask); VerticalHistogram vertHistogram(pipeline_data->thresholds[i], histogramMask);
if (this->config->debugCharSegmenter) if (this->config->debugCharSegmenter)
{ {
@@ -172,16 +172,16 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data)
} }
//ColorFilter colorFilter(img, charAnalysis->getCharacterMask()); //ColorFilter colorFilter(img, charAnalysis->getCharacterMask());
vector<Rect> candidateBoxes = getBestCharBoxes(charAnalysis->thresholds[0], allBoxes, medianCharWidth); vector<Rect> candidateBoxes = getBestCharBoxes(pipeline_data->thresholds[0], allBoxes, medianCharWidth);
if (this->config->debugCharSegmenter) if (this->config->debugCharSegmenter)
{ {
// Setup the dashboard images to show the cleaning filters // Setup the dashboard images to show the cleaning filters
for (int i = 0; i < charAnalysis->thresholds.size(); i++) for (int i = 0; i < pipeline_data->thresholds.size(); i++)
{ {
Mat cleanImg = Mat::zeros(charAnalysis->thresholds[i].size(), charAnalysis->thresholds[i].type()); Mat cleanImg = Mat::zeros(pipeline_data->thresholds[i].size(), pipeline_data->thresholds[i].type());
Mat boxMask = getCharBoxMask(charAnalysis->thresholds[i], candidateBoxes); Mat boxMask = getCharBoxMask(pipeline_data->thresholds[i], candidateBoxes);
charAnalysis->thresholds[i].copyTo(cleanImg); pipeline_data->thresholds[i].copyTo(cleanImg);
bitwise_and(cleanImg, boxMask, cleanImg); bitwise_and(cleanImg, boxMask, cleanImg);
cvtColor(cleanImg, cleanImg, CV_GRAY2BGR); cvtColor(cleanImg, cleanImg, CV_GRAY2BGR);
@@ -193,19 +193,19 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data)
getTime(&startTime); getTime(&startTime);
filterEdgeBoxes(charAnalysis->thresholds, candidateBoxes, medianCharWidth, avgCharHeight); filterEdgeBoxes(pipeline_data->thresholds, candidateBoxes, medianCharWidth, avgCharHeight);
candidateBoxes = filterMostlyEmptyBoxes(charAnalysis->thresholds, candidateBoxes); candidateBoxes = filterMostlyEmptyBoxes(pipeline_data->thresholds, candidateBoxes);
candidateBoxes = combineCloseBoxes(candidateBoxes, medianCharWidth); candidateBoxes = combineCloseBoxes(candidateBoxes, medianCharWidth);
cleanCharRegions(charAnalysis->thresholds, candidateBoxes); cleanCharRegions(pipeline_data->thresholds, candidateBoxes);
cleanMostlyFullBoxes(charAnalysis->thresholds, candidateBoxes); cleanMostlyFullBoxes(pipeline_data->thresholds, candidateBoxes);
//cleanBasedOnColor(thresholds, colorFilter.colorMask, candidateBoxes); //cleanBasedOnColor(thresholds, colorFilter.colorMask, candidateBoxes);
candidateBoxes = filterMostlyEmptyBoxes(charAnalysis->thresholds, candidateBoxes); candidateBoxes = filterMostlyEmptyBoxes(pipeline_data->thresholds, candidateBoxes);
this->characters = candidateBoxes; pipeline_data->charRegions = candidateBoxes;
if (config->debugTiming) if (config->debugTiming)
{ {
@@ -216,7 +216,7 @@ CharacterSegmenter::CharacterSegmenter(PipelineData* pipeline_data)
if (this->config->debugCharSegmenter) if (this->config->debugCharSegmenter)
{ {
Mat imgDash = drawImageDashboard(charAnalysis->thresholds, CV_8U, 3); Mat imgDash = drawImageDashboard(pipeline_data->thresholds, CV_8U, 3);
displayImage(config, "Segmentation after cleaning", imgDash); displayImage(config, "Segmentation after cleaning", imgDash);
Mat generalDash = drawImageDashboard(this->imgDbgGeneral, this->imgDbgGeneral[0].type(), 2); Mat generalDash = drawImageDashboard(this->imgDbgGeneral, this->imgDbgGeneral[0].type(), 2);
@@ -490,7 +490,7 @@ vector<Rect> CharacterSegmenter::combineCloseBoxes( vector<Rect> charBoxes, floa
newCharBoxes.push_back(bigRect); newCharBoxes.push_back(bigRect);
if (this->config->debugCharSegmenter) if (this->config->debugCharSegmenter)
{ {
for (int z = 0; z < charAnalysis->thresholds.size(); z++) for (int z = 0; z < pipeline_data->thresholds.size(); z++)
{ {
Point center(bigRect.x + bigRect.width / 2, bigRect.y + bigRect.height / 2); Point center(bigRect.x + bigRect.width / 2, bigRect.y + bigRect.height / 2);
RotatedRect rrect(center, Size2f(bigRect.width, bigRect.height + (bigRect.height / 2)), 0); RotatedRect rrect(center, Size2f(bigRect.width, bigRect.height + (bigRect.height / 2)), 0);
@@ -1140,7 +1140,4 @@ Mat CharacterSegmenter::getCharBoxMask(Mat img_threshold, vector<Rect> charBoxes
return mask; return mask;
} }
vector<Mat> CharacterSegmenter::getThresholds()
{
return charAnalysis->thresholds;
}

View File

@@ -50,7 +50,6 @@ class CharacterSegmenter
std::vector<cv::Rect> characters; std::vector<cv::Rect> characters;
int confidence; int confidence;
std::vector<cv::Mat> getThresholds();
private: private:
Config* config; Config* config;

View File

@@ -51,12 +51,12 @@ class LicensePlateCandidate
void recognize(); void recognize();
CharacterSegmenter* charSegmenter;
private: private:
PipelineData* pipeline_data; PipelineData* pipeline_data;
Config* config; Config* config;
CharacterSegmenter* charSegmenter;
cv::Mat filterByCharacterHue(std::vector<std::vector<cv::Point> > charRegionContours); cv::Mat filterByCharacterHue(std::vector<std::vector<cv::Point> > charRegionContours);
std::vector<cv::Point> findPlateCorners(cv::Mat inputImage, PlateLines plateLines, CharacterRegion charRegion); // top-left, top-right, bottom-right, bottom-left std::vector<cv::Point> findPlateCorners(cv::Mat inputImage, PlateLines plateLines, CharacterRegion charRegion); // top-left, top-right, bottom-right, bottom-left

View File

@@ -52,7 +52,7 @@ OCR::~OCR()
delete tesseract; delete tesseract;
} }
void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions) void OCR::performOCR(PipelineData* pipeline_data)
{ {
timespec startTime; timespec startTime;
getTime(&startTime); getTime(&startTime);
@@ -60,18 +60,20 @@ void OCR::performOCR(vector<Mat> thresholds, vector<Rect> charRegions)
postProcessor->clear(); postProcessor->clear();
// Don't waste time on OCR processing if it is impossible to get sufficient characters // Don't waste time on OCR processing if it is impossible to get sufficient characters
if (charRegions.size() < config->postProcessMinCharacters) if (pipeline_data->charRegions.size() < config->postProcessMinCharacters)
return; return;
for (int i = 0; i < thresholds.size(); i++) for (int i = 0; i < pipeline_data->thresholds.size(); i++)
{ {
// Make it black text on white background // Make it black text on white background
bitwise_not(thresholds[i], thresholds[i]); bitwise_not(pipeline_data->thresholds[i], pipeline_data->thresholds[i]);
tesseract->SetImage((uchar*) thresholds[i].data, thresholds[i].size().width, thresholds[i].size().height, thresholds[i].channels(), thresholds[i].step1()); tesseract->SetImage((uchar*) pipeline_data->thresholds[i].data,
pipeline_data->thresholds[i].size().width, pipeline_data->thresholds[i].size().height,
pipeline_data->thresholds[i].channels(), pipeline_data->thresholds[i].step1());
for (int j = 0; j < charRegions.size(); j++) for (int j = 0; j < pipeline_data->charRegions.size(); j++)
{ {
Rect expandedRegion = expandRect( charRegions[j], 2, 2, thresholds[i].cols, thresholds[i].rows) ; Rect expandedRegion = expandRect( pipeline_data->charRegions[j], 2, 2, pipeline_data->thresholds[i].cols, pipeline_data->thresholds[i].rows) ;
tesseract->SetRectangle(expandedRegion.x, expandedRegion.y, expandedRegion.width, expandedRegion.height); tesseract->SetRectangle(expandedRegion.x, expandedRegion.y, expandedRegion.width, expandedRegion.height);
tesseract->Recognize(NULL); tesseract->Recognize(NULL);

View File

@@ -26,6 +26,7 @@
#include "utility.h" #include "utility.h"
#include "postprocess.h" #include "postprocess.h"
#include "config.h" #include "config.h"
#include "pipeline_data.h"
#include "constants.h" #include "constants.h"
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgproc/imgproc.hpp"
@@ -39,7 +40,7 @@ class OCR
OCR(Config* config); OCR(Config* config);
virtual ~OCR(); virtual ~OCR();
void performOCR(std::vector<cv::Mat> thresholds, std::vector<cv::Rect> charRegions); void performOCR(PipelineData* pipeline_data);
PostProcess* postProcessor; PostProcess* postProcessor;
//string recognizedText; //string recognizedText;

View File

@@ -17,3 +17,12 @@ PipelineData::PipelineData(Mat colorImage, Rect regionOfInterest, Config* config
PipelineData::~PipelineData() PipelineData::~PipelineData()
{ {
} }
void PipelineData::clearThresholds()
{
for (int i = 0; i < thresholds.size(); i++)
{
thresholds[i].release();
}
thresholds.clear();
}

View File

@@ -13,6 +13,8 @@ class PipelineData
PipelineData(cv::Mat colorImage, cv::Rect regionOfInterest, Config* config); PipelineData(cv::Mat colorImage, cv::Rect regionOfInterest, Config* config);
virtual ~PipelineData(); virtual ~PipelineData();
void clearThresholds();
// Inputs // Inputs
Config* config; Config* config;
@@ -35,6 +37,7 @@ class PipelineData
float overall_confidence; float overall_confidence;
std::vector<cv::Rect> charRegions;
// Plate Lines // Plate Lines
std::vector<LineSegment> horizontalLines; std::vector<LineSegment> horizontalLines;