图像中直线的检测

一.问题描述
寻找图像中的一些直线,比如英语试卷填空题的下划线,这个对后期的切图与自动识别都比较重要。
在这里插入图片描述

二.解决方法
①对于直线检测,我们首先想到的是霍夫直线检测
这里来看下直接使用霍夫直线检测的效果

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
using namespace std;

int max_value = 255;  
int threshold_value = 100; 

Mat srcImage, dstImage, roiImage;

void FindLines(int, void*);

#define WINDOW_NAME1 "【霍夫检测直线图】"

int main(int argc, char* argv)
{
	srcImage = imread("E:\\pictures\\43.jpg", 0);
 	if (srcImage.empty())
 	{
 		cout << "图像读取错误,检测路径!" << endl;
  		return -1;
 	}
 	namedWindow("原图", WINDOW_AUTOSIZE);
 	imshow("原图", srcImage);
 	namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);

	//定义ROI区域
 	Rect roi = Rect(30, 10, srcImage.cols - 50, srcImage.rows - 10);
 	roiImage = srcImage(roi);
 	imshow("ROI", roiImage);

	//创建轨道条
 	createTrackbar("阈值:", WINDOW_NAME1, &threshold_value, max_value, FindLines);
 	FindLines(threshold_value, 0);

	waitKey(0);
 	return 0;
}

void FindLines(int, void*)
{
	Canny(roiImage, dstImage, threshold_value, threshold_value * 2, 3, false);
 	vector<Vec4i> lines;
 	HoughLinesP(dstImage, lines, 1, CV_PI / 180.0, 30, 30.0, 0);
 	//参数中30表示寻找到30个连续的像素即判定为直线
 	cvtColor(dstImage, dstImage, COLOR_GRAY2BGR);
 	for (size_t t = 0; t < lines.size(); t++)
 	{
 		Vec4i In = lines[t];
  		line(dstImage, Point(In[0], In[1]), Point(In[2], In[3]), Scalar(0, 0, 255), 2, 8, 0);
 	}
 	imshow(WINDOW_NAME1, dstImage);
}

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结果发现,无论我们怎么调整二值化的阈值,直线检测的要么是漏检、不全等等,达不到我们预期的效果。

②思路:鉴于直接用霍夫变换的效果,效果不佳;需要通过图像形态学操作来寻找直线,霍夫获取位置信息及显示
程序的思路:
先根据实际图像的情况,进行合理的切割,选取恰当的ROI区域;
因为该图像黑白对比明显,进行二值化的操作;
通过图像形态学操作来寻找直线;
再通过膨胀的操作,使得寻找到的直线更加明显;
最后霍夫获取位置信息及显示。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
using namespace std;

#define WINDOW_NAME1 "【1】原图"
#define WINDOW_NAME2 "【2】ROI区域"
#define WINDOW_NAME3 "【3】二值化后"
#define WINDOW_NAME4 "【4】形态学开运算寻找直线后"
#define WINDOW_NAME5 "【5】膨胀后"
#define WINDOW_NAME6 "【6】效果图"

Mat srcImage, dstImage, roiImage;

void morhpologyLines(int, void*);

int main(int argc, char* argv)
{
	srcImage = imread("E:\\pictures\\43.jpg", 0);
 	if (srcImage.empty())
 	{
 		cout << "图像读取错误,检测路径!" << endl;
  		return -1;
 	}
	namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
 	namedWindow(WINDOW_NAME2, WINDOW_AUTOSIZE);
 	namedWindow(WINDOW_NAME3, WINDOW_AUTOSIZE);
 	namedWindow(WINDOW_NAME4, WINDOW_AUTOSIZE);
 	namedWindow(WINDOW_NAME5, WINDOW_AUTOSIZE);
 	namedWindow(WINDOW_NAME6, WINDOW_AUTOSIZE);
 	imshow(WINDOW_NAME1, srcImage);

	//定义ROI区域:选取的区域以实际情况为准
 	Rect roi = Rect(30, 10, srcImage.cols - 50, srcImage.rows - 10);
 	roiImage = srcImage(roi);
 	imshow(WINDOW_NAME2, roiImage);

	morhpologyLines(0, 0);
	
 	waitKey(0);
 	return 0;
}

void morhpologyLines(int, void*)
{
	//二值化
 	Mat binaryImage;  //二值化图像
 	threshold(roiImage, binaryImage, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
 	//参数中:THRESH_BINARY_INV和THRESH_BINARY将背景设成白色或黑色,以实际情况为准选择需要的
 	//参考博客:https://blog.csdn.net/u012566751/article/details/77046445 查看不同阈值类型的效果
 	imshow(WINDOW_NAME3, binaryImage);

	//形态学寻找直线
 	//设置形态学运算的内核为 30*1像素
 	Mat kernel1 = getStructuringElement(MORPH_RECT, Size(30, 1), Point(-1, -1));
 	//开运算
 	Mat morphologyImage; //形态学操作图像
 	morphologyEx(binaryImage, morphologyImage, MORPH_OPEN, kernel1);
 	//morphologyEx(binaryImage, morhpImage, MORPH_OPEN, kernel, Point(-1, 1));
 	//一开始按照视频教程里面这样写的,就会报错:未加载wkernelbase.pdb,这里不理解是什么原因
 	imshow(WINDOW_NAME4, morphologyImage);

	//进行膨胀操作,使得直线更加明显
 	Mat kernel2 = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
 	dilate(morphologyImage, morphologyImage, kernel2);
 	imshow(WINDOW_NAME5, morphologyImage);

	//霍夫直线检测:此时根据形态学处理后寻找到的直线,再进行霍夫检测更准确
 	vector<Vec4i> lines;
 	HoughLinesP(morphologyImage, lines, 1, CV_PI / 180.0, 30, 30.0, 0);//参数中30表示寻找到30个连续的像素即判定为直线
 	dstImage = roiImage.clone();  //定义dstImage与ROI区域一样的类型
 	cvtColor(dstImage, dstImage, COLOR_GRAY2BGR);//将结果转为BGR格式
 	for (size_t t = 0; t < lines.size(); t++)
 	{
 		Vec4i In = lines[t];
  		line(dstImage, Point(In[0], In[1]), Point(In[2], In[3]), Scalar(0, 0, 255), 2, 8, 0);
 	}	
 	imshow(WINDOW_NAME6, dstImage);
}

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了25 篇原创文章 · 获赞 0 · 访问量 453

猜你喜欢

转载自blog.csdn.net/qq_45445740/article/details/103641477