• 编码标记物智能识别系统(YOLO v5+Opencv实现)


    一、环境搭建

    环境搭建推荐肆十二的文章:手把手教你使用YOLOV5训练自己的目标检测模型-口罩检测-视频教程
    里面有关YOLO v5前期的环境搭建讲解十分详细,且与本项目的YOLO v5前期环境搭建大差不差,这里不再赘述。

    二、编码标记物数据集

    编码标记物数据集采用labelimg手动标注的方法,详细数据集见:环形编码标记物数据集
    编码标记物及相关数据集(部分)展示如下图:
    在这里插入图片描述
    在这里插入图片描述

    三、编码标记物识别

    通过YOLO v5网络实现编码标记物的智能识别与定位,即通过训练后的网络实现对编码标记物的识别,训练好的模型详见:best与last模型
    识别结果如图所示,可见即使是对小而密集的编码标记物也有较好的识别效果:
    在这里插入图片描述

    四、编码标记物的解码

    在完成了编码标记物的定位与识别之后,再需要在预测框图片的基础上完成编码标记物的解码工作,这里采用Opencv的辅助方法。

    1. 循环识别图像获得码值

    def getcode():
        debug=True
        img = cv2.imread('./images/tmp/test/tmp_upload.png') #图片路径
        gray_all=img
        contours_all=[]
        contours_circle=[]
        hierarchy_all=[]
        gray_all = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        #gray_all=cv2.GaussianBlur(gray_all,)
        ret,binary=cv2.threshold(gray_all,100,255,cv2.THRESH_BINARY)
        gray_show=binary
        # 使用findcontours函数对二值化后的图像进行轮廓提取,第三个参数为轮廓点的存储方式,这里选返回所有轮廓点,方便后面做筛选
        contours_all,hierarchy_all= cv2.findContours(binary,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
        vec_center=[]
        vec_radius=[]
        vec_rrect=[]
        #连续采样,计算码值,预设三个扫描起点,进行顺时针扫描,若三个扫描值相同,即为初步码值。
        for i in range(0,len(contours_all)):
            (x, y), radius = cv2.minEnclosingCircle(contours_all[i])
            center = (int(x), int(y))
            radius = int(radius)+0.0000001
            contorarea=cv2.contourArea(contours_all[i])
            ratiol=contorarea/(3.1415*radius*radius)
            if (ratiol>0.9) and len(contours_all[i])>50:
                contours_circle.append(contours_all[i])
                vec_center.append(center)
                vec_radius.append(radius)
            if len(contours_all[i])>50:
                fitelliprect=cv2.fitEllipse(contours_all[i])
                (fitelliprectw,fitelliprecth)=fitelliprect[1]
                minarearect=cv2.minAreaRect(contours_all[i])
                (minarearectw,minarearecth)=minarearect[1]
                fitrectarea=fitelliprectw*fitelliprecth
                minarea=minarearectw*minarearecth
                radio2=fitrectarea/minarea
                if radio2>0.95 and radio2<1.05:
                    vec_rrect.append(fitelliprect)
    
    
        for i in range(0,len(vec_center)):
            rect=gray_show[int(vec_center[i][1] - 3 * vec_radius[i]):int(vec_center[i][1] + 3 * vec_radius[i]),
                    int(vec_center[i][0] - 3 * vec_radius[i]):int(vec_center[i][0] + 3 * vec_radius[i]) ]
            t=rect
            codenew=0
            for scanpoint in range(0,3):
                code=0
                for range0 in range(0,8):
                    count=0
                    starpoint=range0*45+scanpoint*15
                    endpoint=(range0+1)*45+scanpoint*15
                    angle=starpoint
                    while angle<endpoint:
                        pointx=3*vec_radius[i]+(vec_radius[i] / 150 * 350) * math.cos(angle / 180.0 * 3.1415)
                        pointy=3*vec_radius[i] + (vec_radius[i] / 150 * 350) * math.sin(angle / 180.0 * 3.1415)
                        x=(t[int(pointx)][int(pointy)])
                        if x==255:
                            count=count+1
                        angle=angle+3
                    if count<=8:
                        code=code+math.pow(2,range0)
                codenew=findmincode(int(code))
            print(codenew)
        if debug:
            title=str(codenew)
            cv2.imshow(title,t)
            cv2.waitKey(0)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    2. 码值后处理

    因为环形编码标记物并没有固定起点,所以要对得到的码值进行循环移位以得到最小码值,即为最后的结果码值。

    #码值选择函数(找到最小码值)
    def findmincode(code):
        minresult=255
        for i in range(1,8):
            left=circular_shift_left(code,i,8)
            right=circular_shift_right(code,i,8)
            result=min(left,right)
            if(result<minresult):
                minresult=result
        return minresult
    
    #辅助码值选择函数(左移位函数)
    # int_value是输入的整数,k是位移的位数,bit是整数对应二进制的位数
    def circular_shift_left(int_value, k, bit=8):
        bit_string = '{:0%db}' % bit
        bin_value = bit_string.format(int_value)  # 8 bit binary
        bin_value = bin_value[k:] + bin_value[:k]
        int_value = int(bin_value, 2)
        return int_value
    
    #辅助码值选择函数(右移位函数)
    # right circular shift
    def circular_shift_right(int_value, k, bit=8):
        bit_string = '{:0%db}' % bit
        bin_value = bit_string.format(int_value)  # 8 bit binary
        bin_value = bin_value[-k:] + bin_value[:-k]
        int_value = int(bin_value, 2)
        return int_value
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
  • 相关阅读:
    2022年11月26日NaiveBayes
    PMS150C应广单片机开发案例
    JavaScript 的面向对象基础,设计模式中的原型模式(设计模式与开发实践 P2)
    centeros 7安装mysql
    pandas第8章-文本数据
    如何利用小程序提升销售额?
    js基础笔记学习52-练习2计算水仙花数1
    The timestamp difference between admin and executor exceeds the limit.解决办法
    蓝牙设备在智能家居控制系统中的应用
    码住!双11支付宝小程序云云市集,享骨折优惠最强购物清单,抽奖赢iPhone 15 Pro!
  • 原文地址:https://blog.csdn.net/qq_44757221/article/details/125627452