前言
最近参加了大创项目,题目涉及到计算机视觉,学姐发了个修正图像的博客链接,于是打算用这个题目入门OpenCV。
分析问题
照片中的PPT区域总是沿着x,y,z三个轴都有倾斜(如下图),要想把照片翻转到平行位置,需要进行透视变换,而透视变换需要同一像素点变换前后的坐标。由此可以想到,提取矩形区域四个角的坐标作为变换前的坐标,变换后的坐标可以设为照片的四个角落,经过投影变换,矩形区域将会翻转并充满图像。
因此我们要解决的问题变为:提取矩形的四个角落、进行透视变换。
提取矩形角落坐标
矩形的检测主要是提取边缘,PPT显示部分的亮度通常高于周围环境,我们可以将图片阈值化,将PPT部分与周围环境明显的分别开来,这对后边的边缘检测非常有帮助。
检测矩形并提取坐标需要对图像进行预处理、边缘检测、提取轮廓、检测凸包、角点检测。
预处理
由于手机拍摄的照片像素可能会很高,为了加快处理速度,我们首先缩小图片,这里缩小了4倍。
pyrDown(srcPic, shrinkedPic); //减小尺寸 加快运算速度
pyrDown(shrinkedPic, shrinkedPic);
转化为灰度图
cvtColor(shrinkedPic, greyPic, COLOR_BGR2GRAY); //转化为灰度图
中值滤波
medianBlur(greyPic, greyPic, 7); //中值滤波
转为二值图片
threshold(greyPic, binPic, 80, 255, THRESH_BINARY); //阈值化为二值图片
此时图片已经变成了这个样子:
可见PPT部分已经与环境分离开来。
边缘检测与轮廓处理
进行Canny边缘检测
Canny(binPic, cannyPic, cannyThr, cannyThr*FACTOR); //Canny边缘检测
这里 cannyThr = 200, FACTOR = 2.5
可能由于边缘特征过于明显,系数在100-600范围(具体数字可能有出入,反正范围非常大)内产生的效果几乎相同。
提取轮廓
vector> contours; //储存轮廓
vector hierarchy;
findContours(cannyPic, contours,