如何在openCV中“拉伸”minAreaRect函数给出的边界框?

qlckcl4x  于 2022-12-04  发布在  其他
关注(0)|答案(2)|浏览(141)

我希望在图像上的两个已知点之间运行线检测器,但首先我需要加宽线周围的区域,这样我的线检测器就有更多的区域可供使用。主要问题是它会相对于线斜率拉伸线周围的区域。例如:white line generated form two points with black bounding box
我试着手动操作box数组:

input_to_min_area = np.array([[660, 888], [653, 540]]) # this works instead of contour as an input to minAreaRect

rect = cv.minAreaRect(input_to_min_area)
box = cv.boxPoints(rect)
box[[0, 3], 0] += 20
box[[1, 2], 0] -= 20
box = np.int0(box)

cv.drawContours(self.images[0], [box], 0, (0, 255, 255), 2)

但这对任何直线斜率都不起作用。从垂直到this angle一切正常,但对horizontal lines不起作用。
哪一种更简单的解决方案适用于任何直线斜率?

gijlo24d

gijlo24d1#

minAreaRect()提供中心点、矩形的大小和Angular 。
你可以只增加矩形的短边长度,这样你就有了一个“更宽的矩形”的描述,然后你可以对它做任何你想做的事情,比如在它上面调用boxPoints()

padding = 42

rect = cv.minAreaRect(input_to_min_area)

(center, (w,h), angle) = rect # take it apart

if w < h: # we don't know which side is longer, add to shorter side
    w += padding
else:
    h += padding

rect = (center, (w,h), angle) # rebuild

一个方框围绕着你的两个端点,加宽了:

vbkedwbf

vbkedwbf2#

我们可以在垂直于“minAreaRect”的Angular 的轴上添加填充。

  • 获取Angular ,并转换为弧度
angle = np.deg2rad(rect[2])  # Angle of minAreaRect
  • 每个方向上的填充都垂直于minAreaRect的Angular
pad_x = 20*np.sin(angle)
 pad_y = 20*np.cos(angle)
  • 在两个轴上添加填充:

假设盒子中的点的顺序是根据rect的Angular 排序的(我不知道它是否总是正确的--可能需要对点进行排序)。

box[[0, 3], 0] -= pad_x
 box[[1, 2], 0] += pad_x
 box[[0, 3], 1] += pad_y
 box[[1, 2], 1] -= pad_y
 box = np.int0(box)

代码示例:

import cv2
import numpy as np

img = cv2.imread('sketch.png')

#input_to_min_area = np.array([[584, 147], [587, 502]]) # this works instead of contour as an input to minAreaRect
#input_to_min_area = np.array([[109, 515], [585, 144]]) # this works instead of contour as an input to minAreaRect
input_to_min_area = np.array([[80, 103], [590, 502]]) # this works instead of contour as an input to minAreaRect

rect = cv2.minAreaRect(input_to_min_area)
box = cv2.boxPoints(rect)

angle = np.deg2rad(rect[2])  # Angle of minAreaRect

# Padding in each direction is perpendicular to the angle of minAreaRect
pad_x = 20*np.sin(angle)
pad_y = 20*np.cos(angle)

box[[0, 3], 0] -= pad_x
box[[1, 2], 0] += pad_x
box[[0, 3], 1] += pad_y
box[[1, 2], 1] -= pad_y
box = np.int0(box)

cv2.drawContours(img, [box], 0, (0, 255, 255), 2)

cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()

示例输出:

我们可能还想在平行方向上展开长方体。
我还是不确定那些迹象...
在这种情况下,更新input_to_min_area会更简单:

import cv2
import numpy as np

img = cv2.imread('sketch.png')

#input_to_min_area = np.array([[584, 147], [587, 502]]) # this works instead of contour as an input to minAreaRect
#input_to_min_area = np.array([[109, 515], [585, 144]]) # this works instead of contour as an input to minAreaRect
input_to_min_area = np.array([[80, 103], [590, 502]]) # this works instead of contour as an input to minAreaRect

rect = cv2.minAreaRect(input_to_min_area)

angle = np.deg2rad(rect[2])  # Angle of minAreaRect
pad_x = int(round(20*np.cos(angle)))
pad_y = int(round(20*np.sin(angle)))
tmp_to_min_area = np.array([[input_to_min_area[0, 0]+pad_x, input_to_min_area[0, 1]+pad_y], [input_to_min_area[1, 0]-pad_x, input_to_min_area[1, 1]-pad_y]])
rect = cv2.minAreaRect(tmp_to_min_area)

box = cv2.boxPoints(rect)

angle = np.deg2rad(rect[2])  # Angle of minAreaRect

# Padding in each direction is perpendicular to the angle of minAreaRect
pad_x = 20*np.sin(angle)
pad_y = 20*np.cos(angle)

box[[0, 3], 0] -= pad_x
box[[1, 2], 0] += pad_x
box[[0, 3], 1] += pad_y
box[[1, 2], 1] -= pad_y

box = np.int0(box)

cv2.drawContours(img, [box], 0, (0, 255, 255), 2)

cv2.line(img, (tmp_to_min_area[0, 0], tmp_to_min_area[0, 1]), (tmp_to_min_area[1, 0], tmp_to_min_area[1, 1]), (255, 0, 0), 2)

cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()

输出量:

相关问题