与轮廓中大多数点接触的最大正方形

问题描述

我有一张图片,我从 opencv 找到并绘制了轮廓(见左图)。

我想如下绘制一个框(类似于右边的那个),它应该与轮廓中最多的点接触。

哪些函数在这里有用?我想尝试找到最大的矩形,但正如您所看到的,该区域内有一些区域,所以它会排除那个?

非常感谢您的帮助!

Diagram

解决方法

首先,您需要将图像转换为二进制(黑色或白色像素)以区分轮廓和图像的其余部分(在示例中,轮廓为黑色背景上的白色)。然后您可以“行扫描”图像,这意味着计算每行和每列的白色像素数。矩形的第一个水平边缘(具有最多白色像素的水平线)应位于图像高度的前半部分,而下一个水平边缘应位于后半部分。同样,对于垂直边缘(具有最多白色像素的垂直线),第一个应该在图像宽度的前半部分,下一个应该在下一个宽度。看看下面的代码就明白了。

示例代码:

import cv2
import numpy as np

img = cv2.imread("2.png")
h,w = img.shape[:2]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray,255,cv2.THRESH_OTSU+cv2.THRESH_BINARY_INV)[1]
thresh = cv2.rectangle(thresh,(0,0),(w,h),3)

width = 1
horizontal_line = []

best_hor_one = 0
best_hor_two = 0
count_hor_one = 0
count_hor_two = 0
for y in range(h):
    area = thresh[y:y+width,0:h]
    try:
        line = cv2.countNonZero(area)
        if line >= count_hor_one and y < h//2:
            best_hor_one = y
            count_hor_one = line
        if line >= count_hor_two and y >= h//2:
            best_hor_two = y
            count_hor_two = line
    except TypeError:
        pass

best_ver_one = 0
best_ver_two = 0
count_ver_one = 0
count_ver_two = 0
for x in range(w):
    area = thresh[0:h,x:x+width]
    try:
        line = cv2.countNonZero(area)
        if line > count_ver_one and x < w//2:
            best_ver_one = x
            count_ver_one = line
        if line > count_ver_two and x >= w//2:
            best_ver_two = x
            count_ver_two = line
    except TypeError:
        pass

cv2.line(img,(best_ver_one,best_hor_one),(best_ver_two,3)
cv2.line(img,best_hor_two),3)

cv2.imwrite("res.png",img)
cv2.imshow("img",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

enter image description here

输入图像:

enter image description here