OpenCV实战(三)——考试试卷填空题下划线的定位与提取

前言:     

      大家都知道,现在在英语考试中已普遍实现了机器阅卷,所以从试卷图像中提取答题区域就显的很重要了。为了实现对答题区域的切图和识别,现在我们有一个这样的需求,那就是我们要寻找英语试卷填空题的下划线。这种问题有两种思路:一是对图像进行二值化后直接进行霍夫直线检测;二是对图像进行二值化后经过开运算再进行霍夫直线检测。接下我们编程来演示。

一、图像二值化+霍夫直线检测

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

using namespace cv;
using namespace std;

int threshold_value = 100;
int max_count = 255;
const string output_winName = "Hough Lines";
Mat src_img, roi_img, dst_img;
void detectLines(int, void*);        //声明函数
void morhpologyLines(int, void*);    //声明函数

int main( )
{
	src_img = imread("English1.jpg", IMREAD_GRAYSCALE);     //灰度读取一张图片
	if (src_img.empty())
	{
		printf("could not load the image...\n");
		return -1;
	}
	namedWindow("原图", CV_WINDOW_AUTOSIZE);
	imshow("原图", src_img);

	namedWindow(output_winName, CV_WINDOW_AUTOSIZE);
	Rect roi = Rect(5, 5, src_img.cols - 10, src_img.rows - 10);      
	roi_img = src_img(roi);            // 去除边缘空白部分
	imshow("兴趣图像", roi_img);
	createTrackbar("threshold:", output_winName, &threshold_value, max_count, detectLines);
	detectLines(0, 0);
	//morhpologyLines(0, 0);

	waitKey(0);
	return 0;
}

// 思路一:canny边缘检测+霍夫检测的方法
void detectLines(int, void*) 
{
	Canny(roi_img, dst_img, threshold_value, threshold_value * 2, 3, false);         //Canny边缘检测
	vector<Vec4i> lines;
	HoughLinesP(dst_img, lines, 1, CV_PI / 180.0, 30, 30.0, 0);          //调用概率霍夫直线检测函数
	cvtColor(dst_img, dst_img, COLOR_GRAY2BGR);        //灰度度转换成彩色图
	for (size_t t = 0; t < lines.size(); ++t)      // 遍历检测到的每一条直线
	{
		Vec4i ln = lines[t];
		line(dst_img, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(0, 0, 255), 2, 8, 0);   // 绘制出检测到的每条直线
	}
	imshow(output_winName, dst_img);
}

运行程序,来看看结果如何:


改变阈值,看看不同阈值下的结果:



显然,这种思路根本行不通!我们看看第二种思路。


二、图像二值化+形态学运算+霍夫直线检测

      我们为什么要在中间加一个形态学操作呢?其实呀,我们是想保留图像中的下划线,那我们就可以做一个水平的矩形结构元来对图像做一个开运算,同样的道理,如果我们想保留竖直线,那就可以用一个垂直的矩形结构元来对图像做一个开运算。当图像二值图中只剩下白色下划线的时候,再来进行霍夫直线检测那就不会受到其他的干扰了。让我们编写程序来看看效果:

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

using namespace cv;
using namespace std;

int threshold_value = 100;
int max_count = 255;
const string output_winName = "Hough Lines";
Mat src_img, roi_img, dst_img;
void detectLines(int, void*);        //声明函数
void morhpologyLines(int, void*);    //声明函数

int main( )
{
	src_img = imread("English1.jpg", IMREAD_GRAYSCALE);     //灰度读取一张图片
	if (src_img.empty())
	{
		printf("could not load the image...\n");
		return -1;
	}
	namedWindow("原图", CV_WINDOW_AUTOSIZE);
	imshow("原图", src_img);

	namedWindow(output_winName, CV_WINDOW_AUTOSIZE);
	Rect roi = Rect(5, 5, src_img.cols - 10, src_img.rows - 10);     
	roi_img = src_img(roi);            // 去除边缘空白部分
	imshow("兴趣图像", roi_img);
	morhpologyLines(0, 0);

	waitKey(0);
	return 0;
}



// 思路二:二值图化+形态学操作+霍夫检测的方法
void morhpologyLines(int, void*)
{
	//阈值化图像
	Mat binary_img, morhp_img;
	threshold(roi_img, binary_img, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
	imshow("二值化结果", binary_img);

	//进行开运算操作
	Mat kernel = getStructuringElement(MORPH_RECT, Size(30, 1), Point(-1, -1));     //定义一个宽20、高1的一个矩形结构元
	morphologyEx(binary_img, morhp_img, MORPH_OPEN, kernel, Point(-1, -1));     //作开运算,只保留图像中的直线
	imshow("开运算操作结果", morhp_img);

	// 进行膨胀操作
	kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));      //定义一个宽3、高3的一个矩形结构元
	dilate(morhp_img, morhp_img, kernel);                             //作膨胀操作,图像中的直线增强
	imshow("膨胀操作结果", morhp_img);     
	
	// 霍夫直线检测
	vector<Vec4i> lines;
	HoughLinesP(morhp_img, lines, 1, CV_PI / 180.0, 25, 20.0, 0);
	Mat result_img = roi_img.clone();
	cvtColor(result_img, result_img, COLOR_GRAY2BGR);           //灰度图转为彩色图        

	for (size_t t = 0; t < lines.size(); ++t) 
	{
		Vec4i ln = lines[t];
		line(result_img, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(0, 0, 255), 2, 8, 0);
	}
	imshow(output_winName, result_img);
	return;
}

运行程序,如下所示:


结果很完美!

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV是一款非常强大的计算机视觉库,其中包含了很多功能强大的图像处理和计算机视觉算法。而在这个系列的第三篇文章中,我们将重点介绍如何在OpenCV中绘制图形和文本。 OpenCV中绘制图形的函数包括cv2.line(直线),cv2.rectangle(矩形),cv2.circle(圆),cv2.ellipse(椭圆)和cv2.putText(文本)。这些函数的使用非常简单,只需要指定图像,开始点和结束点(或中心点和半径),颜色和线宽即可。 例如,我们可以使用cv2.rectangle函数在图像上绘制一个矩形: ``` import cv2 import numpy as np img = np.zeros((512,512,3), np.uint8) # 创建一个黑色的图像 cv2.rectangle(img,(384,0),(510,128),(0,255,0),3) # 绘制矩形 cv2.imshow("image",img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个例子中,我们首先创建了一个512x512的黑色图像,然后使用cv2.rectangle函数在图像上绘制了一个矩形,并将其显示出来。在这里,矩形的左上角坐标是(384,0),右下角坐标是(510,128),颜色是绿色(0,255,0),线宽为3。 除了绘制图形,我们也可以使用cv2.putText函数在图像上绘制文本。这个函数的使用也非常简单,只需要指定图像,文本内容,位置,字体,字体大小和颜色即可。 例如,我们可以使用cv2.putText函数在图像上写入一个“Hello World!”的文本: ``` import cv2 import numpy as np img = np.zeros((512,512,3), np.uint8) # 创建一个黑色的图像 font = cv2.FONT_HERSHEY_SIMPLEX # 设置字体 cv2.putText(img,'Hello World!',(10,500), font, 1,(255,255,255),2,cv2.LINE_AA) # 绘制文本 cv2.imshow("image",img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个例子中,我们使用cv2.putText函数在左下角绘制了一个“Hello World!”的文本,并将其显示出来。在这里,我们首先选取了字体类型为cv2.FONT_HERSHEY_SIMPLEX,然后指定了文本的位置(10,500),字体大小为1,颜色为白色(255,255,255),线宽为2,并且使用了cv2.LINE_AA参数,以实现更好的文本渲染效果。 综上所述,OpenCV中可以很方便地对图像进行绘制和文本处理,这对于图像处理和计算机视觉应用来说是非常重要的一步。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值