python - OpenCV,用矩形覆盖轮廓

标签 python opencv contour

OpenCV如何覆盖多个矩形的不规则形状?参见示例人物。

矩形应覆盖对象的最大面积,并且可以任意 Angular 。重要的是它们不能互相重叠。如果矩形覆盖了某些背景,则完全可以。

我发现这个thread可以将轮廓分割成小矩形,但不会合并成最大的矩形。 [https://answers.opencv.org/question/25912/split-contours-into-many-small-rectangles/]

我确实将OpenCV与python一起使用,但是如果您在C++中有示例代码,那是完全可以的。

Before image

Wanted result

最佳答案

这是使用Python / OpenCV将其分解为4个矩形的一种简单方法。

  • 读取输入的
  • 转换为灰色
  • 阈值
  • 获取两个轮廓
  • 计算两条垂直线,即外部(较大)轮廓高度的长度,但沿着内部(较小)轮廓的侧面的长度
  • 在阈值图像
  • 上绘制这些垂直线
  • 获取并在上一张图像上绘制轮廓
  • 保存结果

  • 输入:

    enter image description here
    import cv2
    import numpy as np
    
    # read image
    img = cv2.imread('rectangles.png')
    hh, ww = img.shape[:2]
    
    # convert to grayscale
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    
    # threshold
    thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]
    
    # get contours and get the largest and smallest ones
    contour_img = img.copy()
    contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    min_area_thresh = hh * ww
    max_area_thresh = 0
    for cntr in contours:
        cv2.drawContours(contour_img, [cntr], -1, (0, 255, 0), 1)
        area = cv2.contourArea(cntr)
        if area < min_area_thresh:
            xs,ys,ws,hs = cv2.boundingRect(cntr)
            min_area_thresh = area
            small_contour = cntr
        if area > max_area_thresh:
            xl,yl,wl,hl = cv2.boundingRect(cntr)
            max_area_thresh = area
            large_contour = cntr
    
    
    # compute vertical lines of height of large contour along the sides of the inner contours
    x1 = xs
    y1 = yl
    x2 = x1
    y2 = yl + hl - 1
    x3 = xs + ws - 1
    y3 = yl
    x4 = x3
    y4 = y2
    
    # draw two vertical lines in black on thresholded image to separate segments
    thresh2 = thresh.copy()
    cv2.line(thresh2, (x1,y1), (x2,y2), 0, 1) 
    cv2.line(thresh2, (x3,y3), (x4,y4), 0, 1) 
    
    # get and draw contours from thresh2
    result = thresh2.copy()
    result = cv2.merge([result,result,result])
    contours = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    for cntr in contours:
        color = list(np.random.random(size=3) * 256)
        cv2.drawContours(result, [cntr], -1, color, 2)
    
    # show thresh and result    
    cv2.imshow("input", img)
    cv2.imshow("thresh", thresh)
    cv2.imshow("contours", contour_img)
    cv2.imshow("thresh2", thresh2)
    cv2.imshow("result", result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    # save resulting images
    cv2.imwrite('rectangles_contours.png',contour_img)
    cv2.imwrite('rectangles_thresh2.png',thresh2)
    cv2.imwrite('rectangles_result.png',result)
    

    阈值图像上的大轮廓和小轮廓:

    enter image description here

    在阈值图像上绘制的两条黑色垂直线:

    enter image description here

    结果在上一张图像上绘制了随机的颜色轮廓:

    enter image description here

    关于python - OpenCV,用矩形覆盖轮廓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60802025/

    相关文章:

    matlab - 在 Matlab 中的线条内绘制数据标签

    python - 将多个子字符串匹配模式提取到列中

    python opencv 按位异或

    python - 如何在 django 表单中以列表形式输入数据?

    python - 如何在轮廓区域内查找和绘制最大的矩形?

    python - 如何在 python 中找到线阵列的声压级?

    python - 重构:合并两个字典,但忽略 None 值

    python - 使用opencv和Python消除图像模糊

    android - 无法链接 OpenCV Android 示例中的 native 库

    numpy - 准备数据以在 Matplotlib 的 basemap 中绘制等高线