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

2024-04-24 18:39:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图使用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从第一点到第三点沿对角线反射。我怎样才能解决这个问题


Tags: rect图像imagenpmaskcv2opencvpoints
2条回答

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

我不确定这个问题是从哪里产生的,但我认为它是从这一行产生的:

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

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

因此,要解决这个问题,可以在cv2.FillConverExpoly()函数之前翻转points_arr变量,这样就可以解决问题。您可以使用以下行执行此操作:

points_arr = np.fliplr(points_arr)

我发现了这个问题,它与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

相关问题 更多 >