数码管识别

20 篇文章 0 订阅

前言

前一段时间帮别人做项目,这个题目是数码管识别,这个最简单的办法就是准备图片,放到SVM中训练,就会得到不错的效果,但是,我想起以前做过这个项目,当时还没接触机器学习,用的是传统方法识别的。主要思想就是三次扫描一个数目管,判断他的7个发光二极管的亮灭,就可以识别出结果,但当时由于获取到的数码管图像太小,误识别很高,就放弃了,不过现在这个题目得到的图片大,清楚,不容易误识别,就可以用这个方法识别,顺便复习一下当时的思路和算法。

识别思想

采用三次扫描法,可以实现数码管数字的识别,识别方法的思想也简单:
第一次:扫描五号位置和一号位置
第二次:扫描四号位置和二号位置
第三次:扫描零号位置和六号位置三号位置

主要思路如图所示:
算法示意图

扫描结束后,会得到一个码表,比如数字二,它的编码为 0 1 0 1 1 0 1 1,转换为十六进制为0x5b,得到编码之后,就可以查表,识别数字。

下面给出一个可以运行的demo,大家可以运行一下,看下效果(前提配置好OpenCV的C++环境)。

链接:https://download.csdn.net/download/qq_36327203/11221814

效果截图:
在这里插入图片描述

代码

这种方法的代码实现如下:

//2 3 4 5 6 7 8 9 0
static unsigned char model_num2[9] = { 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x47, 0x7f, 0x6f, 0x3f };

int match_num(Mat &img)
{
	//        6 5 4 3 2 1 0
	//2 0x5b  1 0 1 1 0 1 1
	//3 0x4f  1 0 0 1 1 1 1
	//4 0x66  1 1 0 0 1 1 0
	//5 0x6d  1 1 0 1 1 0 1
	//6 0x7d  1 1 1 1 1 0 1
	//7 0x47  0 1 0 0 1 1 1 0x07
	//8 0x7f  1 1 1 1 1 1 1
	//9 0x6f  1 1 0 1 1 1 1
	//0 0x3f  0 1 1 1 1 1 1
	
	//2 3 4 5 6 7 8 9 0
	//unsigned char model_num2[9] = { 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x47, 0x7f, 0x6f, 0x3f };

	Mat img_temp = img.clone();
	/*
	---------------------00000-------------------------
	--------------------5-----1------------------------
	--------------------5-----1------------------------
	---------------------66666-------------------------
	--------------------4-----2------------------------
	--------------------4-----2------------------------
	---------------------33333-------------------------
	*/
	rectangle(img_temp, Rect(0, 0, img_temp.cols, img_temp.rows), Scalar(0), 1);	//处理边界

	int y1 = img_temp.rows >> 2;      	//y方向1/4处
	int y2 = (img_temp.rows >> 2) * 3;;	//y方向3/4处
	int xx = img_temp.cols >> 1;		//x方向1/2处
	int yy = img_temp.rows >> 1;		//x方向1/2处

	unsigned char temp_value = 0;

	//识别到1
	if ((double)img.rows / (double)img.cols > 2.5)
		return 1;


	//两条横线检测遍历
	for (int y = y1; y < img_temp.rows; y += (y1 * 2))
	{
		uchar *pp = img_temp.ptr<uchar>(y);
		for (int x = 0; x < img_temp.cols - 1; x++)
		{
			if (pp[x] == 0)
			{
				if (pp[x + 1] == 255)
				{
					if (x < xx && y < yy) temp_value |= (0x01 << 5);
					if (x > xx && y < yy) temp_value |= (0x01 << 1);
					if (x < xx && y > yy) temp_value |= (0x01 << 4);
					if (x > xx && y > yy) temp_value |= (0x01 << 2);
				}
			}
		}
	}
	//一条竖线检测遍历
	for (int y = 0; y < img_temp.rows - 1; y++)
	{
		uchar *pp = img_temp.ptr<uchar>(y);
		if (pp[xx] == 0)
		{
			if (pp[xx + img_temp.step] == 255)
			{
				if (y < y1) temp_value |= (0x01 << 0);
				if (y > y2) temp_value |= (0x01 << 3);
				if (y > y1 && y < y2) temp_value |= (0x01 << 6);

			}
		}
	}

	//查表匹配
	for (int model_i = 0; model_i < 9; model_i++)
	{
		if (temp_value == model_num2[model_i])
		{
			if (model_i == 8) return 0; //0为特殊情况
			else return model_i + 2;
		}
	}

	return -1;
}

反思与改进

图形必须预处理好,不能有其他明显的噪声。
这种方法是基于擦混同方法识别的,稳定性方面不好,复杂环境下效果不好。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chasentech

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值