c/c++语言开发共享C++ OpenCV实战之图像透视矫正

目录前言一、图像预处理二、轮廓提取1.提取最外轮廓2.提取矩形四个角点3.将矩形角点排序三、透视矫正四、源码前言本文将使用opencv c++ 进行图像透视矫正。一、图像预处理原图如图所示。首先进行图

目录
  • 前言
  • 一、图像预处理
  • 二、轮廓提取
    • 1.提取最外轮廓
    • 2.提取矩形四个角点
    • 3.将矩形角点排序
  • 三、透视矫正
    • 四、源码

      前言

      c/c++开发分享C++ OpenCV实战之图像透视矫正将使用opencv c++ 进行图像透视矫正。

      一、图像预处理

      C++ OpenCV实战之图像透视矫正

      原图如图所示。首先进行图像预处理。将图像进行灰度、滤波、二值化、形态学等操作,目的是为了下面的轮廓提取。在这里我还使用了形态学开、闭操作,目的是使整个二值图像连在一起。大家在做图像预处理时,可以根据图像特征自行处理。

      	mat gray;  	cvtcolor(src, gray, color_bgr2gray);    	mat gaussian;  	gaussianblur(gray, gaussian, size(3, 3), 0);    	mat thresh;  	threshold(gaussian, thresh, 0, 255, thresh_binary_inv | thresh_otsu);    	mat kernel = getstructuringelement(morph_rect, size(3, 3));  	mat open;  	morphologyex(thresh, open, morph_open, kernel);    	mat kernel1 = getstructuringelement(morph_rect, size(7, 7));  	mat close;  	morphologyex(open, close, morph_close, kernel1);  

      C++ OpenCV实战之图像透视矫正

      如图就是经过图像预处理得到的二值图像。

      二、轮廓提取

      1.提取最外轮廓

      	vector<vector<point>>contours;	  	findcontours(close, contours, retr_external, chain_approx_simple);  

      使用findcontours、retr_external就可以提取出物体最外轮廓。

      2.提取矩形四个角点

      接下来将使用approxpolydp进行多边形轮廓拟合,目的是为了找到矩形的四个角点。关于approxpolydp api大家可以自行百度查看其用法。

      	vector<vector<point>>conpoly(contours.size());  	vector<point>srcpts;    	for (int i = 0; i < contours.size(); i++)  	{  		double area = contourarea(contours[i]);    		if (area > 10000)  		{  			double peri = arclength(contours[i], true);    			approxpolydp(contours[i], conpoly[i], 0.02*peri, true);               //获取矩形四个角点  			srcpts = { conpoly[i][0],conpoly[i][1],conpoly[i][2],conpoly[i][3] };    		}    	}  

      3.将矩形角点排序

      由于我们之前使用的approxpolydp获取的角点是无序的,所以我们得确定各角点所在的位置。在这里我使用的算法是根据其角点所在图像位置特征确定左上、左下、右下、右上四个点。

      	int width = src.cols / 2;  	int height = src.rows / 2;  	int t_l, t_r, b_r, b_l;    	for (int i = 0; i < srcpts.size(); i++)  	{  		if (srcpts[i].x < width && srcpts[i].y < height)  		{  			t_l = i;  		}  		if (srcpts[i].x > width && srcpts[i].y < height)  		{  			t_r = i;  		}  		if (srcpts[i].x > width && srcpts[i].y > height)  		{  			b_r = i;  		}  		if (srcpts[i].x < width && srcpts[i].y > height)  		{  			b_l = i;  		}  		  	}  

      C++&nbsp;OpenCV实战之图像透视矫正

      如图所示。至此已经完成了矩形四个角点的定位。接下来就可以使用透视变换进行图像矫正了。

      三、透视矫正

      在这里我们需要知道透视变换一个原理:

      变换后,图像的长和宽应该变为:

      长 = max(变换前左边长,变换前右边长)

      宽 = max(变换前上边长,变换前下边长)

      设变换后图像的左上角位置为原点位置。

      	double leftheight = eudis(srcpts[t_l], srcpts[b_l])	  	double rightheight = eudis(srcpts[t_r], srcpts[b_r]);  	double maxheight = max(leftheight, rightheight);    	double upwidth = eudis(srcpts[t_l], srcpts[t_r]);  	double downwidth = eudis(srcpts[b_l], srcpts[b_r]);  	double maxwidth = max(upwidth, downwidth);  

      确定变换后的长宽之后,就可以使用getperspectivetransform、warpperspective进行透视矫正了。

      //这里使用的顺序是左上、右上、右下、左下顺时针顺序。srcaffinepts、dstaffinepts要一一对应  	point2f srcaffinepts[4] = { point2f(srcpts[t_l]),point2f(srcpts[t_r]) ,point2f(srcpts[b_r]) ,point2f(srcpts[b_l]) };  	point2f dstaffinepts[4] = { point2f(0,0),point2f(maxwidth,0),point2f(maxwidth,maxheight),point2f(0,maxheight) };    	mat m = getperspectivetransform(srcaffinepts, dstaffinepts);  	  	mat dstimg;  	warpperspective(src, dstimg, m, point(maxwidth, maxheight));  

      C++&nbsp;OpenCV实战之图像透视矫正

      这就是进行透视矫正之后的效果。

      四、源码

      #include<iostream>  #include<opencv2/opencv.hpp>    using namespace std;  using namespace cv;    double eudis(point pt1, point pt2)  {  	return sqrt((pt2.x - pt1.x)*(pt2.x - pt1.x) + (pt2.y - pt1.y)*(pt2.y - pt1.y));  }    int main()  {    	mat src = imread("1.jpg");  	if (src.empty())  	{  		cout << "no image!" << endl;  		system("pause");  		return -1;  	}    	mat gray;  	cvtcolor(src, gray, color_bgr2gray);    	mat gaussian;  	gaussianblur(gray, gaussian, size(3, 3), 0);    	mat thresh;  	threshold(gaussian, thresh, 0, 255, thresh_binary_inv | thresh_otsu);    	mat kernel = getstructuringelement(morph_rect, size(3, 3));  	mat open;  	morphologyex(thresh, open, morph_open, kernel);    	mat kernel1 = getstructuringelement(morph_rect, size(7, 7));  	mat close;  	morphologyex(open, close, morph_close, kernel1);    	vector<vector<point>>contours;	  	findcontours(close, contours, retr_external, chain_approx_simple);    	vector<vector<point>>conpoly(contours.size());  	vector<point>srcpts;    	for (int i = 0; i < contours.size(); i++)  	{  		double area = contourarea(contours[i]);    		if (area > 10000)  		{  			double peri = arclength(contours[i], true);    			approxpolydp(contours[i], conpoly[i], 0.02*peri, true);    			srcpts = { conpoly[i][0],conpoly[i][1],conpoly[i][2],conpoly[i][3] };    		}    	}    	int width = src.cols / 2;  	int height = src.rows / 2;  	int t_l, t_r, b_r, b_l;    	for (int i = 0; i < srcpts.size(); i++)  	{  		if (srcpts[i].x < width && srcpts[i].y < height)  		{  			t_l = i;  		}  		if (srcpts[i].x > width && srcpts[i].y < height)  		{  			t_r = i;  		}  		if (srcpts[i].x > width && srcpts[i].y > height)  		{  			b_r = i;  		}  		if (srcpts[i].x < width && srcpts[i].y > height)  		{  			b_l = i;  		}  		  	}    	//circle(src, srcpts[t_l], 10, scalar(0, 0, 255), -1);  	//circle(src, srcpts[t_r], 10, scalar(0, 255, 255), -1);  	//circle(src, srcpts[b_r], 10, scalar(255, 0, 0), -1);  	//circle(src, srcpts[b_l], 10, scalar(0, 255, 0), -1);    	/*  	变换后,图像的长和宽应该变为:  	长 = max(变换前左边长,变换前右边长)  	宽 = max(变换前上边长,变换前下边长)  	设变换后图像的左上角位置为原点位置。  	*/    	double leftheight = eudis(srcpts[t_l], srcpts[b_l]);  	double rightheight = eudis(srcpts[t_r], srcpts[b_r]);  	double maxheight = max(leftheight, rightheight);    	double upwidth = eudis(srcpts[t_l], srcpts[t_r]);  	double downwidth = eudis(srcpts[b_l], srcpts[b_r]);  	double maxwidth = max(upwidth, downwidth);    	point2f srcaffinepts[4] = { point2f(srcpts[t_l]),point2f(srcpts[t_r]) ,point2f(srcpts[b_r]) ,point2f(srcpts[b_l]) };  	point2f dstaffinepts[4] = { point2f(0,0),point2f(maxwidth,0),point2f(maxwidth,maxheight),point2f(0,maxheight) };    	mat m = getperspectivetransform(srcaffinepts, dstaffinepts);    	mat dstimg;  	warpperspective(src, dstimg, m, point(maxwidth, maxheight));  	//imshow("dst", dstimg);      	imshow("src", src);  	waitkey(0);  	destroyallwindows();    	system("pause");  	return 0;  }  

      总结

      c/c++开发分享C++ OpenCV实战之图像透视矫正使用opencv c++ 进行图像透视矫正,关键步骤有以下几点。

      1、图像预处理,获取二值图像。

      2、将二值图像进行轮廓提取,定位矩形四个角点,并确定其位置。

      3、确定图像变换后的长、宽。并将srcaffinepts、dstaffinepts一一对应之后进行透视变换。

      到此这篇关于c++ opencv实战之图像透视矫正的文章就介绍到这了,更多相关c++ opencv图像透视矫正内容请搜索<计算机技术网(www.ctvol.com)!!>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<计算机技术网(www.ctvol.com)!!>!

      需要了解更多c/c++开发分享C++ OpenCV实战之图像透视矫正,都可以关注C/C++技术分享栏目—计算机技术网(www.ctvol.com)!

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/1038125.html

      (1)
      上一篇 2022年1月26日
      下一篇 2022年1月26日

      精彩推荐