将转换矩阵应用于OpenCV中的warpTransform

时间:2018-12-28 13:57:43

标签: python opencv

因此,我想变换图像,但实际上找不到使用OpenCV进行图像处理的正确方法。

我有图像的第一件事是说500x600px,其中有一个我想“拉直”的扭曲的东西,请参见图像: image with distorted sudoku

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

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中以获取转换矩阵,但尚未使其起作用。

2 个答案:

答案 0 :(得分:0)

假设您已正确找到数独的角点,则可以将输入图像进行仿射变换为:

# 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))

enter image description here

答案 1 :(得分:0)

所以事实证明,我发现的极端点是不正确的。 在我们期望是矩形的形状中找到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]]) 

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