首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Mask-RCNN中从Mask矩阵(布尔矩阵)中找到Mask角的坐标(矩形)?

在Mask-RCNN中从Mask矩阵(布尔矩阵)中找到Mask角的坐标(矩形)?
EN

Stack Overflow用户
提问于 2019-12-05 16:40:44
回答 2查看 1.2K关注 0票数 1

在我的项目中,我尝试在我的数据集中检测商店标志。我在用Mask-RCNN。图像大小为512x512。shop sign images with Mask-RCNN

代码语言:javascript
复制
results = model.detect([image], verbose=1)
r = results[0]
masked = r['masks']
rois = r['rois']

在我运行上面的代码后,“rois”给了我商店招牌的边界框的坐标(例如40,52,79,249)。R‘mask’给了我一个布尔矩阵,它代表了图像中的每个蒙版。如果该像素在掩码区域中,则掩码矩阵中的像素值为'True‘。并且如果该像素在掩码区域之外,则像素值为'False‘。如果模型在图像中检测到7个商店招牌(即7个蒙版),则r“蒙版”的大小为512x512x7。每个通道代表不同的掩码。

我必须单独处理每个掩码,因此我分离了每个通道,假设获得第一个通道。然后我找到了'True‘像素的掩码数组中的坐标。

代码语言:javascript
复制
array = masked[:,:,0]

true_points = []
for i in range(512):
    for j in range(512):
        if array[i][j] == True:
            true_points.append([j, i])

所以,我的问题是,我如何从这个布尔矩阵中获得面具(即商店标志)的角的坐标?大多数商店的招牌都是直角的,但可以旋转。我有边界框的坐标,但当商店招牌旋转时,它不准确。我有'True‘点的坐标。你能推荐一个算法来找到角的'True‘值吗?

EN

回答 2

Stack Overflow用户

发布于 2019-12-05 17:52:35

如果您知道旋转角度,只需旋转角点上的bbox角,例如usig cv2.warpAffine。如果您不这样做,那么您可以或多或少很容易地找到极值,如下所示

代码语言:javascript
复制
H,W = array.shape
left_edges = np.where(array.any(axis=1),array.argmax(axis=1),W+1)
flip_lr = cv2.flip(array,1) #1 horz vert 0
right_edges = W-np.where(flip_lr.any(axis=1),flip_lr.argmax(axis=1),W+1)
top_edges = np.where(array.any(axis=0),array.argmax(axis=0),H+1)
flip_ud = cv2.flip(array,0) #1 horz vert 0
bottom_edges = H - np.where(flip_ud.any(axis=0),flip_ud.argmax(axis=0),H+1)
leftmost = left_edges.min()
rightmost = right_edges.max()
topmost = top_edges.min()
bottommost = bottom_edges.max()

你的bbox有角(最左边,最上面),(最右边,最下面),here's我试过的一个例子。顺便说一句,如果你发现自己在像素上循环,你应该知道几乎总是有一个numpy向量化操作,它会做得更快。

票数 0
EN

Stack Overflow用户

发布于 2020-07-27 07:50:18

透视变换可用于解决此问题:

  1. 从检测到的口罩中查找商店标志的角点。(src points)
  2. Desired矩形框点(dst points)
  3. Generate a new image with cv2.getPerspectiveTransform and cv2.warpPerspective

对于角点检测,我们可以使用cv2.findContourscv2.approxPolyDP

cv2.findContours在二进制图像中查找轮廓。

代码语言:javascript
复制
contours, _ = cv2.findContours(r['masks'][:,:,0].astype(np.uint8), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

然后使用cv2.approxPolyDP从轮廓中近似矩形

cv2.approxPolyDP中的关键点是epsilon (逼近精度的参数)。用于矩形点检测的自定义阈值(下图)

代码语言:javascript
复制
def Contour2Quadrangle(contour):
    def getApprox(contour, alpha):
        epsilon = alpha * cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, epsilon, True)
        return approx

    # find appropriate epsilon
    def getQuadrangle(contour):
        alpha = 0.1
        beta = 2 # larger than 1
        approx = getApprox(contour, alpha)
        if len(approx) < 4:
            while len(approx) < 4:
                alpha = alpha / beta
                approx = getApprox(contour, alpha)  
            alpha_lower = alpha
            alpha_upper = alpha * beta
        elif len(approx) > 4:
            while len(approx) > 4:
                alpha = alpha * beta
                approx = getApprox(contour, alpha)  
            alpha_lower = alpha / beta
            alpha_upper = alpha
        if len(approx) == 4:
            return approx
        alpha_middle = (alpha_lower * alpha_upper ) ** 0.5
        approx_middle = getApprox(contour, alpha_middle)
        while len(approx_middle) != 4:
            if len(approx_middle) < 4:
                alpha_upper = alpha_middle
                approx_upper = approx_middle
            if len(approx_middle) > 4:
                alpha_lower = alpha_middle
                approx_lower = approx_middle
            alpha_middle = ( alpha_lower * alpha_upper ) ** 0.5
            approx_middle = getApprox(contour, alpha_middle)
        return approx_middle

    def getQuadrangleWithRegularOrder(contour):
        approx = getQuadrangle(contour)
        hashable_approx = [tuple(a[0]) for a in approx]
        sorted_by_axis0 = sorted(hashable_approx, key=lambda x: x[0])
        sorted_by_axis1 = sorted(hashable_approx, key=lambda x: x[1])
        topleft_set = set(sorted_by_axis0[:2]) & set(sorted_by_axis1[:2])
        assert len(topleft_set) == 1
        topleft = topleft_set.pop()
        topleft_idx = hashable_approx.index(topleft)
        approx_with_reguler_order = [ approx[(topleft_idx + i) % 4] for i in range(4) ]
        return approx_with_reguler_order

    return getQuadrangleWithRegularOrder(contour)

最后,我们使用所需的目的地坐标生成一个新图像。

代码语言:javascript
复制
contour = max(contours, key=cv2.contourArea)
corner_points = Contour2Quadrangle(contour)
src = np.float32(list(map(lambda x: x[0], corner_points)))
dst = np.float32([[0,0],[0, 200],[400, 200],[200, 0]])

M = cv2.getPerspectiveTransform(src, dst)
transformed = cv2.warpPerspective(img, M, (rect_img_w, rect_img_h))
plt.imshow(transformed) # check the results
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59191179

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档