Преобразование перспективы в OPENCV PYTHON

#python #numpy #opencv

#python #numpy #opencv

Вопрос:

Я пытаюсь выполнить перспективное преобразование головоломки судоку. Ожидаемое преобразование происходит только с левой стороны. Пожалуйста, помогите мне, указав на мою ошибку.

Входное изображение:

введите описание изображения здесь

Ожидаемое выходное изображение:

введите описание изображения здесь

Результат, который я получаю:

введите описание изображения здесь

Углы головоломки судоку, найденные с помощью cv2.approxpolydp(), следующие:

 top_left = [71,62]
top_right = [59, 418]
bottom_right = [443, 442]
bottom_left = [438, 29]
  

Форма выходного изображения равна [300,300].

Соответствующие выходные координаты :

 output_top_left = [0,0]
output_top_right = [0, 299]
output_bottom_right = [299, 299]
output_bottom_left = [299,0]
  

Ниже приведен код, который я использовал для преобразования перспективы:

 #corners = [[71,62], [59, 418], [443, 442], [438, 29]]
new = np.float32([[0,0], [0,299], [299,299], [299,0]])
M = cv2.getPerspectiveTransform(np.float32(corners), new)
dst = cv2.warpPerspective(gray, M, (300,300))
  

Сгенерированная матрица преобразования :

 [[ 9.84584842e-01  3.31882531e-02 -7.19631955e 01]
 [ 8.23993265e-02  9.16380389e-01 -6.26659363e 01]
 [ 4.58051741e-04  1.45318012e-04  1.00000000e 00]]
  

Ответ №1:

У вас поменялись местами координаты X, Y. Python / OpenCV требует, чтобы они были перечислены как X, Y (даже если вы определяете их как значения numpy). Массив, который вы должны указать для getPerspectiveTransform, должен содержать их как X, Y.

Ввод:

введите описание изображения здесь

 import numpy as np
import cv2

# read input
img = cv2.imread("sudoku.jpg")

# specify desired output size 
width = 350
height = 350

# specify conjugate x,y coordinates (not y,x)
input = np.float32([[62,71], [418,59], [442,443], [29,438]])
output = np.float32([[0,0], [width-1,0], [width-1,height-1], [0,height-1]])

# compute perspective matrix
matrix = cv2.getPerspectiveTransform(input,output)

print(matrix.shape)
print(matrix)

# do perspective transformation setting area outside input to black
imgOutput = cv2.warpPerspective(img, matrix, (width,height), cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=(0,0,0))
print(imgOutput.shape)

# save the warped output
cv2.imwrite("sudoku_warped.jpg", imgOutput)

# show the result
cv2.imshow("result", imgOutput)
cv2.waitKey(0)
cv2.destroyAllWindows()
  

Результаты:

введите описание изображения здесь

Комментарии:

1. Привет, frmw42, можем ли мы автоматизировать перспективное преобразование, чтобы можно было автоматически определять координаты X, Y

2. Извините, я не уверен, что понимаю ваш вопрос. Пожалуйста, уточните.

3. Если вы спрашиваете, как получить углы входного изображения, то самым простым методом было бы извлечь контуры и найти контур самого большого прямоугольника — контур головоломки судоку. Затем используйте approxPolyDP(), чтобы получить четырехугольник и использовать 4 угла четырехугольника. Другим способом было бы зарегистрировать головоломку в другой головоломке, которая уже была лицом к лицу, используя SIFT или ORB, чтобы найти соответствующие контрольные точки. См. docs.opencv.org/3.4/dc/dc3/tutorial_py_matcher.html

4. Что можно сделать, если я хочу деформировать только небольшую часть целевого изображения, которая не является прямоугольной, а определяется 4 углами? Я не вижу warpPerspective возможности использовать маску или ограничения ROI, чтобы выполнять там только обратную деформацию. Как к этому подойти?

5. Деформируйте все изображение и обрезайте. Или сделайте прозрачным внешний размер входных данных и деформируйте его.

Ответ №2:

Вы должны отметить, что:

  1. Координаты меняются местами: ширина, высота
  2. Масштабируется назначение: соотношение первого места: ширина / высота, соотношение второго места: высота / ширина
  3. Порядок координат точек не имеет значения, но исходные и конечные точки должны соответствовать друг другу.