8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何使用 OpenCV 连接图像中的边缘?

ryandra 2月前

165 0

我有一张二进制图像,其中包含一些矩形形状,其中只有边缘完全可见。我想连接缺失的线条并制作完整的矩形。如何使用 Open... 实现此目的

我有一张二值图像,其中包含一些矩形形状,其中只有边缘完全可见。我想连接缺失的线条并制作完整的矩形。如何使用 OpenCV 实现这一点。

source image

我的目标结果如下:

帖子版权声明 1、本帖标题:如何使用 OpenCV 连接图像中的边缘?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由ryandra在本站《opencv》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 这不是一项简单的任务。您需要识别图像中边界框的角,然后将它们匹配在一起,然后再绘制其余的矩形。第一部分通常使用卷积完成。有几个库可以处理这个问题: pattern_match 来自 scikit-image 是一个不错的开始。

    然而,在这个特殊情况下,角点是单值且宽度和高度均为一个像素。您可以通过在图像阵列上扫描窗口并匹配角点的外观来强力找到角点。这样就可以找到角点的位置。

    然后你需要匹配属于一起的角。左上角和右上角的 top-value 应该非常接近;左上角和左下角的 left-value 应该非常接近;等等。

    以下是我上面描述的两个步骤。首先,我们收集图像数据并将其转换为 numpy 数组。

    import cv2
    import io
    import numpy as np
    from PIL import Image
    import requests
    from collections import namedtuple
    
    # first collect our data and turn it into a numpy array
    res = requests.get('https://i.sstatic.net/cLDfS.png')
    img = Image.open(io.BytesIO(res.content))
    img_arr = np.array(img)
    
    # create objects to organize the data 
    CornerCollection = namedtuple('CornerCollection', ['tls', 'trs', 'brs', 'bls'])
    BoundingBox = namedtuple('BoundingBox', ['tl', 'tr', 'br', 'bl'])
    

    添加遍历图像数组并寻找与角落完全匹配的函数。

    def find_corners(img: np.array) -> CornerCollection:
        """Finds the corners outlines in a mono-tone image."""
        top_left = np.array([[1,1],[1,0]])
        top_right = np.array([[1,1],[0,1]])
        bot_right = np.array([[0,1],[1,1]])
        bot_left = np.array([[1,0],[1,1]])
    
        tl_corners = []
        tr_corners = []
        br_corners = []
        bl_corners = []
    
        window_iter = np.lib.stride_tricks.sliding_window_view(np.array(img), (2,2))
        for i, row_view in enumerate(window_iter):
            for j, view in enumerate(row_view):
                if (view == top_left).all():
                    tl_corners.append((i, j))
                if (view == top_right).all():
                    tr_corners.append((i, j + 1))
                if (view == bot_right).all():
                    br_corners.append((i + 1, j + 1))
                if (view == bot_left).all():
                    bl_corners.append((i, j + 1))
        return CornerCollection(tl_corners, tr_corners, br_corners, bl_corners)
    
    crnr_col = find_corners(img_arr)
    

    这里我们遍历每个左上角并找到与其他角的最佳匹配。这将返回一个 BoundingBox 对象列表。

    def merge_corners(cc: CornerCollection) -> list[BoundingBox]:
        boxes = []
        trs: list = cc.trs.copy()
        bls: list = cc.bls.copy()
        brs: list = cc.brs.copy()
        for (tl_i, tl_j) in cc.tls:
            best_tr = min(trs, key=lambda ij: abs(ij[0] - tl_i))
            best_bl = min(bls, key=lambda ij: abs(ij[1] - tl_j))
            best_br = min(brs, key=lambda ij: abs(ij[0] - tl_i) + abs(ij[1] - tl_j))
            trs.remove(best_tr)
            bls.remove(best_bl)
            brs.remove(best_br)
            boxes.append(BoundingBox((tl_i, tl_j), best_tr, best_br, best_bl))
        return boxes
    
    bboxes = merge_corners(crnr_col)
    bboxes
    # returns:
    [BoundingBox(tl=(9, 534), tr=(9, 545), br=(41, 545), bl=(41, 534)),
     BoundingBox(tl=(57, 672), tr=(57, 689), br=(80, 689), bl=(80, 672)),
     BoundingBox(tl=(77, 322), tr=(77, 340), br=(127, 340), bl=(127, 322)),
     BoundingBox(tl=(107, 849), tr=(107, 872), br=(143, 872), bl=(143, 849)),
     BoundingBox(tl=(132, 758), tr=(132, 794), br=(268, 794), bl=(268, 758)),
     BoundingBox(tl=(160, 916), tr=(160, 971), br=(298, 971), bl=(298, 916)),
     BoundingBox(tl=(169, 524), tr=(169, 539), br=(186, 539), bl=(186, 524)),
     BoundingBox(tl=(199, 581), tr=(199, 640), br=(325, 640), bl=(325, 581)),
     BoundingBox(tl=(244, 1155), tr=(244, 1191), br=(343, 1191), bl=(343, 1155))]
    

    使用 bboxes tl tr br 以及回到到的 bl 线条 tl 来制作矩形或者使用函数 cv2.rectangle

    import cv2
    
    for bbox in bboxes:
        cv2.rectangle(img_arr, bbox.tl[::-1], bbox.br[::-1], color=1, thickness=1)
    

    Here is the plot with the rectangles added.

返回
作者最近主题: