【问题标题】:image rectangle extraction with cv2使用 cv2 提取图像矩形
【发布时间】:2021-04-23 17:45:34
【问题描述】:

我在一张图像上工作,我从中提取了边缘,并在其中对垂直和水平线进行了形态学闭合。

我只想保留这张图片中间的矩形:

我有点不知道如何做到这一点。你能帮帮我吗?

【问题讨论】:

  • 看起来您的图像是边缘检测和阈值处理等预处理的结果。可以发一下原图和图片处理代码吗?

标签: python image cv2


【解决方案1】:

您可以使用扩张缩小矩形中的间隙,然后寻找内部也有轮廓的最大轮廓。

矩形是最大的轮廓,但是找到最大的轮廓接缝太具体了。
为了概括解决方案,我建议寻找其中包含另一个轮廓的最大轮廓。
假设是矩形通过它的“子轮廓”来区分。

寻找孙子:
Contours Hierarchy 有点难以理解...
我们需要处理一个空轮廓由两个轮廓组成的事实——外轮廓和内轮廓(内轮廓是外轮廓的子轮廓)。
我们需要寻找有孙子的轮廓,而不是寻找有子的轮廓。

您可以使用以下阶段:

  • 使用“扩张”形态学操作来缩小矩形线条之间的间隙。
  • 查找轮廓和层次结构,使用 RETR_TREE 在轮廓内创建轮廓树。
  • 按区域对等高线(和层次结构)进行排序 - 按降序排序,以便最大的在前。
  • 搜索具有孙轮廓的面积最大的轮廓。

这是一个代码示例:

import numpy as np
import cv2

img = cv2.imread('rect_img.png', cv2.IMREAD_GRAYSCALE)  # Read input image as Grayscale
img = img[10:-10, 10:-10]  # Crop the margins
thresh = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)[1]  # Convert to binary (the input image is not binary).

# Use "dilate" morphological operation for closing the gaps between the lines of the rectangle
thresh = cv2.dilate(thresh, np.ones((3,3)))

# Find contours and hierarchy, use RETR_TREE for creating a tree of contours within contours
cnts, hiers = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2:]  # [-2:] indexing takes return value before last (due to OpenCV compatibility issues).

hiers = hiers[0]  # Remove redundant dimensions of hierarchy

# Merge two lists to list of pairs (before sorting), cnts_hiers is [(c,h), (c,h), (c,h), ...]
# https://stackoverflow.com/questions/2407398/how-to-merge-lists-into-a-list-of-tuples
cnts_hiers = zip(cnts, hiers)

# Sort contours (and hierarchy) by area - the largest comes first.
cnts_hiers = sorted(cnts_hiers, key=lambda c: cv2.contourArea(c[0]), reverse=True)

# Iterate the sorted contours (and hierarchy):
# Look for contour with largest area that have a grandchild contour
# Note: we are looking for a grandchild because each empty contour has an inner contour and an outer contour.
for c_h in cnts_hiers:
    c = c_h[0]  # The first index of c_h is the contour
    h = c_h[1]  # The second index of c_h is the hierarchy of the contour

    # https://docs.opencv.org/master/d9/d8b/tutorial_py_contours_hierarchy.html
    # OpenCV represents hierarchy as an array of four values : [Next, Previous, First_Child, Parent]
    # If there is no child or parent, that field is taken as -1

    # Check if contour has at least one child contour, and than check if the child has a child (look for grandchild)
    if h[2] >= 0:
        child_idx = h[2]  # Get the index of the child (the child is the "inner contour").
        child_hier = hiers[child_idx]  # Get the hierarchy that applies the index of the child.

        # Check if the child has a child (look for grandchild)
        if child_hier[2] >= 0:
            best_cnt = c  # The best candidate contour was found.
            break  # Break the loop


img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)  # Convert to BGR before drawing the contour.

# Mark best_cnt with green line
cv2.drawContours(img, [best_cnt], 0, (0, 255, 0), 2)

cv2.imshow('img', img)  # Show result for testing
cv2.waitKey()
cv2.destroyAllWindows()

结果:


裁剪矩形:

rect = cv2.minAreaRect(best_cnt)  # Find rectangle with minimum area
box = cv2.boxPoints(rect)
box = np.int0(box) # convert all coordinates floating point values to int
(topy, topx) = (np.min(box[:,1]), np.min(box[:,0]))  # https://stackoverflow.com/questions/28759253/how-to-crop-the-internal-area-of-a-contour
(bottomy, bottomx) = (np.max(box[:,1]), np.max(box[:,0]))
rect = img[topy:bottomy+1, topx:bottomx+1, :]

结果:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-22
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 2020-01-09
    相关资源
    最近更新 更多