Пример #1
0
/*
 * Copied from http://opencv-code.com/tutorials/automatic-perspective-correction-for-quadrilateral-objects/
 */
bool straighten(Mat &src, Mat &dst, unsigned int rows, unsigned int cols) {
	vector<cv::Vec4i> slines;
	vector<par_line> par_lines;
	vector<par_line> borders;
	bool new_corners = false;
	vector<Point2f> corners = find_corners(src, rows, cols);
	vector<Point2f> quad_pts;

	if( corners.size() == 4 ) {
		// Define the destination image
		dst = Mat::zeros(cols, rows, CV_8UC3);
		// Corners of the destination image
		quad_pts.push_back(Point2f(0, 0));
		quad_pts.push_back(Point2f(dst.cols, 0));
		quad_pts.push_back(Point2f(dst.cols, dst.rows));
		quad_pts.push_back(Point2f(0, dst.rows));
		// Get transformation matrix
		Mat transmtx = getPerspectiveTransform(corners, quad_pts);
		// Apply perspective transformation
		warpPerspective(src, dst, transmtx, dst.size());
		return true;
	}
	else {
		return false;
	}
}
Пример #2
0
void reset_sight()
{
	list_node *c;
	for (c = CORNERS->next; c->next != NULL; c = c->next, free(c->prev)) {
		if (((line_point *) c->data) != NULL) {
			free((line_point *) c->data);
		}
	}
	CORNERS = make_list();
	memset(RAYS, 0, sizeof(RAYS));
	RAY_INDEX = 0;
	find_corners();
}
Пример #3
0
	int find(cv::Mat src, unsigned thresh,std::vector<cv::Point2f>& corners){
  		cv::Mat src_gray;
  		cv::cvtColor( src, src_gray, CV_RGB2GRAY );
  		cv::GaussianBlur(src_gray,src_gray,cv::Size(3,3),0);


		std::vector<std::vector<cv::Point> > contours;
		std::vector<cv::Vec4i> lines;
		cv::Mat canny_output;

		cv::Canny( src_gray, canny_output, thresh, thresh*3, 3 );
		cv::findContours(
		    canny_output, 
		    contours, 
		    CV_RETR_EXTERNAL, 
		    CV_CHAIN_APPROX_SIMPLE);
		  
		std::vector<cv::Point> approx;
		cv::Scalar color(0,0,255);
		
		for (int i = 0; i < contours.size(); i++){
			// Approximate contour with accuracy proportional
			// to the contour perimeter
			cv::approxPolyDP(
			    cv::Mat(contours[i]), 
			    approx, 
			    cv::arcLength(cv::Mat(contours[i]), true) * 0.02, 
			    true);
			    
			// Skip small or non-convex objects 
			if (std::fabs(cv::contourArea(contours[i])) < 200 || !cv::isContourConvex(approx))
			    continue;

			cv::Mat drawing = cv::Mat::zeros( src.size(), CV_8UC3 );
			if (approx.size()==4){
				//cv::Rect r = cv::boundingRect(approx); // описанный квадрат
				//rectangle(drawing,r.tl(),r.br(),color,2,8,0); 
				cv::drawContours(drawing,contours,i,cv::Scalar(255,255,255));
				//FIX MEE!!!!!!!!!!!!!
				return find_corners(drawing, thresh, corners);
			}
		}
  		return -1;
	}	
Пример #4
0
int main(int argc, char* argv[]) {
  if (argc != 2) {
    return usage(argv[0]);
    return 1;
  }

  graymap_t* graymap = alloc_graymap_from_pgm(argv[1]);
  if (!graymap) {
    fprintf(stderr, "Failed to load %s\n", argv[1]);
    return 1;
  }
  
  // http://sudokugrab.blogspot.com/2009/07/how-does-it-all-work.html
  threshold_pixels(graymap);
  save_graymap_to_pgm("1_thresh.pgm", graymap);
  // TODO: Maybe run a few open iterations to clean up noise pixels?
  find_biggest_connected_component(graymap);
  save_graymap_to_pgm("2_component.pgm", graymap);

  float projected_corners[4][2];
  if (!find_corners(graymap, projected_corners)) {
    fprintf(stderr, "Failed to find corners\n");
    return 1;
  }

  for (int i = 0; i < 4; ++i) {
    const int k = 11;
    for (int y = projected_corners[i][1] - k/2;
         y <= projected_corners[i][1] + k/2;
         ++y) {
      for (int x = projected_corners[i][0] - k/2;
           x <= projected_corners[i][0] + k/2;
           ++x) {
        if (x >= 0 && x < graymap->w && y >= 0 && y < graymap->h)
          graymap->data[y*graymap->w + x] = 128 + 30 * i;
      }
    }
  }

  save_graymap_to_pgm("3_corners.pgm", graymap);

  free_graymap(graymap);

  const int kTileSize = 16;
  const int kSudokuWidth = kTileSize * 9;
  const int kSudokuHeight = kTileSize * 9;
  float unprojected_corners[4][2] = {
    { 0, 0 },
    { kSudokuWidth - 1 , 0 },
    { 0, kSudokuHeight - 1 },
    { kSudokuWidth - 1, kSudokuHeight - 1 },
  };
  float projmat[3][3];
  compute_projection_matrix(projmat, unprojected_corners, projected_corners);

  graymap_t* orig = alloc_graymap_from_pgm(argv[1]);
  graymap_t* sudoku = alloc_graymap(kSudokuWidth, kSudokuHeight);
  for (int y = 0; y < kSudokuHeight; ++y) {
    for (int x = 0; x < kSudokuWidth; ++x) {
      float p[3] = {
        projmat[0][0]*x + projmat[0][1]*y + projmat[0][2],
        projmat[1][0]*x + projmat[1][1]*y + projmat[1][2],
        projmat[2][0]*x + projmat[2][1]*y + projmat[2][2],
      };
      float sx = p[0] / p[2];
      float sy = p[1] / p[2];
      int ix = (int)sx;
      int iy = (int)sy;

      // XXX nicer sampling?
#if 1
      sx -= ix;
      sy -= iy;
      int ix2 = ix < orig->w-1 ? ix + 1 : ix;
      int iy2 = iy < orig->h-1 ? iy + 1 : iy;
      float p1 = lerp(sx, orig->data[iy*graymap->w + ix],
                          orig->data[iy*graymap->w + ix2]);
      float p2 = lerp(sx, orig->data[iy2*graymap->w + ix],
                          orig->data[iy2*graymap->w + ix2]);
      float p3 = lerp(sy, p1, p2);

      sudoku->data[y * kSudokuWidth + x] = p3 + 0.5;
#else
      sudoku->data[y * kSudokuWidth + x] = orig->data[iy*graymap->w + ix];
#endif
    }
  }
  free_graymap(orig);

  save_graymap_to_pgm("4_sudoku.pgm", sudoku);

  threshold_pixels(sudoku);
  save_graymap_to_pgm("5_thresh.pgm", sudoku);

  graymap_t* tile = alloc_graymap(kTileSize, kTileSize);
  for (int r = 0; r < 9; ++r) {
    for (int c = 0; c < 9; ++c) {
      // XXX give graymap a stride? Then this copying isn't needed.
      for (int y = 0; y < tile->h; ++y)
        for (int x = 0; x < tile->w; ++x) {
          tile->data[y*tile->w + x] =
              sudoku->data[(y + r*kTileSize)*sudoku->w + (x + c*kTileSize)];
        }

      // Clean 2px wide border.
      memset(tile->data, 255, 2*kTileSize);
      memset(&tile->data[14 * kTileSize], 255, 2*kTileSize);
      for (int i = 2; i < 14; ++i) {
        tile->data[i*kTileSize + 0]  = 255;
        tile->data[i*kTileSize + 1]  = 255;
        tile->data[i*kTileSize + 14] = 255;
        tile->data[i*kTileSize + 15] = 255;
      }

      for (int y = 0; y < tile->h; ++y)
        for (int x = 0; x < tile->w; ++x) {
          sudoku->data[(y + r*kTileSize)*sudoku->w + (x + c*kTileSize)] =
              tile->data[y*tile->w + x];
        }
    }
  }
  free_graymap(tile);
  save_graymap_to_pgm("6_comp.pgm", sudoku);

  free_graymap(sudoku);
}