本文将介绍如何利用OpenCV,提取图片中的矩形轮廓特征并进行图片的倾斜校正。完成demo程序可以至:基于轮廓的倾斜仪表校正
本demo所处理的图片是一张仪表(如下图),欲实现的功能是将图片中倾斜的PCB校正为水平。基本的思路是检测PCB的边缘直线,而后根据边缘直线的斜率旋转图片。但是由于仪表上存在指针,所以图片在经过轮廓提取直线检测后,会误检出很多条直线。demo程序中主要的算法就是从含有噪声的直线簇中提取出直线中相互垂直的直线。
Step1: 直线检测。OpenCV提供了一个检测直线的函数HoughLinesP(),关于此函数的API介绍,可以参考HoughLinesP。此步骤主要程序如下:
Mat imgOrigion = imread(IMAGE_PATH);
Mat imgScale;
float scaleFactor = COLSLIMIT / imgOrigion.cols;
resize(imgOrigion, imgScale, Size(imgOrigion.cols * scaleFactor, imgOrigion.rows * scaleFactor)); // reduce image size to speed up calculation
Mat imgGray;
cvtColor(imgScale, imgGray, COLOR_BGR2GRAY); // gray scale
Mat imgCanny;
Canny(imgGray, imgCanny, 100, 200); // use canny operator to detect contour
imshow("Contour detection", imgCanny);
std::vector<Vec4i> lineAll;
HoughLinesP(imgCanny, lineAll, 1, CV_PI / 180, 30, 50, 4);
// draw all lines detected
Mat imgAllLines;
imgScale.copyTo(imgAllLines);
for (int i = 0, steps = lineAll.size(); i < steps; i++)
{
line(imgAllLines, Point(lineAll[i][0], lineAll[i][1]), Point(lineAll[i][2], lineAll[i][3]), Scalar(255, 255, 255), 3, 8);
}
imshow("All lines detected", imgAllLines);
上图为使用Canny算子检测出的边缘。仪表板上的轮廓使得算法检测出了丰富的轮廓信息。对此轮廓图进行直线检测,结果如下图所示ÿ