如何利用C++ OpenCV 实现从投影图像恢复仿射特性,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
原理
我们通过相机拍摄的图片存在各种畸变,其中投影畸变使得原本平行的直线不再平行,就会产生照片中近大远小的效果,要校正这一畸变,书中给了很多方法,这里是其中的一种。
我们可以将投影变换拆分成相似变换、仿射变换和投影变换三部分, 如下图,
其中相似变换和仿射变换不会改变infinite line,只有投影变换会改变。因此只要找到畸变图像中的这条线,就能够恢复图像的仿射特性(相当于逆转投影变换)。而要确定这条线的位置,就得至少知道线上的两个点。我们知道,所有平行线的交点都在infinite line上面,因此,我们只需要找到图像上的两对平行线(原本是平行,图像上不再平行),求出对应的两个交点,就能找到infinite line了,如下图
进而可以图像的恢复仿射特性。
实现思路
首先我们的畸变图像如下图,
利用公式:
l = x1 × x2
可以通过x1、x2的齐次坐标求出两点连线l的齐次坐标。在图中我们找到两对平行线l1、l2和l3、l4,如下图
利用公式:
x = l1 × l2
可以通过l1、l2以及l3、l4的齐次坐标分别求出两对平行线的交点A12、A34,直线A12A34就是我们要找的infinite line。假设该直线的齐次坐标为(l1,l2,l3),那么通过矩阵:
H = ((1,0,0),(0,1,0),(l1,l2,l3))
就能够将直线(l1,l2,l3)变换成(0,0,1),即将该直线还原成为infinite line。同理我们也可以利用H矩阵,通过公式:
x = Hx'
还原投影畸变。
主要代码
代码一共需要运行两次
第一次运行的主函数:
int main() { Mat src =, imread (“distortion.jpg",, IMREAD_GRAYSCALE); IplImage * src1 =, cvLoadImage (“distortion.jpg");//第一步,通过鼠标获取图片中某个点的坐标,运行第一步时注释掉纠正(points_3d, src, src1);,将获取到的八个点写入//points_3d[8]坐标数组中,因为是齐次坐标,x3 =1 GetMouse (src1);//输入畸变图上的8个关键点 Point3d points_3d [8],=, {, Point3d (99,, 147,,,, Point3d (210,, 93,,,, Point3d (144,, 184,,,, Point3d (261,, 122,, 1), Point3d (144,, 184,,,, Point3d (99,, 147,,,, Point3d (261,, 122,,,, Point3d (210,, 93,, 1),};//第二步,校正图像,运行此步骤时注释掉GetMouse (src1);,解除注释纠正(points_3d, src, src1);//纠正(points_3d, src, src1); imshow (“yuantu", src); waitKey (0); }
其他函数:
void on_mouse (int 事件,int x,, int y, int 旗帜,void *,科大) { ,,,CvFont 字体; ,,,cvInitFont(和字体,,CV_FONT_HERSHEY_SIMPLEX,, 0.5, 0.5, 0,, 1,, CV_AA); ,,,if (event ==, CV_EVENT_LBUTTONDOWN) ,,,{ ,,,,,,,CvPoint pt =, cvPoint (x, y); ,,,,,,,char 临时[16]; ,,,,,,,sprintf (temp,,“(% d % d)“,, pt.x,, pt.y); ,,,,,,,cvPutText (src,临时,pt,,,字体,,cvScalar (255,, 255,, 255,, 0)); ,,,,,,,cvCircle (src, pt,, 2,, cvScalar (255, 0, 0, 0),, CV_FILLED,, CV_AA,, 0); ,,,,,,,cvShowImage (“src",, src); ,,,} } void GetMouse (IplImage * img) { ,,,src =, img; ,,,cvNamedWindow (“src",, 1); ,,,cvSetMouseCallback (“src",, on_mouse,, 0); ,,,cvShowImage (“src",, src); ,,,waitKey (0); }
在弹出来的图片中点击任意地方可获得改点的图像坐标(x1, x2),如下图: