本文介绍了自动透视校正OpenCV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我试图在我的iOS程序中实现自动透视校正,当我使用测试图像我发现在教程一切正常工作。但是当我拍照时,我会得到一个奇怪的结果。 我使用的是,这里你应该得到4点,它代表你的卡的角落。您可以调整参数 epsilon 来创建4个坐标。 img src =http://i.stack.imgur.com/xWhaP.jpgalt =enter image description here> 计算坐标目标图像中相应的四边形顶点 通过计算最大轮廓的边界矩形可以很容易地找出。 li> 在下图中,红色矩形表示源点,绿色表示目标点。 调整坐标顺序和应用透视变换 这里我手动调整坐标顺序,可以使用一些排序算法。 然后计算转换矩阵,并应用 wrapPrespective 查看最终结果 代码 Mat src = imread(card.jpg); Mat thr; cvtColor(src,thr,CV_BGR2GRAY); threshold(thr,thr,70,255,CV_THRESH_BINARY); vector<向量< Point> >轮廓; //用于存储轮廓的向量向量< Vec4i>层次; 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(),contour,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE); //查找图像中的轮廓 for(int i = 0; i double a = contourArea(contoururs [i],false); //找到轮廓的区域 if(a> largest_area){ highest_area = a; largest_contour_index = i; //存储最大轮廓的索引} } drawContours(dst,contours,largest_contour_index,Scalar(255,255,255),CV_FILLED,8, vector< vector< Point> > contours_poly(1); approxPolyDP(Mat(contours [largest_contour_index]),contours_poly [0],5,true); Rect boundRect = boundingRect(contoururs [largest_contour_index]); if(contours_poly [0] .size()== 4){ std :: vector< Point2f> quad_pts; std :: vector< Point2f> squre_pts; quad_pts.push_back(Point2f(contoururs_poly [0] [0] .x,contours_poly [0] [0] .y)); quad_pts.push_back(Point2f(contoururs_poly [0] [1] .x,contours_poly [0] [1] .y)); quad_pts.push_back(Point2f(contoururs_poly [0] [3] .x,contours_poly [0] [3] .y)); quad_pts.push_back(Point2f(contoururs_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 = contoururs_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(converted,boundRect,Scalar(0,255,0),1,8,0); imshow(quadrilateral,transformed); imshow(thr,thr); $ b $ p imshow(dst,dst); imshow(src,src); imwrite(result1.jpg,dst); imwrite(result2.jpg,src); imwrite(result3.jpg,transformed); waitKey(); } else cout<<确保你使用approxPolyDP ...获得4角<< endl; I am trying to implement Automatic perspective correction in my iOS program and when I use the test image I found on the tutorial everything works as expected. But when I take a picture I get back a weird result.I am using code found in this tutorialWhen I give it an image that looks like this:I get this as the result:Here is what dst gives me that might help.I am using this to call the method which contains the code.quadSegmentation(Img, bw, dst, quad);Can anyone tell me when I am getting so many green lines compared to the tutorial? And how I might be able to fix this and properly crop the image to only contain the card? 解决方案 For perspective transform you need,source points->Coordinates of quadrangle vertices in the source image.destination points-> Coordinates of the corresponding quadrangle vertices in the destination image.Here we will calculate these point by contour process.Calculate Coordinates of quadrangle vertices in the source imageYou will get the your card as contour by just by blurring, thresholding, then find contour, find largest contour etc..After finding largest contour just calculate approximates a polygonal curve, here you should get 4 Point which represent corners of your card. You can adjust the parameter epsilon to make 4 co-ordinates.Calculate Coordinates of the corresponding quadrangle vertices in the destination imageThis can be easily find out by calculating bounding rectangle for largest contour.In below image the red rectangle represent source points and green for destination points.Adjust the co-ordinates order and Apply Perspective transformHere I manually adjust the co-ordinates order and you can use some sorting algorithm.Then calculate transformation matrix and apply wrapPrespectiveSee the final resultCode 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; 这篇关于自动透视校正OpenCV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-26 00:25