【问题标题】:Cropping polygon with OpenCV rotates the polygon使用 OpenCV 裁剪多边形会旋转多边形
【发布时间】:2020-08-11 11:19:44
【问题描述】:

我正在尝试使用 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]]

点从左上角顺时针排列。由于某种原因,切割后我得到:

为了检查,我将一个矩形从[ 275 1420](左上角)剪切到[ 454 1616](右下角),我有:

如您所见,第一点和第三点都可以,但第二点和第四点颠倒了,即。 e.从第一点到第三点沿对角线反射。我该如何解决这个问题?

【问题讨论】:

    标签: python image opencv image-processing


    【解决方案1】:

    其实不光是第二个和最后一个点都翻转了,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)
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-28
        • 1970-01-01
        • 1970-01-01
        • 2011-09-08
        • 2018-06-26
        • 1970-01-01
        • 1970-01-01
        • 2015-10-01
        相关资源
        最近更新 更多