问题描述: 对于下面的一张图片,获取其中的直线部分。
1、基本两种方式
- 先用canny检测边缘得到边缘图片,再用霍夫直线检测边缘图片中的直线;(效果差)
- 先将图像通过形态学操作腐蚀掉字母,然后在通过霍夫检测将直线展示出来。(效果还可以)
2、基于上述方法二的算法步骤
- 阈值化(二值化);
- 构建结构元素,消除字母;
- 膨胀处理,让直线更加明显;
- 霍夫直线检测;
- 记录直线位置。
说明:形态学开操作中,一般提取水平直线用的是(n,1),提取垂直直线用的是(1,n)。
3、代码实践
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<stdlib.h>
using namespace cv;
using namespace std;
Mat src, gray, dst;
int threshold_value = 100;
int max_threshold_value = 255;
const char* name = "test";
void morhpologyLines(int, void*);
int main()
{
char* path = "D:\\00.jpg";
src = imread(path);
if (src.empty()){
return -1;
}
namedWindow(name);
imshow(name, src);
createTrackbar("Threshold:", name, &threshold_value, max_threshold_value, morhpologyLines);
morhpologyLines(0, 0);
waitKey();
return 0;
}
void morhpologyLines(int, void*) {
//先二直化图像,必须先转换成单通道的图像
Mat BinaryImage, morhpImage;
cvtColor(src, gray, COLOR_BGR2GRAY);
threshold(gray, BinaryImage, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
imshow("binary image", BinaryImage);
//构建结构元素,消除字母:重点在于kenerl中的size给的大小
Mat kernel = getStructuringElement(MORPH_RECT, Size(50, 1), Point(-1, -1));
morphologyEx(BinaryImage, morhpImage, MORPH_OPEN, kernel, Point(-1, -1));
//imshow("morhpolopy image", morhpImage);
//膨胀操作,让直线更加的明显。
kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
dilate(morhpImage, morhpImage, kernel);
//imshow("dilate image", morhpImage);
//获取直线
vector<Vec4i> lines;
HoughLinesP(morhpImage, lines, 1, CV_PI / 180.0, 50, 20, 0);
Mat dst = src.clone();
for (size_t t = 0; t < lines.size(); t++) {
Vec4i In = lines[t];
line(dst, Point(In[0], In[1]), Point(In[2], In[3]), Scalar(0, 0, 255), 1, 8, 0);
}
imshow(name, dst);
}