opencv 八 液晶屏数字提取

一、算法需求

提取特定仪器液晶屏显示区域中的数字。
在这里插入图片描述

二、问题分析

在灰度图中,目标液晶屏显示区域为图中面积最大的连通域(将其表述为数字主体区域)。在二值化后发现,数字主体区域和周围区域存在一些白点和黑色连通域,需要设法去除这些干扰因素。在得到完好的数字主体区域后,可以使用数字主体区域与原图做与运算,得到原图中的数字区域,然后进行形态学优化即可。

三、基本实现步骤

1、读取图像为灰度图并进局部二值化 【imread(“filename”,0),0:灰度图模式】
2、进行开运算,把核心区域和周边区域断开 【若开运算达不到目的,则需要补充mask断开周边区域】
3、运用函数删除白色和黑色孔洞得到核心区域 【deleteMinWhiteArea 和deleteMinBlackArea 】
4、根据核心区域提取数字

四、实现过程

4.1 图像读取为二值图

使用imread(filepath,0)将图像读取为灰度图,然后使用adaptiveThreshold函数将图像进行局部二值化。局部二值化的特点是不需要设置二值化阈值,可根据局部特征进行二值化,但需要注意blockSize的设置(控制局部区域的大小)。

//读取图片为灰度图并进行二值化
	Mat img = imread("D:\\Img_data\\Num\\test\\z1230.jpg",0);
	resize(img, img, {
    
     512,512 });
	imshow("01.灰度图", img);
	Mat bin_mat;
	int blockSize = 35;
	int constValue = 10;
	adaptiveThreshold(img, bin_mat, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, blockSize, constValue);
	imshow("02.二值图", bin_mat);

读取的灰度图如下所示:
在这里插入图片描述
二值化后的图像如下所示,可以看到其存在多个白色和黑色的区域及噪点:
在这里插入图片描述

4.2 去除干扰因素

在4.1中分析出二值图中存在多个多个白色和黑色的区域及噪点,需要设计算法去除这些干扰因素。对于白色噪点可以低通滤波器(中值滤波、均值滤波、高斯滤波等)或形态学算法(开运算或腐蚀)进行移除;对于面积较大的白色干扰因素可以使用连通域面积的方法进行移除;同时需要关注图像是否存在黑色的小连通域需要删除。

4.2.1 对二值图进行开运算

进行开运算,目的是使中间数字区域与周围连通域断开。

//进行开运算,目的是使中间数字区域与周围连通域断开
	Mat  open_mat;
	cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
	morphologyEx(bin_mat, open_mat, MORPH_OPEN, element);
	imshow("03.开运算", open_mat);

开运算后的图像如下图所示:
在这里插入图片描述

4.2.2 删除白色和黑色干扰

由开运算效果图可以看出,在主体区域周围存在很多零散的白色孔洞及连通域,可以运用 deleteMinWhiteArea函数进行删除,需要注意的是该函数阈值需要根据图片尺寸(open_mat.size)具体设定。deleteMinWhiteArea函数参考自https://hpg123.blog.csdn.net/article/details/126864086

//删除白色干扰,主要是周围区域存在白色孔洞
	cout << open_mat.channels() << "--" << open_mat.size() << endl;
	Mat im1 = deleteMinWhiteArea(open_mat, 50000); 
	imshow("04.删除白色干扰", im1);

删除白色干扰后的效果如下图所示:
在这里插入图片描述
周围白色干扰删除后,中间主体区域存在很多零散的黑色孔洞及连通域,可以运用 deleteMinBlackArea函数进行删除。deleteMinBlackArea函数参考自https://hpg123.blog.csdn.net/article/details/126864086

//删除黑色干扰,主要是中间数字区域存在黑色孔洞
	Mat im2 = deleteMinBlackArea(im1, 50000);
	imshow("05.删除黑色干扰 ", im2);

删除黑色干扰后的效果如下图所示:
在这里插入图片描述
小面积黑色干扰删除后,中间主体部分还存在明显的黑色缺口,可以用形态学算法中的闭运算(MORPH_CLOSE)进行消除。

	// 消除主体区域(数字区域)的缺口
	Mat im2_close;
	morphologyEx(im2, im2_close, MORPH_CLOSE,
		getStructuringElement(cv::MORPH_RECT, cv::Size(51, 51)));
	imshow("消除主体区域缺口", im2_close);

消除主体区域缺口后的效果如下图所示,这里我们得到了完整的空白主体区域。
在这里插入图片描述

4.3 优化原图中的主体区域

4.3.1 提取原图中的主体区域

将上述部分得到的完整空白的主体区域作为mask,与原图进行按位与运算,得到原图中的主体区域。

	//提取原图中的主体区域
	Mat ba, ba_close,im3_open;
	bitwise_and(bin_mat, im2_close, ba);//原图(img2)和二值图(bin_mat)做按位与运算,结果保存在ba中
	imshow("06.与运算结果", ba);

代码运行效果如下图所示:
在这里插入图片描述

4.3.2优化原图中的主体区域

上述步骤得到的原图主体区域中存在黑色孔洞和黑色连通域,可以再次进行形态学优化(如使用闭运算删除其中小面积的黑色区域,使用deleteMinBlackArea函数删除小面积连通域)。deleteMinBlackArea函数参考自https://hpg123.blog.csdn.net/article/details/126864086

//优化原图中的主体区域
	cv::Mat element3 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
	morphologyEx(ba, ba_close, MORPH_CLOSE, element3);//删除主体区域黑色孔洞
	imshow("07.闭运算", ba_close);
	Mat im3 = deleteMinBlackArea(ba_close, 200);//再次删除主体区域黑色连通域
	imshow("08.闭运算结果删除黑色干扰", im3);

闭运算的效果如下图所示:
在这里插入图片描述
闭运算后的图片还存在小面积的黑色干扰,再次利用deleteMinBlackArea函数进行优化,效果如下图所示:
在这里插入图片描述

4.4 优化主体区域中的数字

上述图中的单个数字的并不在一个连通域中,如数字1被一条白色的细线从中间横向分割为两个区域。故需要使用开运算将白色区域移除,使单个数字内部区域连接在一起构成一个连通域,方便后续字符分割处理。

//使单个数字内部区域连接在一起
	cv::Mat element4 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
	morphologyEx(im3, im3_open, MORPH_OPEN, element4);
	imshow("09.单个数字优化", im3_open);

	imshow("10.得到数字区域", im2_close - im3_open);

在这里插入图片描述
最终提取的数字区域如下所示:
在这里插入图片描述

五、完整代码

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

#include <iostream>  
#include <vector>
#include <io.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include "MatTool.hpp"

using namespace std;
using namespace cv;

void main() {
    
    
	/* 提取液晶屏显示的数字
	  核心思想: 利用最大的连通域提取核心区域
	  基本步骤:
			1、读取图像为灰度图并进局部二值化 【imread("filename",0),0:灰度图模式】
			2、进行开运算,把核心区域和周边区域断开 【若开运算达不到目的,则需要补充mask断开周边区域】
			3、运用函数删除白色和黑色孔洞得到核心区域 【deleteMinWhiteArea 和deleteMinBlackArea 】
			4、根据核心区域提取数字  
			 
	*/
	//读取图片为灰度图并进行二值化
	Mat img = imread("D:\\Img_data\\Num\\test\\z1230.jpg",0);
	resize(img, img, {
    
     512,512 });
	imshow("01.灰度图", img);
	Mat bin_mat;
	int blockSize = 35;
	int constValue = 10;
	adaptiveThreshold(img, bin_mat, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, blockSize, constValue);
	imshow("02.二值图", bin_mat);

	//进行开运算,目的是使中间数字区域与周围连通域断开
	Mat  open_mat;
	cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
	morphologyEx(bin_mat, open_mat, MORPH_OPEN, element);
	imshow("03.开运算", open_mat);

	//删除白色干扰,主要是周围区域存在白色孔洞
	cout << open_mat.channels() << "--" << open_mat.size() << endl;
	Mat im1 = deleteMinWhiteArea(open_mat, 50000); 
	imshow("04.删除白色干扰", im1);

	//删除黑色干扰,主要是中间数字区域存在黑色孔洞
	Mat im2 = deleteMinBlackArea(im1, 50000);
	imshow("05.删除黑色干扰 ", im2);

	// 消除主体区域(数字区域)的缺口
	Mat im2_close;
	morphologyEx(im2, im2_close, MORPH_CLOSE,
		getStructuringElement(cv::MORPH_RECT, cv::Size(51, 51)));
	imshow("消除主体区域缺口", im2_close);

	//提取原图中的主体区域
	Mat ba, ba_close,im3_open;
	bitwise_and(bin_mat, im2_close, ba);//原图(img2)和二值图(bin_mat)做按位与运算,结果保存在ba中
	imshow("06.与运算结果", ba);

	//优化原图中的主体区域
	cv::Mat element3 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
	morphologyEx(ba, ba_close, MORPH_CLOSE, element3);//删除主体区域黑色孔洞
	imshow("07.闭运算", ba_close);
	Mat im3 = deleteMinBlackArea(ba_close, 200);//再次删除主体区域黑色连通域
	imshow("08.闭运算结果删除黑色干扰", im3);

	//使单个数字内部区域连接在一起
	cv::Mat element4 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
	morphologyEx(im3, im3_open, MORPH_OPEN, element4);
	imshow("09.单个数字优化", im3_open);

	imshow("10.得到数字区域", im2_close - im3_open);
	
	waitKey();
}

猜你喜欢

转载自blog.csdn.net/m0_74259636/article/details/128600001