• OpenCV中的例程检测方框的代码报错问题修改


    #!/usr/bin/env python
    
    '''
    Simple "Square Detector" program.
    
    Loads several images sequentially and tries to find squares in each image.
    '''
    
    # Python 2/3 compatibility
    from __future__ import print_function
    import sys
    PY3 = sys.version_info[0] == 3
    
    if PY3:
        xrange = range
    
    import numpy as np
    import cv2 as cv
    
    
    def angle_cos(p0, p1, p2):
        d1, d2 = (p0-p1).astype('float'), (p2-p1).astype('float')
        return abs( np.dot(d1, d2) / np.sqrt( np.dot(d1, d1)*np.dot(d2, d2) ) )
    
    def find_squares(img):
        img = cv.GaussianBlur(img, (5, 5), 0)
        squares = []
        for gray in cv.split(img):
            for thrs in xrange(0, 255, 26):
                if thrs == 0:
                    bin = cv.Canny(gray, 0, 50, apertureSize=5)
                    bin = cv.dilate(bin, None)
                else:
                    _retval, bin = cv.threshold(gray, thrs, 255, cv.THRESH_BINARY)
                contours, _hierarchy = cv.findContours(bin, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
                for cnt in contours:
                    cnt_len = cv.arcLength(cnt, True)
                    cnt = cv.approxPolyDP(cnt, 0.02*cnt_len, True)
                    if len(cnt) == 4 and cv.contourArea(cnt) > 1000 and cv.isContourConvex(cnt):
                        cnt = cnt.reshape(-1, 2)
                        max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in xrange(4)])
                        if max_cos < 0.1:
                            squares.append(cnt)
        return squares
    
    def main():
        from glob import glob
        for fn in glob('../data/pic*.png'):
            img = cv.imread(fn)
            squares = find_squares(img)
            cv.drawContours( img, squares, -1, (0, 255, 0), 3 )
            cv.imshow('squares', img)
            ch = cv.waitKey()
            if ch == 27:
                break
    
        print('Done')
    
    
    if __name__ == '__main__':
        print(__doc__)
        main()
        cv.destroyAllWindows()
    
    
    • 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

    修改项:
    OpenCV版本不同,cv.findContours函数的返回值结构与您的代码不匹配。在较新版本的OpenCV中,cv.findContours函数只返回两个值:轮廓和层级信息,而不再返回二进制图像。

    要解决这个问题,您需要修改您的代码,只获取轮廓信息,而不再获取不再返回二进制图像。在函数 find_squares 中,修改以下这行代码:

    bin, contours, _hierarchy = cv.findContours(bin, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
    
    • 1

    将其修改为:

    contours, _hierarchy = cv.findContours(bin, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
    
    • 1

    这样,您的代码将只获取轮廓信息,而不再尝试解包二进制图像,从而避免了 “not enough values to unpack” 错误。修改后的代码应该如下所示:

    def find_squares(img):
        img = cv.GaussianBlur(img, (5, 5), 0)
        squares = []
        for gray in cv.split(img):
            for thrs in range(0, 255, 26):
                if thrs == 0:
                    bin = cv.Canny(gray, 0, 50, apertureSize=5)
                    bin = cv.dilate(bin, None)
                else:
                    _retval, bin = cv.threshold(gray, thrs, 255, cv.THRESH_BINARY)
                contours, _hierarchy = cv.findContours(bin, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
                for cnt in contours:
                    cnt_len = cv.arcLength(cnt, True)
                    cnt = cv.approxPolyDP(cnt, 0.02*cnt_len, True)
                    if len(cnt) == 4 and cv.contourArea(cnt) > 1000 and cv.isContourConvex(cnt):
                        cnt = cnt.reshape(-1, 2)
                        max_cos = np.max([angle_cos(cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4]) for i in range(4)])
                        if max_cos < 0.1:
                            squares.append(cnt)
        return squares
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    这应该解决了 “not enough values to unpack” 错误,使您的代码能够正常运行。

    代码解析:

    def find_squares(img):
        img = cv.GaussianBlur(img, (5, 5), 0)
        squares = []
        for gray in cv.split(img):
    
    • 1
    • 2
    • 3
    • 4

    这段代码定义了一个名为 find_squares 的函数,该函数接受一个图像 img 作为输入参数。函数开始对输入图像进行高斯模糊处理,以减少噪声,这是为了更好地处理后续的图像处理步骤。然后,它创建了一个空列表 squares,以存储找到的正方形的坐标。

    接下来的部分是一个循环,该循环遍历图像的灰度通道:

            for thrs in range(0, 255, 26):
    
    • 1

    这个循环在0到255的范围内,每隔26进行迭代,以查找不同阈值下的轮廓。

                if thrs == 0:
                    bin = cv.Canny(gray, 0, 50, apertureSize=5)
                    bin = cv.dilate(bin, None)
                else:
                    _retval, bin = cv.threshold(gray, thrs, 255, cv.THRESH_BINARY)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在循环中,首先检查阈值 thrs 是否为0。如果是0,它会执行Canny边缘检测,并将结果存储在名为 bin 的二进制图像中。然后,它对二进制图像进行膨胀操作。膨胀是一种形态学操作,用于增强图像中的边缘。

    如果阈值 thrs 不为0,它将执行阈值二值化操作,将灰度图像转换为二进制图像。这两种方法用于查找图像中的边缘和轮廓。

                contours, _hierarchy = cv.findContours(bin, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
    
    • 1

    接下来,它使用 cv.findContours 函数查找二进制图像中的轮廓。该函数返回轮廓列表 contours 和层次信息(在这里未使用)。

                for cnt in contours:
    
    • 1

    接下来是另一个循环,它遍历找到的轮廓。

                    cnt_len = cv.arcLength(cnt, True)
    
    • 1

    对于每个轮廓,它计算轮廓的长度。

                    cnt = cv.approxPolyDP(cnt, 0.02 * cnt_len, True)
    
    • 1

    然后,它使用多边形逼近方法(cv.approxPolyDP)将轮廓近似为更简单的多边形。这是为了找到具有更少顶点的多边形,以帮助确定是否是正方形。

                    if len(cnt) == 4 and cv.contourArea(cnt) > 1000 and cv.isContourConvex(cnt):
    
    • 1

    接下来,它检查轮廓是否包含4个顶点,是否具有足够大的面积,以及它是否是凸多边形。这些条件用于确定找到的多边形是否是正方形。

                        cnt = cnt.reshape(-1, 2)
                        max_cos = np.max([angle_cos(cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4]) for i in range(4)])
    
    • 1
    • 2

    如果满足上述条件,它将多边形的坐标重塑为一维数组,然后计算多边形的角度。

                        if max_cos < 0.1:
                            squares.append(cnt)
    
    • 1
    • 2

    最后,它检查多边形的角度是否接近于直角(cosine值小于0.1),如果是,就将该多边形添加到 squares 列表中。

        return squares
    
    • 1

    最后,函数返回包含找到的正方形坐标的 squares 列表。

    这个函数的目的是在图像中查找正方形轮廓,并返回这些轮廓的坐标。您可以在您的代码中调用这个函数,然后进一步处理或标记找到的正方形。

  • 相关阅读:
    JTabbedPane 右键标题关闭选项卡
    原创 VTK 基础入门 ( 一 ) 贴纹理
    DDRx寻址原理
    使用 Keras 和 Tensorflow Hub 对电影评论进行文本分类
    用DIV+CSS技术设计的公益主题网站——防止电信诈骗(web前端网页制作课作业)
    Centos&RHEL 6忘记装图形化界面了补装
    Jtti:云服务器ftp不能访问端口如何解决
    ARM汇编指令
    数据结构与算法之LeetCode-64-最小路径和(动态规划求解)
    mysql主从复制和读写分离
  • 原文地址:https://blog.csdn.net/qq_42244167/article/details/133993545