Преобразование изображения в OpenCV

Этот вопрос связан с этим вопросом: How to remove convexity defects in sudoku square

Я пытался реализовать nikie's answer в Mathematica to OpenCV-Python, Но я застрял на последнем этапе процедуры.

т.е. я получил все точки пересечения в квадрате, как показано ниже:

Теперь я хочу превратить это в идеальный квадрат размером (450 450), как показано ниже:

(Не берите в голову разницу яркости двух изображений).

Вопрос: Как я могу сделать это в OpenCV-Python? я использую cv2 версия.

2 ответа

Решение

Помимо предложения etarion, вы также можете использовать функцию remap. Я написал быстрый сценарий, чтобы показать, как вы можете сделать это. Как вы видите, на Python это действительно просто. Это тестовое изображение:

искаженное изображение

и это результат после деформации:

искаженное изображение

И вот код:

import cv2
from scipy.interpolate import griddata
import numpy as np

grid_x, grid_y = np.mgrid[0:149:150j, 0:149:150j]
destination = np.array([[0,0], [0,49], [0,99], [0,149],
                  [49,0],[49,49],[49,99],[49,149],
                  [99,0],[99,49],[99,99],[99,149],
                  [149,0],[149,49],[149,99],[149,149]])
source = np.array([[22,22], [24,68], [26,116], [25,162],
                  [64,19],[65,64],[65,114],[64,159],
                  [107,16],[108,62],[108,111],[107,157],
                  [151,11],[151,58],[151,107],[151,156]])
grid_z = griddata(destination, source, (grid_x, grid_y), method='cubic')
map_x = np.append([], [ar[:,1] for ar in grid_z]).reshape(150,150)
map_y = np.append([], [ar[:,0] for ar in grid_z]).reshape(150,150)
map_x_32 = map_x.astype('float32')
map_y_32 = map_y.astype('float32')

orig = cv2.imread("tmp.png")
warped = cv2.remap(orig, map_x_32, map_y_32, cv2.INTER_CUBIC)
cv2.imwrite("warped.png", warped)

Я полагаю, вы можете Google и найти, что делает griddata. Короче говоря, он выполняет интерполяцию, и здесь мы используем его для преобразования разреженных отображений в плотные отображения, поскольку cv2.remap требует плотных отображений. Нам просто нужно преобразовать значения в float32, так как OpenCV жалуется на тип float64. Пожалуйста, дайте мне знать, как это происходит.

Обновление: если вы не хотите полагаться на Scipy, один из способов - реализовать функцию 2D-интерполяции в вашем коде, например, посмотреть исходный код griddata на Scipy или более простой, например, http://inasafe.readthedocs.org/en/latest/_modules/engine/interpolation2d.html который зависит только от numpy. Тем не менее, я бы предложил использовать для этого Scipy или другую библиотеку, хотя я понимаю, почему для такого случая лучше использовать только CV2 и numpy. Я хотел бы услышать, как ваш окончательный код решает судоку.

Если у вас есть исходные и конечные точки (вам нужно только 4), вы можете подключить их к cv2.getPerspectiveTransform и использовать этот результат в cv2.warpPerspective. Дает вам хороший плоский результат.

Другие вопросы по тегам