Esempio n. 1
0
std::vector<cv::Point2f> EdgeFinder::findEdgeCorners() {

  TextLineCollection tlc(pipeline_data->textLines);
  
  vector<Point> corners;
  
  // If the character segment is especially small, just expand the existing box
  // If it's a nice, long segment, then guess the correct box based on character height/position
  if (tlc.longerSegment.length > tlc.charHeight * 3)
  {
    float charHeightToPlateWidthRatio = pipeline_data->config->plateWidthMM / pipeline_data->config->charHeightMM;
    float idealPixelWidth = tlc.charHeight *  (charHeightToPlateWidthRatio * 1.03);	// Add 3% so we don't clip any characters

    float charHeightToPlateHeightRatio = pipeline_data->config->plateHeightMM / pipeline_data->config->charHeightMM;
    float idealPixelHeight = tlc.charHeight *  charHeightToPlateHeightRatio;


    float verticalOffset = (idealPixelHeight * 1.5 / 2);
    float horizontalOffset = (idealPixelWidth * 1.25 / 2);
    LineSegment topLine = tlc.centerHorizontalLine.getParallelLine(verticalOffset);
    LineSegment bottomLine = tlc.centerHorizontalLine.getParallelLine(-1 * verticalOffset);

    LineSegment leftLine = tlc.centerVerticalLine.getParallelLine(-1 * horizontalOffset);
    LineSegment rightLine = tlc.centerVerticalLine.getParallelLine(horizontalOffset);

    Point topLeft = topLine.intersection(leftLine);
    Point topRight = topLine.intersection(rightLine);
    Point botRight = bottomLine.intersection(rightLine);
    Point botLeft = bottomLine.intersection(leftLine);

    corners.push_back(topLeft);
    corners.push_back(topRight);
    corners.push_back(botRight);
    corners.push_back(botLeft);
  }
  else
  {

    //cout << "HEYOOO!" << endl;
    int expandX = (int) ((float) pipeline_data->crop_gray.cols) * 0.15f;
    int expandY = (int) ((float) pipeline_data->crop_gray.rows) * 0.15f;
    int w = pipeline_data->crop_gray.cols;
    int h = pipeline_data->crop_gray.rows;
    
    corners.push_back(Point(-1 * expandX, -1 * expandY));
    corners.push_back(Point(expandX + w, -1 * expandY));
    corners.push_back(Point(expandX + w, expandY + h));
    corners.push_back(Point(-1 * expandX, expandY + h));
    
//    for (int i = 0; i < 4; i++)
//    {
//      std::cout << "CORNER: " << corners[i].x << " - " << corners[i].y << std::endl;
//    }
  }

  // Re-crop an image (from the original image) using the new coordinates
  Transformation imgTransform(pipeline_data->grayImg, pipeline_data->crop_gray, pipeline_data->regionOfInterest);
  vector<Point2f> remappedCorners = imgTransform.transformSmallPointsToBigImage(corners);

  Size cropSize = imgTransform.getCropSize(remappedCorners, 
          Size(pipeline_data->config->templateWidthPx, pipeline_data->config->templateHeightPx));

  Mat transmtx = imgTransform.getTransformationMatrix(remappedCorners, cropSize);
  Mat newCrop = imgTransform.crop(cropSize, transmtx);

  // Re-map the textline coordinates to the new crop  
  vector<TextLine> newLines;
  for (uint i = 0; i < pipeline_data->textLines.size(); i++)
  {        
    vector<Point2f> textArea = imgTransform.transformSmallPointsToBigImage(pipeline_data->textLines[i].textArea);
    vector<Point2f> linePolygon = imgTransform.transformSmallPointsToBigImage(pipeline_data->textLines[i].linePolygon);

    vector<Point2f> textAreaRemapped;
    vector<Point2f> linePolygonRemapped;

    textAreaRemapped = imgTransform.remapSmallPointstoCrop(textArea, transmtx);
    linePolygonRemapped = imgTransform.remapSmallPointstoCrop(linePolygon, transmtx);

    newLines.push_back(TextLine(textAreaRemapped, linePolygonRemapped));
  }

  // Find the PlateLines for this crop
  PlateLines plateLines(pipeline_data);
  plateLines.processImage(newCrop, newLines, 1.05);

  // Get the best corners
  PlateCorners cornerFinder(newCrop, &plateLines, pipeline_data, newLines);
  vector<Point> smallPlateCorners = cornerFinder.findPlateCorners();

  confidence = cornerFinder.confidence;

  // Transform the best corner points back to the original image
  std::vector<Point2f> imgArea;
  imgArea.push_back(Point2f(0, 0));
  imgArea.push_back(Point2f(newCrop.cols, 0));
  imgArea.push_back(Point2f(newCrop.cols, newCrop.rows));
  imgArea.push_back(Point2f(0, newCrop.rows));
  Mat newCropTransmtx = imgTransform.getTransformationMatrix(imgArea, remappedCorners);

  vector<Point2f> cornersInOriginalImg = imgTransform.remapSmallPointstoCrop(smallPlateCorners, newCropTransmtx);

  return cornersInOriginalImg;

}
Esempio n. 2
0
  vector<PlateLine> PlateLines::getLines(Mat edges, float sensitivityMultiplier, bool vertical)
  {
    if (this->debug)
      cout << "PlateLines::getLines" << endl;

    static int HORIZONTAL_SENSITIVITY = pipelineData->config->plateLinesSensitivityHorizontal;
    static int VERTICAL_SENSITIVITY = pipelineData->config->plateLinesSensitivityVertical;

    vector<Vec2f> allLines;
    vector<PlateLine> filteredLines;

    int sensitivity;
    if (vertical)
      sensitivity = VERTICAL_SENSITIVITY * (1.0 / sensitivityMultiplier);
    else
      sensitivity = HORIZONTAL_SENSITIVITY * (1.0 / sensitivityMultiplier);

    HoughLines( edges, allLines, 1, CV_PI/180, sensitivity, 0, 0 );

    for( size_t i = 0; i < allLines.size(); i++ )
    {
      float rho = allLines[i][0], theta = allLines[i][1];
      Point pt1, pt2;
      double a = cos(theta), b = sin(theta);
      double x0 = a*rho, y0 = b*rho;

      double angle = theta * (180 / CV_PI);
      pt1.x = cvRound(x0 + 1000*(-b));
      pt1.y = cvRound(y0 + 1000*(a));
      pt2.x = cvRound(x0 - 1000*(-b));
      pt2.y = cvRound(y0 - 1000*(a));

      if (vertical)
      {
        if (angle < 20 || angle > 340 || (angle > 160 && angle < 210))
        {
          // good vertical

          LineSegment line;
          if (pt1.y <= pt2.y)
            line = LineSegment(pt2.x, pt2.y, pt1.x, pt1.y);
          else
            line = LineSegment(pt1.x, pt1.y, pt2.x, pt2.y);

          // Get rid of the -1000, 1000 stuff.  Terminate at the edges of the image
          // Helps with debugging/rounding issues later
          LineSegment top(0, 0, edges.cols, 0);
          LineSegment bottom(0, edges.rows, edges.cols, edges.rows);
          Point p1 = line.intersection(bottom);
          Point p2 = line.intersection(top);

          PlateLine plateLine;
          plateLine.line = LineSegment(p1.x, p1.y, p2.x, p2.y);
          plateLine.confidence = (1.0 - MIN_CONFIDENCE) * ((float) (allLines.size() - i)) / ((float)allLines.size()) + MIN_CONFIDENCE;
          filteredLines.push_back(plateLine);
        }
      }
      else
      {
        if ( (angle > 70 && angle < 110) || (angle > 250 && angle < 290))
        {
          // good horizontal

          LineSegment line;
          if (pt1.x <= pt2.x)
            line = LineSegment(pt1.x, pt1.y, pt2.x, pt2.y);
          else
            line =LineSegment(pt2.x, pt2.y, pt1.x, pt1.y);

          // Get rid of the -1000, 1000 stuff.  Terminate at the edges of the image
          // Helps with debugging/ rounding issues later
          int newY1 = line.getPointAt(0);
          int newY2 = line.getPointAt(edges.cols);

          PlateLine plateLine;
          plateLine.line = LineSegment(0, newY1, edges.cols, newY2);
          plateLine.confidence = (1.0 - MIN_CONFIDENCE) * ((float) (allLines.size() - i)) / ((float)allLines.size()) + MIN_CONFIDENCE;
          filteredLines.push_back(plateLine);
        }
      }
    }

    return filteredLines;
  }