自动透视校正OpenCV

我试图在我的iOS程序中实现自动透视校正,当我使用我在教程中find的testing图像时,一切正常。 但是当我拍摄一张照片时,我收到了一个奇怪的结果。

我正在使用本教程中的代码

当我给它看起来像这样的图像:

在这里输入图像说明

我得到这个结果:

在这里输入图像说明

这是什么dst给我可能有所帮助。

在这里输入图像说明

我正在使用这个来调用包含代码的方法。

quadSegmentation(Img, bw, dst, quad);

任何人都可以告诉我,当我得到如此多的绿线相比,教程? 而我怎么能够解决这个问题,并适当裁剪图像只包含卡?

对于你需要的透视变换,

源点 – >源图像中四边形顶点的坐标。

目标点 – >目标图像中相应四边形顶点的坐标。

这里我们将通过轮廓过程来计算这些点。

计算源图像中四边形顶点的坐标

  • 你只要通过模糊,阈值,然后find轮廓,find最大的轮廓等就可以得到你的卡。
  • find最大的轮廓后,只需计算一个近似于一个多边形曲线 ,在这里你应该得到代表你的卡angular落的4点。 您可以调整参数epsilon以创build4个坐标。

在这里输入图像说明

计算目标图像中相应四边形顶点的坐标

  • 这可以通过计算最大轮廓的边界矩形很容易find。

在这里输入图像说明

在下图中,红色矩形表示源点,绿色表示目标点。

在这里输入图像说明

调整坐标顺序和应用透视变换

  • 在这里,我手动调整坐标顺序,你可以使用一些sortingalgorithm。
  • 然后计算变换matrix并应用wrapPrespective

看最后的结果

在这里输入图像说明

  Mat src=imread("card.jpg"); Mat thr; cvtColor(src,thr,CV_BGR2GRAY); threshold( thr, thr, 70, 255,CV_THRESH_BINARY ); vector< vector <Point> > contours; // Vector for storing contour vector< Vec4i > hierarchy; int largest_contour_index=0; int largest_area=0; Mat dst(src.rows,src.cols,CV_8UC1,Scalar::all(0)); //create destination image findContours( thr.clone(), contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image for( int i = 0; i< contours.size(); i++ ){ double a=contourArea( contours[i],false); // Find the area of contour if(a>largest_area){ largest_area=a; largest_contour_index=i; //Store the index of largest contour } } drawContours( dst,contours, largest_contour_index, Scalar(255,255,255),CV_FILLED, 8, hierarchy ); vector<vector<Point> > contours_poly(1); approxPolyDP( Mat(contours[largest_contour_index]), contours_poly[0],5, true ); Rect boundRect=boundingRect(contours[largest_contour_index]); if(contours_poly[0].size()==4){ std::vector<Point2f> quad_pts; std::vector<Point2f> squre_pts; quad_pts.push_back(Point2f(contours_poly[0][0].x,contours_poly[0][0].y)); quad_pts.push_back(Point2f(contours_poly[0][1].x,contours_poly[0][1].y)); quad_pts.push_back(Point2f(contours_poly[0][3].x,contours_poly[0][3].y)); quad_pts.push_back(Point2f(contours_poly[0][2].x,contours_poly[0][2].y)); squre_pts.push_back(Point2f(boundRect.x,boundRect.y)); squre_pts.push_back(Point2f(boundRect.x,boundRect.y+boundRect.height)); squre_pts.push_back(Point2f(boundRect.x+boundRect.width,boundRect.y)); squre_pts.push_back(Point2f(boundRect.x+boundRect.width,boundRect.y+boundRect.height)); Mat transmtx = getPerspectiveTransform(quad_pts,squre_pts); Mat transformed = Mat::zeros(src.rows, src.cols, CV_8UC3); warpPerspective(src, transformed, transmtx, src.size()); Point P1=contours_poly[0][0]; Point P2=contours_poly[0][1]; Point P3=contours_poly[0][2]; Point P4=contours_poly[0][3]; line(src,P1,P2, Scalar(0,0,255),1,CV_AA,0); line(src,P2,P3, Scalar(0,0,255),1,CV_AA,0); line(src,P3,P4, Scalar(0,0,255),1,CV_AA,0); line(src,P4,P1, Scalar(0,0,255),1,CV_AA,0); rectangle(src,boundRect,Scalar(0,255,0),1,8,0); rectangle(transformed,boundRect,Scalar(0,255,0),1,8,0); imshow("quadrilateral", transformed); imshow("thr",thr); imshow("dst",dst); imshow("src",src); imwrite("result1.jpg",dst); imwrite("result2.jpg",src); imwrite("result3.jpg",transformed); waitKey(); } else cout<<"Make sure that your are getting 4 corner using approxPolyDP..."<<endl; 

teethe这通常发生在你依靠别人代码来解决你的特定问题而不是采用代码的时候。 看看处理阶段以及它们和你的图像的区别(从图像开始,确保代码的工作方式,这是一个好主意):

  1. 获取边缘地图。 – 可能会工作,因为你的边缘很好
  2. 用Hough变换检测线条。 – 失败,因为你不仅在轮廓上,而且在卡内。 所以期待很多虚惊一场的线路
  3. 通过查找线条之间的相交来获得angular点。 – 由于上述原因而失败
  4. 检查近似多边形曲线是否有4个顶点。 – 失败
  5. 确定左上angular,左下angular,右上angular和右下angular。 – 失败
  6. 应用视angular转换。 – 完全失败

要解决您的问题,您必须确保只提取外围的线。 如果你总是有一个黑暗的背景,你可以用这个事实来放弃具有其他对比度/极性的线条。 或者,您可以提取所有行,然后select最接近图像边界的行(如果您的背景没有行)。