1、 转化为灰度图像。
2、 二值化。
3、 边缘检测。
4、 霍夫直线检测。
示例代码:
void MethodOne(Mat img)
{
// 第一步:转化为灰度图像
Mat grayImg;
cvtColor(img, grayImg, COLOR_BGR2GRAY);
// 第二步:二值化。
threshold(grayImg, grayImg, 0, 255, THRESH_OTSU | THRESH_BINARY);
// 第三步:边缘检测
Canny(grayImg, grayImg, 100, 200, 3, false);
// 第四步:霍夫直线检测
vectorplines;
HoughLinesP(grayImg, plines, 1, CV_PI / 180, 30, 18, 0);
Mat dst = img.clone();
for (size_t i = 0; i < plines.size(); i++)
{
Vec4f hline = plines[i];
line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), Scalar(0,0,255), 1, LINE_AA);
}
imshow("dst", dst);
}
在不断尝试霍夫直线的参数之后最终比较好的效果如下图,可以看到结果还是很不理想。
2.2.2 思路二
1、 转化为灰度图像。
2、 二值化。
3、 边缘检测。
4、 形态学处理保留直线。
5、 霍夫直线检测。
示例代码:
void MethodTwo(Mat img)
{
// 第一步:转化为灰度图像
Mat grayImg;
cvtColor(img, grayImg, COLOR_BGR2GRAY);
// 第二步:二值化。
threshold(grayImg, grayImg, 0, 255, THRESH_OTSU | THRESH_BINARY);
// 第三步:边缘检测
Canny(grayImg, grayImg, 100, 200, 3, false);
// 第四步: 闭操作填充Y方向空洞
Mat kernel = getStructuringElement(MORPH_RECT, Size(1, 3));
morphologyEx(grayImg, grayImg, MORPH_CLOSE, kernel);
// 第五步:开操作保留直线
kernel = getStructuringElement(MORPH_RECT, Size(20, 1));
morphologyEx(grayImg, grayImg, MORPH_OPEN, kernel);
#if 0
imshow("grayImg", grayImg);
// 第六步:霍夫直线检测
vectorplines;
HoughLinesP(grayImg, plines, 1, CV_PI / 180, 20, 5, 0);
Mat dst = img.clone();
for (size_t i = 0; i < plines.size(); i++)
{
Vec4f hline = plines[i];
line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), Scalar(0, 0, 255), 2, LINE_AA);
}
#else
// 创建红色背景的图片
Mat redImg(grayImg.size(),CV_8UC3,Scalar(0,0,255));
Mat RedLineImg;
cvtColor(grayImg, RedLineImg,COLOR_GRAY2BGR);
// 与操作得到只由红色直线黑色背景图
RedLineImg &= redImg;
imshow("RedLineImg", RedLineImg);
// 与操作得到结果
Mat dst = img.clone();
dst = dst | RedLineImg;
#endif
imshow("dst", dst);
}
形态学处理后使用霍夫直线检测后的效果图如下,可以看出效果好的多了。
有意思的是在形态学直线提取之后,得到的直线反而非常好,比最终的霍夫直线检测效果还好,下图是利用图像与操作实现直线的标红,未使用霍夫直线,效果非常好,当然这要求背景是白色的。
morphologyEx:可以调节形态学算子,检测水平竖直线,效果非常好。
这个例子告诉我们,霍夫直线检测固然好,但是还是需要结合实际问题,霍夫检测前需要做预处理得出大致的直线图样,而并不是上来就使用霍夫直线检测。