1 背景

利用opencv识别数码管,采用传统的穿线法,前提是利用深度学习目标检测的方法,在机柜中将数码管区域切割出来,然后再对切割出来的区域进行识别,判断数字是多少。切割出来的形状如图所示:

数码管各段表示为

2 识别思路

先对数码管进行灰度化和二值化,将数字变为255,背景变为0,然后利用穿线法,对abcdefg7个区域依次穿线,判断是否有255的值,有则表示该区域高亮,最后结合7个区域的高亮信息,综合判断数字是多少

a b c d e f g result

0 √ √ √ √ √ √ 63

1 √ √ 6

2 √ √ √ √ √ 91

3 √ √ √ √ √ 79

4 √ √ √ √ 102

5 √ √ √ √ √ 109

6 √ √ √ √ √ √ 125

7 √ √ √ 7

8 √ √ √ √ √ √ √ 127

9 √ √ √ √ √ 103

3 灰度化

opencv有自带的灰度化函数cv2.cvtColor(),但是在使用过程中发现,对于一些整体亮度低的数码管灰度化后,会丢失数字信息,看不出来哪段亮,考虑到数码管都是红色的,红色通道的数据最重要,因此设计了一个自己灰度化的函数 def tomygray(image):

height = image.shape[0]

width = image.shape[1]

gray = np.zeros((height, width, 1), np.uint8)

for i in range(height):

for j in range(width):

# pixel = max(image[i,j][0], image[i,j][1], image[i,j][2])

pixel = 0.0 * image[i, j][0] + 0.0 * image[i, j][1] + 1 * image[i, j][2]

gray[i, j] = pixel

return gray

4 二值化

opencv有多种二值化的方法,主要包括固定阈值和自适应阈值的方法,具体介绍可看《OpenCV之阈值化操作总结》

自适应阈值主要适用于一张图片中亮度不一样的情况,而对于我们的数码管来说,由于大小很小,基本上没有亮度变化,因此使用固定阈值的方法即可。函数原型如下 ret, dst = cv2.threshold(src, thresh, maxval, type)

函数最重要的部分是thresh值的设置,由于不同图片的数码管亮度不同,不可以选择同一个阈值,需要分别计算每张图片的固定阈值,计算阈值有很多方法,我用到的方法有以下两种

4.1 统计直方图

统计直方图中像素的分布情况,根据数量最多的像素值来设置一个阈值(下边的参数都是调试效果比较好的值,自己可根据具体情况来设置)

hist = cv2.calcHist([image_gray], [0], None, [256], [0,256])

#plt.hist(hist.ravel(), 256, [0,256])

#plt.savefig(filename + '_hist.png')

#plt.show()

min_val, max_val, min_index, max_index = cv2.minMaxLoc(hist)

ret, image_bin = cv2.threshold(image_gray, int(max_index[1])-7, 255,

cv2.THRESH_BINARY)

4.2 计算平均值

计算灰度图的平均像素值,根据平均值设定阈值 mean,stddev = cv2.meanStdDev(image_gray)

ret, image_bin = cv2.threshold(image_gray, meanvalue + 65, 255,

cv2.THRESH_BINARY)

5 穿线法

得到二值化的图像后,将图像进行分割,切成一个一个的数字,然后每个都用穿线法来判断值是多少

def TubeIdentification(filename, num, image):

tube = 0

tubo_roi = [

[image.shape[0] * 0/3, image.shape[0] * 1/3, image.shape[1] * 1/2,

image.shape[1] * 1/2],

[image.shape[0] * 1/3, image.shape[0] * 1/3, image.shape[1] * 2/3,

image.shape[1] - 1 ],

[image.shape[0] * 2/3, image.shape[0] * 2/3, image.shape[1] * 2/3,

image.shape[1] - 1 ],

[image.shape[0] * 2/3, image.shape[0] -1 , image.shape[1] * 1/2,

image.shape[1] * 1/2],

[image.shape[0] * 2/3, image.shape[0] * 2/3, image.shape[1] * 0/3,

image.shape[1] * 1/3],

[image.shape[0] * 1/3, image.shape[0] * 1/3, image.shape[1] * 0/3,

image.shape[1] * 1/3],

[image.shape[0] * 1/3, image.shape[0] * 2/3, image.shape[1] * 1/2,

image.shape[1] * 1/2]]

i = 0

while(i < 7):

if(Iswhite(image, int(tubo_roi[i][0]), int(tubo_roi[i][1]),

int(tubo_roi[i][2]),int(tubo_roi[i][3]))):

tube = tube + pow(2,i)

cv2.line(image, ( int(tubo_roi[i][3]),int(tubo_roi[i][1])),

(int(tubo_roi[i][2]), int(tubo_roi[i][0])),

(255,0,0), 1)

i += 1

if(tube==63):

onenumber = 0

elif(tube==6):

onenumber = 1

elif(tube==91):

onenumber = 2

elif(tube==79):

onenumber = 3

elif(tube==102 or tube==110):

#110是因为有干扰情况

onenumber = 4

elif(tube==109):

onenumber = 5

elif(tube==125):

onenumber = 6

elif(tube==7):

onenumber = 7

elif(tube==127):

onenumber = 8

elif(tube==103):

onenumber = 9

else:

onenumber = -1

cv2.imwrite(filename + '_' + str(num) + '_' + str(onenumber) + '.png', image)

return onenumber

def Iswhite(image, row_start, row_end, col_start, col_end):

white_num = 0

j=row_start

i=col_start

while(j <= row_end):

while(i <= col_end):

if(image[j][i] == 255):

white_num+=1

i+=1

j+=1

i=col_start

#print('white num is',white_num)

if(white_num >= 5):

return True

else:

return False

6 识别主程序 def digitalrec(image):

filename = str(image).split('.jpg', 1)[0]

image_org = cv2.imread(image)

height = image_org.shape[0]

width = image_org.shape[1]

#transe image to gray

#image_gray = cv2.cvtColor(image_org, cv2.COLOR_RGB2GRAY)

image_gray = tomygray(image_org)

cv2.imwrite(filename + '_gray.png',image_gray)

meanvalue = image_gray.mean()

if meanvalue >= 200:

hist = cv2.calcHist([image_gray], [0], None, [256], [0,256])

#plt.hist(hist.ravel(), 256, [0,256])

#plt.savefig(filename + '_hist.png')

#plt.show()

min_val, max_val, min_index, max_index = cv2.minMaxLoc(hist)

ret, image_bin = cv2.threshold(image_gray, int(max_index[1])-7, 255,

cv2.THRESH_BINARY)

else:

mean,stddev = cv2.meanStdDev(image_gray)

ret, image_bin = cv2.threshold(image_gray, meanvalue + 65, 255,

cv2.THRESH_BINARY)

#image_bin = cv2.adaptiveThreshold(image_gray, 255,

# cv2.ADAPTIVE_THRESH_GAUSSIAN_C,

# cv2.THRESH_BINARY, 11,

# 0)

x, y, w, h = cv2.boundingRect(image_bin)

image_bin = image_bin[max(y-5,0) : h+10, max(x-5,0) : w+10]

cv2.imwrite(filename + '_bin.png',image_bin)

#split number and identify it

num = 0

result = ''

while True:

if(num < 3):

roi = image_bin[0: height, int(width / 3 * num):

int(width / 3 * (num + 1))]

onenumber = TubeIdentification(filename, num, roi)

if(onenumber == -1):

result += '0'

else:

result += str(onenumber)

num += 1

else:

break

print('picture of %s detect result is %s'%(filename,result))

return result

7 识别效果

8 展望

上边介绍的方法可以实现数码管的识别,但是由于有很多对像素的操作,比较耗时,平均识别一张图片需要2s左右,而且使用传统的方法来识别数码管,涉及到很多参数的设置与调试,鲁棒性不强,尤其是在灰度化和二值化的时候,参数设置很关键。

最好的解决方法是可以利用深度学习的方法来识别,提高识别率,有时间的话会尝试新的方法来解决。

数码管识别c语言代码,OpenCV之七段数码管识别(含代码)相关推荐

  1. 8255数码管显示c语言,用汇编语言编写七段数码管显示1~9,用8255A接口芯片,用中断方式控制。...

    满意答案 vgvm7321 2013.07.19 采纳率:52%    等级:11 已帮助:11521人 正好我们做了这个实验 你知道的,把数据段中的端口地址改为你的计算机可识别的8255A的端口地址 ...

  2. 【03】Unity AR 2022Vuforia图片识别超详细案例(小岛动画交互)【含代码】

    Unity AR Vuforia(拓展)--Vuforia图片识别超详细案例(小岛动画交互)[含代码] 文章目录 Unity AR Vuforia(拓展)--Vuforia图片识别超详细案例(小岛动画 ...

  3. 3d人脸识别算法opencv_用Opencv打造自己的人脸识别

    # 用Opencv打造自己的人脸识别 标签: opencv 人脸识别在现在使用的越来越多,所以使用opencv构造一个简单的人脸识别.步骤包括收集及处理数据,构建人脸识别器,进行人脸识别. 收集数据 ...

  4. 简单人脸识别一之使用opencv+cnn网络实现人脸识别

    最近在研究目标检测这个方向,看到网上有很多的人脸识别帖子,所以也想着上上手看看.当时是做了三个模型出来,第一个就是网上很通用普遍的opencv+简单三层cnn网络来实现的,说实话效果真的一般吧!具体的 ...

  5. c语言成绩管理程序设计,成绩管理程序设计报告(含代码C语言

    <成绩管理程序设计报告(含代码C语言>由会员分享,可在线阅读,更多相关<成绩管理程序设计报告(含代码C语言(19页珍藏版)>请在人人文库网上搜索. 1.大连民族学院计算机科学与 ...

  6. 单片机c语言数码管显示循环0到9程序,七段数码管0~9循环显示程序

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 编写程序实现80C51的P0口控制一个数码管显示,让它循环显示0~9等十位数字,时间间隔为1秒钟. 利用查表程序可以完成BCD与七段码的转换,从而取代硬件 ...

  7. python七段数码管绘制英文字母_Python实例之七段数码管绘制理解

    Python 实例之七段数码管绘制理解 八段线的编号如上图所示.基本逻辑为画笔从 1 走到 7 ,每一步画笔落下代表画或者是 画笔抬起代表不画,最终形成 1-9 的数字排列.以下理解均为个人学习理解. ...

  8. OpenCV之七段数码管识别(含代码)

    1 背景 利用opencv识别数码管,采用传统的穿线法,前提是利用深度学习目标检测的方法,在机柜中将数码管区域切割出来,然后再对切割出来的区域进行识别,判断数字是多少.切割出来的形状如图所示: 数码管 ...

  9. 基于OpenCV的简易实时手势识别(含代码)

    基于OpenCV的简易实时手势识别 1.基本信息介绍 1.1实验步骤 1.2效果展示 2.肤色检测+二值化+开运算+高斯模糊 2.1 flip()函数原型 2.2cvtColor()函数原型 2.3s ...

最新文章

  1. SpringMVC图片上传
  2. IDT系列:(一)初探IDT,Interrupt Descriptor Table,中断描述符表
  3. hdu 1269(Tarjan求强连通分量)
  4. linux删除软件包git的命令,linux系统安装git及git常用命令
  5. marc数据个人心得
  6. 常用设计模式之抽象工厂模式
  7. 利用js实现popup弹窗
  8. springboot 关闭懒加载_SpringBoot新手入门篇
  9. NB-IOT:系列专题1:低功耗能力
  10. 敏捷开发之极限编程过程
  11. 如何阅读MySQL源码
  12. 3dmax:3dmax三维VR渲染设置(VR间接照明GI栏、【VR间接(全局)照明】发光贴图、光子贴图、BF算法、灯光贴图、灯光缓存)之详细攻略(切记收藏!)
  13. 企业如何选择固定资产管理系统?
  14. JVM垃圾收集算法及垃圾收集器
  15. 什么是ActiveX控件?
  16. java apns feedback_php从苹果apns的feedback服务器获取推送失败的token
  17. 微信对账单--每日定时任务获取昨日微信支付账单
  18. python 可以用excel做词云图嘛_word_cloud-用Python之作个性化词云图
  19. Numpy 解一元二次方程
  20. 一 简单句和并列句(2021-10-29)

热门文章

  1. Mysql的安装及客户端使用
  2. 剑侠单机版显示服务器正在维护,12.6服务器维护公告:修复大量BUG+游戏内容
  3. app点餐点菜订餐订菜系统(前台h5,后台Java,SSH,mysql)
  4. SinoBBD承德德鸣3号楼数据中心获CQC最高等级机房认证
  5. cc2530单片机的内核是什么_cc2530是什么_cc2530能做什么
  6. android demo例子大全
  7. 51单片机OLED收银电子秤称重计价清零去皮金额累计HX711
  8. Django4.1从入门到精通——模型的创建
  9. 模拟登陆CSDN——就是这么简单
  10. 数据挖掘-关联规则挖掘之Apriori算法