设计利用可用光传输的软件之二维码的定位识别及裁剪

我们设计出了二维码的编码和解码,但要进行拍摄的时候,就必须对拍摄的图片进行定位和裁剪,以达到更好的识别效果。

一、二维码的定位

参考这篇博客的内容,我们对二维码定位点识别
python+opencv实现二维码定位(一)
其思路的核心有几点:首先利用opencv的cv2.cvtColor()以及cv2.threshold()对图片进行处理。而后cv2.findContours()进行进一步的轮廓提取。

'''检测轮廓'''
def detect(image):

    width,height=image.shape[:2][::-1]
    img_gray=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)#转灰度图
    retval,binary=cv2.threshold(img_gray,0,255,cv2.THRESH_OTSU+cv2.THRESH_BINARY_INV)#二值化处理
    contours,hierarchy=cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)#等级树结构轮廓
    #cv2.drawContours(img,contours,-1,(0,0,255),3)
    #cv2.imshow("img",image)
    #cv2.waitKey()
    return contours,hierarchy

接下来是对识别到的轮廓进行处理,判断是否满足1:1:3:1:1的二维码定位点设计比例。

'''轮廓比例 边占比7:5'''
def get_scale1(contours,i,j):
#外轮廓和子轮廓比例 1:1:3:1:1
    area1=cv2.contourArea(contours[i])#轮廓面积1
    area2=cv2.contourArea(contours[j])#轮廓面积2
    if area2==0:#无子轮廓
        return False
    ratio = area1*1.0 / area2
    if abs(ratio-49.0/25): # 7/5
        return True
    return False
'''轮廓比例 边占比5:3'''
def get_scale2(contours,i,j):
    #子轮廓和子子轮廓
    area1 = cv2.contourArea(contours[i])#轮廓面积1
    area2 = cv2.contourArea(contours[j])#轮廓面积2
    if area2 == 0:#无子轮廓
        return False
    ratio = area1 * 1.0 / area2
    if abs(ratio - 25.0 / 9):# 5/3
        return True
    return False

判断后,我们获取三个轮廓的中心坐标

'''求轮廓中心坐标'''
def get_center(contours,i):
    M=cv2.moments(contours[i]) #求矩阵
    cx=int(M['m10']/M['m00']) #求x坐标
    cy=int(M['m01']/M['m00']) #求y坐标
    return cx,cy
'''判断中心间距'''
def detect_contours(vec):
    distance_1=np.sqrt((vec[0]-vec[2])**2+(vec[1]-vec[3])**2)#1、2两点的距离
    distance_2 = np.sqrt((vec[0] - vec[4]) ** 2 + (vec[1] - vec[5]) ** 2)#1、3两点的距离
    distance_3 = np.sqrt((vec[2] - vec[4]) ** 2 + (vec[3] - vec[5]) ** 2)#2、3两点的距离
    if sum((distance_1,distance_2,distance_3))/3<3:
        return True
    return False

其中原作者使用是否三角形作为了一个判断条件,是一个很好的思路。

def triangle(rec):#是否组成三角形
    if len(rec) < 3:
        return -1, -1, -1
    '''判断边长是否满足三角形条件'''
    for i in range(len(rec)):
        for j in range(i + 1, len(rec)):
            for k in range(j + 1, len(rec)):
                distance_1 = np.sqrt((rec[i][0] - rec[j][0]) ** 2 + (rec[i][1] - rec[j][1]) ** 2)
                distance_2 = np.sqrt((rec[i][0] - rec[k][0]) ** 2 + (rec[i][1] - rec[k][1]) ** 2)
                distance_3 = np.sqrt((rec[j][0] - rec[k][0]) ** 2 + (rec[j][1] - rec[k][1]) ** 2)
                if abs(distance_1 - distance_2) < 5:
                    if abs(np.sqrt(np.square(distance_1) + np.square(distance_2)) - distance_3) < 5:
                        return i, j, k
                elif abs(distance_1 - distance_3) < 5:
                    if abs(np.sqrt(np.square(distance_1) + np.square(distance_3)) - distance_2) < 5:
                        return i, j, k
                elif abs(distance_2 - distance_3) < 5:
                    if abs(np.sqrt(np.square(distance_2) + np.square(distance_3)) - distance_1) < 5:
                        return i, j, k
    return -1, -1, -1

以上步骤结束,基本就可以对二维码进行一个粗略的定位了。那么接下去就是对二维码的裁剪处理了。

二、二维码的裁剪

为了使解码更为准确,我们需要将二维码从原图上裁剪下来,并进行尺寸的处理。

    ss=np.concatenate((contours[rec[i][6]],contours[rec[j][6]],contours[rec[k][6]]))#矩阵拼接
    rect=cv2.minAreaRect(ss)#最小外接矩形
    box=cv2.boxPoints(rect)#矩形边缘
    box=np.int0(box)
    leftup = box[2][1]
    rightup = box[0][1]
    leftbuttom = box[1][0]
    rightbuttom = box[3][0]

    '''裁剪图片'''
 	new_image=image[leftup:rightup,leftbuttom:rightbuttom]
    #new_image=image[43:1025,403:1387]
    #cv2.imshow('img', new_image)
    #cv2.waitKey(0)
    new_image1=cv2.resize(new_image,(1024,1024))
    #cv2.imshow('img', new_image1)
    #cv2.waitKey(0)
    return new_image1

我们通过简单测试,粗略地寻找除了几个点对图像进行裁剪,裁剪可以使得大部分的信息能够被读取,但对于太大的倾斜仍然无法有效地处理。

发布了3 篇原创文章 · 获赞 7 · 访问量 186

猜你喜欢

转载自blog.csdn.net/qq_44101587/article/details/104913827
今日推荐