(Python)大小符识别之基于opencv穿线法的数码管识别

一、问题

女朋友的大作业第一题选自于robomaster的题目,机器人需要通过摄像头先识别数码管区域的 5 个密码数字,然后控制射击机构依照顺序用塑料子弹击打九宫格区域内对应的数字。因此需要对数码管进行识别。下面是题目要求。

二、分析

对于数码管的识别,可以利用简单的穿线法。

图像的分割可以利用opencv中自带的函数。

将图片转换为HSV格式可以更好分割。

三、代码

1.转换成hsv格式,利用hsv格式进行筛选,其中筛选参数lower,upper需要根据自己情况来设定。

hsv = cv2.cvtColor(image_org, cv2.COLOR_BGR2HSV)

lower = np.array([h0, s0, v0])
upper = np.array([h1, s1, v1])

image_gray = cv2.inRange(hsv, lower, upper)

 

2.对hsv图像进行高斯滤波,二值化处理

image_gray = cv2.GaussianBlur(image_gray, (7, 7), 0)
ret, image_bin = cv2.threshold(image_gray, 200, 255, cv2.THRESH_BINARY)

3.进行形态学处理,利用闭运算处理。

cv2.morphologyEx(image_bin, cv2.MORPH_CLOSE, kernel2, iterations=1)

4. 运用cv2.findContours得到边界,下图是可视化边界的样图。

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.最终得到结果(未按顺序输出)

四、改进

可以利用神经网络来做,这样准确率很高,鲁棒性强。但是需要自己做数据集,麻烦。

五、参考

https://blog.csdn.net/zong596568821xp/article/details/85098590

https://blog.csdn.net/km2km2km/article/details/94778305

https://blog.csdn.net/sandalphon4869/article/details/95398033

https://blog.csdn.net/spw_1201/article/details/78310349

  • 3
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
OpenCV 穿线(Hough 变换)是一种常用的图像处理方,可以用于检测直线、圆等几何形状。在单个数码管数字识别中,我们可以使用穿线来检测数码管的线段,然后根据线段的位置和长度来判断数字。 下面是实现步骤: 1. 首先读入图像,并进行灰度化和二值化处理。 ```python import cv2 import numpy as np img = cv2.imread('digit.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY_INV) ``` 2. 对二值化后的图像进行边缘检测,得到边缘图像。 ```python edges = cv2.Canny(thresh, 50, 150) ``` 3. 对边缘图像进行穿线变换,得到所有直线的参数。 ```python lines = cv2.HoughLines(edges, 1, np.pi/180, 150) ``` 4. 遍历所有直线,筛选出合条件的线段,并记录线段的位置和长度。 ```python segments = [] for line in lines: rho, theta = line[0] if theta < np.pi/4 or theta > 3*np.pi/4: x1 = int(rho/np.cos(theta)) x2 = int((rho - thresh.shape[0]*np.sin(theta))/np.cos(theta)) length = abs(x2 - x1) if length > 10: segments.append((x1, x2)) ``` 5. 根据线段的位置和长度,判断数字。 ```python digits = [] for i in range(7): x_min = int(i*img.shape[1]/7) x_max = int((i+1)*img.shape[1]/7) segment = None for s in segments: if s[0] >= x_min and s[1] <= x_max: if segment is None or abs(s[1]-s[0]) > abs(segment[1]-segment[0]): segment = s if segment is None: digits.append(' ') elif abs(segment[1]-segment[0]) < (x_max-x_min)/2: digits.append('.') else: digits.append(str(int(round(1.0*(segment[0]+segment[1])/2/(x_max-x_min)*10)))) ``` 完整代码如下: ```python import cv2 import numpy as np img = cv2.imread('digit.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY_INV) edges = cv2.Canny(thresh, 50, 150) lines = cv2.HoughLines(edges, 1, np.pi/180, 150) segments = [] for line in lines: rho, theta = line[0] if theta < np.pi/4 or theta > 3*np.pi/4: x1 = int(rho/np.cos(theta)) x2 = int((rho - thresh.shape[0]*np.sin(theta))/np.cos(theta)) length = abs(x2 - x1) if length > 10: segments.append((x1, x2)) digits = [] for i in range(7): x_min = int(i*img.shape[1]/7) x_max = int((i+1)*img.shape[1]/7) segment = None for s in segments: if s[0] >= x_min and s[1] <= x_max: if segment is None or abs(s[1]-s[0]) > abs(segment[1]-segment[0]): segment = s if segment is None: digits.append(' ') elif abs(segment[1]-segment[0]) < (x_max-x_min)/2: digits.append('.') else: digits.append(str(int(round(1.0*(segment[0]+segment[1])/2/(x_max-x_min)*10)))) print(digits) ``` 其中,`digit.jpg` 是包含单个数码管的图片,可以根据实际情况进行替换。运行后输出的 `digits` 即为识别出的数字

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值