使用OpenCV裁剪多边形可旋转多边形

时间:2020-08-11 11:19:44

标签: python image opencv image-processing

我正在尝试使用Python中的OpenCV从大(1920x1080)图像中切出一个停车位,

def cut_polygon_ROI_from_img(image: np.ndarray, ROI) -> np.ndarray:
    x, y, w, h = ROI.bounding_rect
    cropped = image[x:x + w, y:y + h].copy()

    points_arr = ROI.points - ROI.points.min(axis=0)
    mask = np.zeros(cropped.shape[:2], np.uint8)
    cv2.fillConvexPoly(mask, points_arr, color=(255, 255, 255))

    cropped = cv2.bitwise_and(cropped, cropped, mask=mask)
    return cropped

我用手测量了边界点(位于ROI.points中)。 ROI.bounding_rect包含一个cv2.boundingRect(points)元组,该元组是根据我手动测量的点创建的:

[[ 275 1420]
 [ 279 1531]
 [ 454 1616]
 [ 453 1503]]

点是从左上方顺时针组织的。由于某种原因,切割后我得到:

enter image description here

为了进行检查,我从[ 275 1420](左上)到[ 454 1616](右下)切出了一个矩形,并且得到了:

enter image description here

如您所见,第一个和第三个点都可以,但是第二个和第四个点是翻转的。 e。从第一点到第三点沿对角线反射。我该如何解决?

2 个答案:

答案 0 :(得分:0)

实际上,不仅第二点和最后一点都被翻转,而且所有4个点都被翻转。第一点和第三点的x和y坐标几乎相同,这就是为什么它看起来正确的原因。

我不确定此问题是从哪里引起的,但我认为是此行引起的:

points_arr = ROI.points - ROI.points.min(axis=0)

可以看到numpy有时以[y,x]格式而不是[x,y]格式返回坐标。

因此,要解决此问题,您可以在cv2.fillConvexPoly()函数之前翻转points_arr变量,这将解决此问题。您可以使用以下行来做到这一点:

points_arr = np.fliplr(points_arr)

答案 1 :(得分:0)

我发现了问题,这与OpenCV怪异的坐标要求有关:

  • 对于在单点(或单点列表)上运行的函数,它需要坐标顺序:(列,行)
  • 对于在绘图点列表上运行的函数(例如,绘图多边形)它要求将这些点逆时针排序,从最低行的点(第二个坐标,Y)开始
  • >

我必须逆时针对点进行排序,然后翻转坐标:

def cut_polygon_ROI_from_img(image: np.ndarray, ROI) -> np.ndarray:
    x, y, w, h = ROI.bounding_rect
    cropped = image[x:x + w, y:y + h].copy()

    points_arr = ROI.points - ROI.points.min(axis=0)
    # OpenCV requires coordinates [column, row] for single points
    points_arr[:, [0, 1]] = points_arr[:, [1, 0]]

    mask = np.zeros(cropped.shape[:2], np.uint8)
    cv2.drawContours(image=mask,
                     contours=[points_arr],
                     contourIdx=-1,
                     color=(255, 255, 255),
                     thickness=-1,  # fill the area bounded by contours
                     lineType=cv2.LINE_AA)

    cropped = cv2.bitwise_and(cropped, cropped, mask=mask)
    return cropped