本文所采用的技术大体来源于网络上另一作者的开源项目,https://pqpo.me/2017/09/11/opencv-border-recognition/#reward,只是对其智能裁剪部分做了优化。所以本文之着重讲述优化部分,具体环境搭建则不细写了,原作者已经写的很详细了。
OpenCV 的全称是 Open Source Computer Vision Library,是一个使用 C++ 编写的跨平台的计算机视觉库,功能十分强大,在图片增强,去噪,图像检测等都有相当多的Api提供。也就是说这个库实际上就像是一个图像处理工具箱,提供了许多实用算法,而具体实现效果就在于开发者自身怎么去使用了。
本文实现效果如下:
图片边缘识别技术主要有以下几个步骤:
1.图片灰度化,将彩色图片转为灰度图
2.高斯模糊去噪
3.使用Canny算法进行边缘识别
4.将边缘识别后的图像二值化
5.提取图像边框,选组合适边框
6.对图像轮廓点进行多边形拟合
7.在多边形中选择合适点作为扫描图形的边界点
8.对结果图像使用透视技术纠正角度
正常流程是以上几个步骤,这和我在OpenCV.Android.Programming.By.Example一书中了解到的边缘识别技术也大体吻合。但是实际上对于某些特殊情况,上述算法还是表现不佳,比如在所想要裁剪的物体的颜色和图片整体颜色较为接近时,裁剪效果就不佳。此时可以在灰度图后机上一步直方图均衡操作提高图片的对比度,效果会好一些。下面一步步讲述上面一些关键步骤的作用:
步骤1-4的代码如下:
Mat Scanner::preprocessImage(Mat &image, int cannyValue, int blurValue) {
Mat grayMat;
cvtColor(image, grayMat, CV_BGR2GRAY);
if (isHisEqual){
equalizeHist(grayMat, grayMat);
}
Mat blurMat;
GaussianBlur(grayMat, blurMat, Size(blurValue, blurValue), 0);
Mat cannyMat;
Canny(blurMat, cannyMat, 50, cannyValue, 3);
Mat thresholdMat;
threshold(cannyMat, thresholdMat, 0, 255, CV_THRESH_OTSU);
return cannyMat;
}
和原先smartCropper项目代码的区别是把高斯模糊和Canny检测的参数改为动态尝试而非写死一个值了。原因是这两个参数对裁剪的效果影响比较大。不同的图像想要获得较好的效果需要的参数不同,如果这里写死参数,那么势必会导致某些图片裁剪效果不佳,因此动态参数的效果会更好。当然,这样算法所需的时间会增长。
着重介绍高斯模糊和Canny检测:
高斯模糊函数说明:
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT)
参数说明:
src:输入图片,可以是任意通道数(通道数的意思是一个像素采用多少个数值表示,比如RGB图像是三通道的,一个像素要用RGB三个数字表示),但是深度只能是CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. (深度指的是一个数字用多少位,CV_8U指的是8位无符号数)
dst:输出图片,和输入图片相同大小和深度
ksize:高斯内核大小。ksize.width和ksize.height允许不相同但是必须是正奇数。
sigmaX:高斯内核在X方向的标准偏差
sigmaY:高斯内核在Y方向的标准偏差。
borderType:用于判断图像边界的模式
在算法中主要调整的是高斯内核大小,高斯内核越大,模糊效果是越强的。也就是去噪效果越好,但是一旦模糊过度了,那图像边界也可能被模糊掉。
下面以一张图片高斯模糊内核为3和15直观感受以下高斯模糊的作用:
高斯内核为3
高斯内核为15
Canny检测:
函数原型:
void Canny(InputArray image,OutputArray edges, double threshold1, double threshold2, int apertureSize=3,bool L2gradient=false )
参数说明:
第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型。
第三个参数,double类型的threshold1,第一个滞后性阈值。
第四个参数,double类型的threshold2,第二个滞后性阈值。
第五个参数,int类型的ap