- 前言
- 一、图像预处理
- 二、霍夫直线检测
- 三、源码
- 四、结果显示
- 总结
前言
本案例通过使用OpenCV中的霍夫直线检测HoughLinesP进行填空题区域检测(说白了就是进行直线检测),实现起来也很简单。
一、图像预处理原图如图所示:
首先第一步先进行图像预处理,得到二值图像。
Mat gray; cvtColor(src, gray, COLOR_BGR2GRAY); Mat gaussian; GaussianBlur(gray, gaussian, Size(3, 3), 0); Mat thresh; threshold(gaussian, thresh, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
通过使用大津阈值进行图像二值化处理,如下图所示,得到一幅二值图像。接下来,需要提取出二值图中直线部分。由图像特征可以看出,直线部分又长又细,所以可以使用形态学操作对图像进行腐蚀操作,仅保留直线部分。在这里我使用的是形态学开操作(先腐蚀,后膨胀)保证能完整的提取出直线部分。由于直线部分又长又细,所以我们在创建kernel时,Size(width,height),width尽可能大一些,height尽可能小一些。这里我使用的是Size(25, 3)大小的kernel。
经形态学开操作处理之后的效果如图所示:
Mat kernel = getStructuringElement(MORPH_RECT, Size(25, 3)); morphologyEx(thresh, thresh, MORPH_OPEN, kernel);二、霍夫直线检测
关于霍夫直线检测算法原理我在这里就不细说了,网上教程很多,解释的肯定也比我好。我在这里就简单介绍一下OpenCV中霍夫直线检测API使用。OpenCV中使用霍夫直线检测有两个API,一个是 cv::HoughLines() 标准和多尺度Hough变换;另一个是 cv::HoughLinesP() 渐进概率Hough变换。
void HoughLines( InputArray image, //输入图像,必须是8位二值图像 OutputArray lines, //结果存放位置,可以是N x 1双通道数组,也可以是一个N项类型为Vec2f的std::vector<>向量,用于存储rho和theta值 double rho, //直线所需分辨率(即累加平面的分辨率),单位是像素 double theta, //直线所需分辨率(即累加平面的分辨率),单位是弧度 int threshold, //累加平面中算法用于判断线条属于一条直线的阈值 double srn = 0, //srn和stn用于控制称为“多尺度Hough变换”(MHT)的SHT算法扩展,不用于标准Hough变换 double stn = 0, );
void HoughLinesP( InputArray image, //输入图像,必须是8位二值图像 OutputArray lines, //结果存放位置,四通道(或Vec4i类型的向量),四通道分别是找出线段两端点坐标(x0,y0)和(x1,y1)(按顺序) double rho, //直线所需分辨率(即累加平面的分辨率),单位是像素 double theta, //直线所需分辨率(即累加平面的分辨率),单位是弧度 int threshold, //累加平面中算法用于判断线条属于一条直线的阈值 double minLineLength = 0, //返回线段的最小长度 double maxLineGap = 0 //共线线段之间的最小间隔,防止算法把它们连成一条 );
这里我使用的是HoughLinesP进行直线检测,下面直接上源码。
三、源码#include四、结果显示#include using namespace std; using namespace cv; int main() { Mat src = imread("test.jpg"); if (src.empty()) { cout << "can not read the image..." << endl; system("pause"); return -1; } Mat gray; cvtColor(src, gray, COLOR_BGR2GRAY); Mat gaussian; GaussianBlur(gray, gaussian, Size(3, 3), 0); Mat thresh; threshold(gaussian, thresh, 0, 255, THRESH_BINARY_INV | THRESH_OTSU); Mat kernel = getStructuringElement(MORPH_RECT, Size(25, 3)); morphologyEx(thresh, thresh, MORPH_OPEN, kernel); vector lines; HoughLinesP(thresh, lines, 1, CV_PI / 180, 100, 50, 10); for (int i = 0; i < lines.size(); i++) { line(src, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), Scalar(0, 0, 255), 2); } imshow("src", src); waitKey(0); destroyAllWindows(); system("pause"); return 0; }
总结
本文使用OpenCV C++ 进行填空题区域检测,其实原理很简单,主要操作有以下几点。
1、图像预处理,得到二值图像
2、霍夫直线检测,注意调参,参数不同,得到的结果也不太一样。



