[OpenCV+VS2015]表计读数识别(一):表计位置检测(表计歪的咋办!?)

[OpenCV+VS2015]表计读数识别(一):表计位置检测

本文是基于传统视频图像处理办法检测表计读数,作者资历尚浅,如有不足之处,欢迎指正,谢谢!

1 位置检测的思路

当时拿到手有如下的几个思路想法:
a、表计都是圆的,可以用hough变换圆形检测,再用mask掩膜提取,就可以完成位置的确定
b、表盘的颜色有一定的分布,比如外圈是黑色原框,内部是白色表盘底。可以先用聚类的方式让颜色聚类分开,便于区域分割。然后设定一些RGB判据进行二值化,就可以得出表盘轮廓从而提取。
c、模板匹配:这里分为直接模板匹配surf特征点匹配找到对应匹配点,前者是不具有旋转拉伸不变性。

然后我拿到图,裂开
在这里插入图片描述
这嘛玩意歪成这样,好吧,我直接颜色聚类简单点处理算了。
所以我直接方案b走起,其他方法我也想过,可以操作但是有点麻烦,而且本人太菜!

2 位置提取

2.1 kmeans颜色聚类

keamns简介和代码,我之前写过,这里建个传送门

这里的核心思想就是表盘颜色接近白色和周围颜色有明显不同,所以kmeans聚类之后,使用二值化判断的方法把表轮廓的部分选择出来
在这里插入图片描述
这个图就是我二值化的结果,表盘部分很明显是内部白色外部黑色的圆形轮廓

2.2 表盘轮廓提取

这个时候就可以选择
1、可以hough变换找圆形或者拟合椭圆形去寻找
2、可以直接findcontour找到轮廓,然后用矩形框选,但是框选的时候应该添加一些条件,比如:

  • 表计的长方形框长宽比接近1:1;
  • 表计位置不会出出现在图片的边缘位置;
  • 表计不会过于狭窄;
  • 表计框选内部的颜色分量应该是白色居多;
    等等可以按照自己的需要添加条件

3 结果

最后截取效果
在这里插入图片描述
表盘就出来啦

4 代码

这是主要部分的代码

void Gauge_Detection(Mat& src, Mat& dst)
{
   
   
	Mat binary_image;
	Image trans_in, trans_out;

	MattoImage(src, trans_in);
	RGB_kmeans(trans_in, trans_out);
	ImagetoMat(trans_out, dst);

	//namedWindow("【kmeans聚类图像】", 0);
	//resizeWindow("【kmeans聚类图像】", 640, 480);
	//imshow("【kmeans聚类图像】",dst);

	Binary(dst, binary_image);
	namedWindow("【二值化图像】", 0);
	resizeWindow("【二值化图像】", 640, 480);
	imshow("【二值化图像】", binary_image);
	DrawFire(src, binary_image);

	//namedWindow("【kmeans聚类图像】", 0);
	//resizeWindow("【kmeans聚类图像】", 640, 480);
	//imshow("【kmeans聚类图像】", dst);
	//namedWindow("【二值化图像】", 0);
	//resizeWindow("【二值化图像】", 640, 480);
	//imshow("【二值化图像】", binary_image);
}
/*将导入的mat型变换到image*/
void MattoImage(Mat &src, Image &dst) {
   
   
	for (int i = 0; i < src.rows; i++) {
   
   
		Row row;
		for (int j = 0; j < src.cols; j++) {
   
   
			auto temp = src.at<Vec3b>(i, j);
			row.emplace_back(Color(temp[2], temp[1], temp[0]));
		}
		dst.push_back(row);
	}
}

void RGB_kmeans(Image &src, Image &dst)
{
   
   
	int i, j, s, it, t, pos;
	double diff;
	double mindiff = _mindiff;
	int Maxitr = _Maxitr;

	assert(!src.empty());
	for (i = 1; i < src.size(); i++) {
   
   
		assert(src[i].size() == src[0].size());
	}

	int rows = src.size();
	int cols = src[0].size();

	Mat cluster(src.size(), src[0].size(), CV_8UC1);
	dst.clear();
	//给定初始质心
	double temp = src.size() / k;
	if (temp < 1 || temp<0)
	{
   
   
		printf("the input 'k' error.please try again!");
	}

	int interval = (src.size() - src.size() % k) / k;
	int krow[k] = {
   
    0 };
	int kcol[k] = {
   
    0 };//用于存放初始化随机k个质心点位置

	int kr[k];
	int kg[k];
	int kb[k]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值