Beispiel #1
0
  Mat TextContours::drawDebugImage(Mat baseImage) {
      Mat img_contours(baseImage.size(), CV_8U);
      baseImage.copyTo(img_contours);

      cvtColor(img_contours, img_contours, CV_GRAY2RGB);

      vector<vector<Point> > allowedContours;
      for (unsigned int i = 0; i < this->contours.size(); i++)
      {
        if (this->goodIndices[i])
          allowedContours.push_back(this->contours[i]);
      }

      drawContours(img_contours, this->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


      return img_contours;
  }
CharacterSegmenter::CharacterSegmenter(Mat img, bool invertedColors, Config* config)
{

  this->config = config;
  
  this->confidence = 0;
 
  if (this->config->debugCharSegmenter)
    cout << "Starting CharacterSegmenter" << endl;
  
  //CharacterRegion charRegion(img, debug);
  
  timespec startTime;
  getTime(&startTime);

  
  Mat img_gray(img.size(), CV_8U);
  cvtColor( img, img_gray, CV_BGR2GRAY );
  //normalize(img_gray, img_gray, 0, 255, CV_MINMAX );
  medianBlur(img_gray, img_gray, 3);
  
  if (invertedColors)
    bitwise_not(img_gray, img_gray);
  
  
  charAnalysis = new CharacterAnalysis(img_gray, config);
  charAnalysis->analyze();
  
  
  
  if (this->config->debugCharSegmenter)
  {
      displayImage(config, "CharacterSegmenter  Thresholds", drawImageDashboard(charAnalysis->thresholds, CV_8U, 3));
  }
  

  
  
  

  if (this->config->debugCharSegmenter)
  {
      
    Mat img_contours(charAnalysis->bestThreshold.size(), CV_8U);
    charAnalysis->bestThreshold.copyTo(img_contours);
    cvtColor(img_contours, img_contours, CV_GRAY2RGB);
    
    vector<vector<Point> > allowedContours;
    for (int i = 0; i < charAnalysis->bestContours.size(); i++)
    {
	if (charAnalysis->bestCharSegments[i])
	  allowedContours.push_back(charAnalysis->bestContours[i]);
    }
    
    drawContours(img_contours, charAnalysis->bestContours,
	    -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
    
    if (charAnalysis->linePolygon.size() > 0)
    {
      line(img_contours, charAnalysis->linePolygon[0], charAnalysis->linePolygon[1], Scalar(255, 0, 255), 1);
      line(img_contours, charAnalysis->linePolygon[3], charAnalysis->linePolygon[2], Scalar(255, 0, 255), 1);
    }
    
    Mat bordered = addLabel(img_contours, "Best Contours");
    imgDbgGeneral.push_back(bordered);
  }
  
  // Figure out the average character width
  float totalCharWidth = 0;
  float totalCharHeight = 0;
  
  if (charAnalysis->linePolygon.size() > 0)
  {
    this->top = LineSegment(charAnalysis->linePolygon[0].x, charAnalysis->linePolygon[0].y, charAnalysis->linePolygon[1].x, charAnalysis->linePolygon[1].y);
    this->bottom = LineSegment(charAnalysis->linePolygon[3].x, charAnalysis->linePolygon[3].y, charAnalysis->linePolygon[2].x, charAnalysis->linePolygon[2].y);
    
    for (int i = 0; i < charAnalysis->bestContours.size(); i++)
    {
	if (charAnalysis->bestCharSegments[i] == false)
	  continue;
	
	Rect mr = boundingRect(charAnalysis->bestContours[i]);
	totalCharWidth += mr.width;
	totalCharHeight += mr.height;
    }
    
    int numSamples = charAnalysis->bestCharSegmentsCount;
    float avgCharWidth = totalCharWidth / numSamples;
    float avgCharHeight = totalCharHeight / numSamples;
  
    removeSmallContours(charAnalysis->thresholds, charAnalysis->allContours, avgCharWidth, avgCharHeight);
  
    // Do the histogram analysis to figure out char regions
    
    
    timespec startTime;
    getTime(&startTime);

    
    vector<Mat> allHistograms;
    
    vector<Rect> allBoxes;
    for (int i = 0; i < charAnalysis->allContours.size(); i++)
    {


      Mat histogramMask = Mat::zeros(charAnalysis->thresholds[i].size(), CV_8U);

      fillConvexPoly(histogramMask, charAnalysis->linePolygon.data(), charAnalysis->linePolygon.size(), Scalar(255,255,255));
      
      
      VerticalHistogram vertHistogram(charAnalysis->thresholds[i], histogramMask);
      

      if (this->config->debugCharSegmenter)
      {
	Mat histoCopy(vertHistogram.debugImg.size(), vertHistogram.debugImg.type());
	//vertHistogram.copyTo(histoCopy);
	cvtColor(vertHistogram.debugImg, histoCopy, CV_GRAY2RGB);
	allHistograms.push_back(histoCopy);
      }

//       
      float score = 0;
      vector<Rect> charBoxes = getHistogramBoxes(vertHistogram.debugImg, avgCharWidth, avgCharHeight, &score); 
      
      
      if (this->config->debugCharSegmenter)
      {
	for (int cboxIdx = 0; cboxIdx < charBoxes.size(); cboxIdx++)
	{
	    rectangle(allHistograms[i], charBoxes[cboxIdx], Scalar(0, 255, 0));
	}
	
	Mat histDashboard = drawImageDashboard(allHistograms, allHistograms[0].type(), 3);
	displayImage(config, "Char seg histograms", histDashboard);
      }
      
      for (int z = 0; z < charBoxes.size(); z++)
	allBoxes.push_back(charBoxes[z]);
      //drawAndWait(&histogramMask);
    }
    

    float biggestCharWidth = avgCharWidth;
    // Compute largest char width
    for (int i = 0; i < allBoxes.size(); i++)
    {
      if (allBoxes[i].width > biggestCharWidth)
	biggestCharWidth = allBoxes[i].width;
    }
      

    if (config->debugTiming)
    {
      timespec endTime;
      getTime(&endTime);
      cout << "  -- Character Segmentation Create and Score Histograms Time: " << diffclock(startTime, endTime) << "ms." << endl;
    }
    
    //ColorFilter colorFilter(img, charAnalysis->getCharacterMask());    
    vector<Rect> candidateBoxes = getBestCharBoxes(charAnalysis->thresholds[0], allBoxes, biggestCharWidth);
    
    
    if (this->config->debugCharSegmenter)
    {
	// Setup the dashboard images to show the cleaning filters
      for (int i = 0; i < charAnalysis->thresholds.size(); i++)
      {
	Mat cleanImg = Mat::zeros(charAnalysis->thresholds[i].size(), charAnalysis->thresholds[i].type());
	Mat boxMask = getCharBoxMask(charAnalysis->thresholds[i], candidateBoxes);
	charAnalysis->thresholds[i].copyTo(cleanImg);
	bitwise_and(cleanImg, boxMask, cleanImg);
	cvtColor(cleanImg, cleanImg, CV_GRAY2BGR);
	
	for (int c = 0; c < candidateBoxes.size(); c++)
	  rectangle(cleanImg, candidateBoxes[c], Scalar(0, 255, 0), 1);
	imgDbgCleanStages.push_back(cleanImg);
      }
    }
    
    
    getTime(&startTime);
    
    filterEdgeBoxes(charAnalysis->thresholds, candidateBoxes, biggestCharWidth, avgCharHeight);
    
    candidateBoxes = filterMostlyEmptyBoxes(charAnalysis->thresholds, candidateBoxes);
 
    candidateBoxes = combineCloseBoxes(candidateBoxes, biggestCharWidth);

    cleanCharRegions(charAnalysis->thresholds, candidateBoxes);
    cleanMostlyFullBoxes(charAnalysis->thresholds, candidateBoxes);
    
    //cleanBasedOnColor(thresholds, colorFilter.colorMask, candidateBoxes);
    
    candidateBoxes = filterMostlyEmptyBoxes(charAnalysis->thresholds, candidateBoxes);
    this->characters = candidateBoxes;
    
    if (config->debugTiming)
    {
      timespec endTime;
      getTime(&endTime);
      cout << "  -- Character Segmentation Box cleaning/filtering Time: " << diffclock(startTime, endTime) << "ms." << endl;
    }
    
    if (this->config->debugCharSegmenter)
    {
      
      
      Mat imgDash = drawImageDashboard(charAnalysis->thresholds, CV_8U, 3);
      displayImage(config, "Segmentation after cleaning", imgDash);
      
      Mat generalDash = drawImageDashboard(this->imgDbgGeneral, this->imgDbgGeneral[0].type(), 2);
      displayImage(config, "Segmentation General", generalDash);
      
      Mat cleanImgDash = drawImageDashboard(this->imgDbgCleanStages, this->imgDbgCleanStages[0].type(), 3);
      displayImage(config, "Segmentation Clean Filters", cleanImgDash);
    }
  }
  
  
  
  
  
  
  if (config->debugTiming)
  {
    timespec endTime;
    getTime(&endTime);
    cout << "Character Segmenter Time: " << diffclock(startTime, endTime) << "ms." << endl;
  }
}
Beispiel #3
0
 void CvScan::charsSegement( IplImage *src, vector<Mat> &vector){
     
     if (src == NULL) {
         return;
     }
     
     IplImage *pimg = cvCreateImage(cvSize(src->width*1.1, src->height*1.1), src->depth, src->nChannels);
     /*
     int m_otsu = otsu(pimg);
     printf("m_otsu:%d\n",m_otsu);
     cvReleaseImage(&pimg);
     pimg = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
     cvThreshold(src, pimg, m_otsu, 255, CV_THRESH_BINARY);
     //cvZero(pimg);
     //*/
     
     //IplImage imgHSV = *cvCreateImage(cvGetSize(pimg), 8, 1);
     //cv::Mat matImg(&imgHSV,true);
     
     cv::Mat img_contours(pimg->width,pimg->height,CV_8UC1,Scalar::all(0));
     img_contours.data = (uchar *)pimg->imageData;
     
     
     std::vector< std::vector< CvPoint> > contours;
     
     findContours(img_contours,
                  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
     std::vector<std::vector<CvPoint>>::iterator itc = contours.begin();
     std::vector<CvRect> vecRect;
     
     //Remove patch that are no inside limits of aspect ratio and area.
     //将不符合特定尺寸的图块排除出去
     while (itc != contours.end()){
         Rect mr = boundingRect(cv::Mat(*itc));
         cv::Mat auxRoi(img_contours, mr);
         if (verifyMatCharSizes(auxRoi))
             vecRect.push_back(mr);
         
         ++itc;
     }
     
     if (vecRect.size() == 0)
         return ;
     std::vector<CvRect> sortedRect;
     ////对符合尺寸的图块按照从左到右进行排序
     sortRect(vecRect, sortedRect);
     
     for (int i = 0; i < sortedRect.size(); i++){
         CvRect mr = sortedRect[i];
         cv::Mat auxRoi(img_contours, mr);
         
         auxRoi = preprocessChar(auxRoi);
         vector.push_back(auxRoi);
     }
     
     /* 另一个方法
     
     //*/
     return ;
 }
Beispiel #4
0
void CharacterAnalysis::analyze()
{


    thresholds = produceThresholds(img_gray, config);


    /*
      // Morph Close the gray image to make it easier to detect blobs
      int morph_elem  = 1;
      int morph_size = 1;
      Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );

      for (int i = 0; i < thresholds.size(); i++)
      {
        //morphologyEx( mask, mask, MORPH_CLOSE, element );
        morphologyEx( thresholds[i], thresholds[i], MORPH_OPEN, element );
        //dilate( thresholds[i], thresholds[i],  element );

      }
    */


    timespec startTime;
    getTime(&startTime);


    for (int i = 0; i < thresholds.size(); i++)
    {
        vector<vector<Point> > contours;
        vector<Vec4i> hierarchy;

        Mat tempThreshold(thresholds[i].size(), CV_8U);
        thresholds[i].copyTo(tempThreshold);
        findContours(tempThreshold,
                     contours, // a vector of contours
                     hierarchy,
                     CV_RETR_TREE, // retrieve all contours
                     CV_CHAIN_APPROX_SIMPLE ); // all pixels of each contours

        allContours.push_back(contours);
        allHierarchy.push_back(hierarchy);
    }




    if (config->debugTiming)
    {
        timespec endTime;
        getTime(&endTime);
        cout << "  -- Character Analysis Find Contours Time: " << diffclock(startTime, endTime) << "ms." << endl;
    }
    //Mat img_equalized = equalizeBrightness(img_gray);


    getTime(&startTime);

    for (int i = 0; i < thresholds.size(); i++)
    {
        vector<bool> goodIndices = this->filter(thresholds[i], allContours[i], allHierarchy[i]);
        charSegments.push_back(goodIndices);

        if (config->debugCharAnalysis)
            cout << "Threshold " << i << " had " << getGoodIndicesCount(goodIndices) << " good indices." << endl;
    }

    if (config->debugTiming)
    {
        timespec endTime;
        getTime(&endTime);
        cout << "  -- Character Analysis Filter Time: " << diffclock(startTime, endTime) << "ms." << endl;
    }



    this->plateMask = findOuterBoxMask();

    if (hasPlateMask)
    {
        // Filter out bad contours now that we have an outer box mask...
        for (int i = 0; i < thresholds.size(); i++)
        {
            charSegments[i] = filterByOuterMask(allContours[i], allHierarchy[i], charSegments[i]);
        }
    }


    int bestFitScore = -1;
    int bestFitIndex = -1;
    for (int i = 0; i < thresholds.size(); i++)
    {

        //vector<bool> goodIndices = this->filter(thresholds[i], allContours[i], allHierarchy[i]);
        //charSegments.push_back(goodIndices);

        int segmentCount = getGoodIndicesCount(charSegments[i]);


        if (segmentCount > bestFitScore)
        {
            bestFitScore = segmentCount;
            bestFitIndex = i;
            bestCharSegments = charSegments[i];
            bestThreshold = thresholds[i];
            bestContours = allContours[i];
            bestHierarchy = allHierarchy[i];
            bestCharSegmentsCount = segmentCount;
        }
    }

    if (this->config->debugCharAnalysis)
        cout << "Best fit score: " << bestFitScore << " Index: " << bestFitIndex << endl;


    if (bestFitScore <= 1)
        return;


    //getColorMask(img, allContours, allHierarchy, charSegments);

    if (this->config->debugCharAnalysis)
    {

        Mat img_contours(bestThreshold.size(), CV_8U);
        bestThreshold.copyTo(img_contours);
        cvtColor(img_contours, img_contours, CV_GRAY2RGB);

        vector<vector<Point> > allowedContours;
        for (int i = 0; i < bestContours.size(); i++)
        {
            if (bestCharSegments[i])
                allowedContours.push_back(bestContours[i]);
        }

        drawContours(img_contours, bestContours,
                     -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


        displayImage(config, "Matching Contours", img_contours);
    }


    //charsegments = this->getPossibleCharRegions(img_threshold, allContours, allHierarchy, STARTING_MIN_HEIGHT + (bestFitIndex * HEIGHT_STEP), STARTING_MAX_HEIGHT + (bestFitIndex * HEIGHT_STEP));



    this->linePolygon =  getBestVotedLines(img_gray, bestContours, bestCharSegments);

    if (this->linePolygon.size() > 0)
    {
        this->topLine = LineSegment(this->linePolygon[0].x, this->linePolygon[0].y, this->linePolygon[1].x, this->linePolygon[1].y);
        this->bottomLine = LineSegment(this->linePolygon[3].x, this->linePolygon[3].y, this->linePolygon[2].x, this->linePolygon[2].y);
        //this->charArea = getCharSegmentsBetweenLines(bestThreshold, bestContours, this->linePolygon);
        filterBetweenLines(bestThreshold, bestContours, bestHierarchy, linePolygon, bestCharSegments);

        this->charArea = getCharArea();

        if (this->charArea.size() > 0)
        {
            this->charBoxTop = LineSegment(this->charArea[0].x, this->charArea[0].y, this->charArea[1].x, this->charArea[1].y);
            this->charBoxBottom = LineSegment(this->charArea[3].x, this->charArea[3].y, this->charArea[2].x, this->charArea[2].y);
            this->charBoxLeft = LineSegment(this->charArea[3].x, this->charArea[3].y, this->charArea[0].x, this->charArea[0].y);
            this->charBoxRight = LineSegment(this->charArea[2].x, this->charArea[2].y, this->charArea[1].x, this->charArea[1].y);


        }
    }

    this->thresholdsInverted = isPlateInverted();



}