OpenCV C++案例实战二十六《填空题区域检测》

OpenCV C++案例实战二十六《填空题区域检测》

  • 前言
  • 一、图像预处理
  • 二、霍夫直线检测
  • 三、源码
  • 四、结果显示
  • 总结


前言

本案例通过使用OpenCV中的霍夫直线检测HoughLinesP进行填空题区域检测(说白了就是进行直线检测),实现起来也很简单。

一、图像预处理

原图如图所示:

OpenCV C++案例实战二十六《填空题区域检测》_第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);

通过使用大津阈值进行图像二值化处理,如下图所示,得到一幅二值图像。接下来,需要提取出二值图中直线部分。由图像特征可以看出,直线部分又长又细,所以可以使用形态学操作对图像进行腐蚀操作,仅保留直线部分。在这里我使用的是形态学开操作(先腐蚀,后膨胀)保证能完整的提取出直线部分。由于直线部分又长又细,所以我们在创建kernel时,Size(width,height),width尽可能大一些,height尽可能小一些。这里我使用的是Size(25, 3)大小的kernel。

OpenCV C++案例实战二十六《填空题区域检测》_第2张图片

经形态学开操作处理之后的效果如图所示:

	Mat kernel = getStructuringElement(MORPH_RECT, Size(25, 3));
	morphologyEx(thresh, thresh, MORPH_OPEN, kernel);

OpenCV C++案例实战二十六《填空题区域检测》_第3张图片

二、霍夫直线检测

关于霍夫直线检测算法原理我在这里就不细说了,网上教程很多,解释的肯定也比我好。我在这里就简单介绍一下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<Vec4i>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++案例实战二十六《填空题区域检测》_第4张图片
OpenCV C++案例实战二十六《填空题区域检测》_第5张图片


总结

本文使用OpenCV C++ 进行填空题区域检测,其实原理很简单,主要操作有以下几点。
1、图像预处理,得到二值图像
2、霍夫直线检测,注意调参,参数不同,得到的结果也不太一样。

你可能感兴趣的:(OpenCV,C++项目实战,opencv,计算机视觉,c++)