【问题标题】:Apply transform matrix to warpTransform in OpenCV将变换矩阵应用于 OpenCV 中的 warpTransform
【发布时间】:2019-01-08 22:58:43
【问题描述】:

所以,我想转换一张图片,但真的找不到使用 OpenCV 的合适方法。

我有图像的第一件事可以说是 500x600px,其中有一个扭曲的东西我想“拉直”看图像:

我正在像这样获得数独的轮廓:

cropped_image, contours, _ = 
cv2.findContours(cropped_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
max_contour = max(contours, key=cv2.contourArea)

然后我得到max_contour 和图像极端像素(左上、右上、右下和左下)并得到变换矩阵并像这样变换图像:

x, y = cropped_image.shape
image_extreme_pixels = np.array([[0, y], [x, y], [x, 0], [0, 0]], dtype=np.float32)
c_x, c_y = [], []
for i in contour:
  c_x.append(i[0][0])
  c_y.append(i[0][1])
contour_extreme_pixels = np.array([
  [min(c_x), max(c_y)],
  [max(c_x), max(c_y)],
  [max(c_x), min(c_y)],
  [min(c_x), min(c_y)]],
  dtype=np.float32)

t_matrix = cv2.getPerspectiveTransform(contour_extreme_pixels, image_extreme_pixels)

transformed_image = cv2.warpPerspective(cropped_image, t_matrix, (y, x))


plt.imshow(cropped_image, interpolation='nearest', cmap=plt.cm.gray)

但是当我查看图像时,它以一种奇怪的方式发生了变化。我想拉伸数独的顶部,使其轮廓笔直。

您能指出我的代码有什么问题吗? 我假设这可能是我创建 4 个极端像素然后放入 getPerspectiveTransform 以获取转换矩阵但尚未使其工作的方式。

【问题讨论】:

    标签: python opencv


    【解决方案1】:

    假设您已经准确地找出了数独的角点,您可以将输入图像仿射变换为:

    # Hard coded the points here assuming that you already have 4 corners of sudoku image
    sudoku_corner_points = np.float32([[235, 40], [1022, 55], [190, 875], [1090, 880]])
    canvas = np.ones((500, 500), dtype=np.uint8)
    dst_points = np.float32([[0, 0], [500, 0], [0, 500], [500, 500]])
    
    t_matrix = cv2.getPerspectiveTransform(sudoku_corner_points, dst_points)
    
    transformed_image = cv2.warpPerspective(img, t_matrix, (500, 500))
    

    【讨论】:

    • sudoku_corner_points 和 dst_points 的顺序重要吗?
    • 仿射变换不同于透视变换
    • 我假设我发现的数独的角点不正确,因为您的代码不能解决我的问题,我正试图找出问题所在
    【解决方案2】:

    结果证明我发现的极值点是不正确的。 在我们期望为矩形的形状中找到 4 个极值点的正确方法(其中一种)是这样的:

    def get_contour_extreme_points(img, contour):
      m_point = image_center(img)
      l1, l2, l3, l4 = 0, 0, 0, 0
      p1, p2, p3, p4 = 0, 0, 0, 0
    
      for point in contour:
        d = distance(m_point, point[0])
        if inside_bottom_right(m_point, point[0]) and l1 < d:
          l1 = d
          p1 = point[0]
          continue
        if inside_bottom_left(m_point, point[0]) and l2 < d:
          l2 = d
          p2 = point[0]
          continue
        if inside_top_right(m_point, point[0]) and l3 < d:
          l3 = d
          p3 = point[0]
          continue
        if inside_top_left(m_point, point[0]) and l4 < d:
          l4 = d
          p4 = point[0]
          continue
    
      return np.float32([p1, p2, p3, p4])
    
    def inside_bottom_right(center, point):
      return center[0] < point[0] and center[1] < point[1]
    
    def inside_bottom_left(center, point):
      return center[0] > point[0] and center[1] < point[1]
    
    def inside_top_right(center, point):
      return center[0] < point[0] and center[1] > point[1]
    
    def inside_top_left(center, point):
      return center[0] > point[0] and center[1] > point[1]
    
    def distance(p1, p2):
      return math.sqrt( ((p1[0]-p2[0])**2)+((p1[1]-p2[1])**2) )
    
    def image_center(img):
      x, y = img.shape
    
      return tuple([x/2, y/2])
    

    那么我必须小心图像的 4 个极值点的顺序。应该是这样的:

    x, y = img.shape
    img_extreme_points = np.float32([[x, y], [0, y], [x, 0], [0, 0]]) 
    

    所以首先是右下极点,然后是左下角、右上角和左上角。只要极值点索引正确对应,矩阵也将被正确计算。

    【讨论】:

      猜你喜欢
      • 2014-03-31
      • 2012-12-14
      • 1970-01-01
      • 2018-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多