2012-04-28 23 views
18

Esta pregunta está relacionada con esta pregunta: How to remove convexity defects in sudoku squareTransformación de imágenes en OpenCV

Yo estaba tratando de poner en práctica nikie's answer en Mathematica to OpenCV-Python. Pero estoy atascado en el último paso del procedimiento.

es decir Tengo los todos los puntos de intersección en la plaza, como a continuación:

enter image description here

Ahora, quiero transformar esto en un cuadrado perfecto de tamaño (450 450) como se indica a continuación:

enter image description here

(No importa la diferencia de brillo de dos imágenes).

Pregunta: ¿Cómo puedo hacer esto en OpenCV-Python? Estoy usando la versión cv2.

+2

Como sugirió en su respuesta, solo use las transformaciones estándar (la que intentó usar en su primera pregunta) para cada celda individual ... – etarion

+0

Utilicé la perspectiva warp que utilizó 4 esquinas para transformar. ¿Estás diciendo que utilizas el mismo tomando 4 puntos de cada celda? ¿no es un proceso lento? –

+0

¿Estás hablando de programación integrada? Supongo que no, ya que estás usando Python ... en una máquina de escritorio, no, no debería ser notorio, ya que son solo 81 celdas ... – etarion

Respuesta

30

Además de la sugerencia de etarion, también podría usar la función remap. Escribí un guión rápido para mostrar cómo puedes hacer esto. Como ve la codificación esto es realmente fácil en Python. Esta es la imagen de la prueba:

distorted image

y este es el resultado después de la deformación:

warped image

Y aquí está el código:

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) 

supongo que puede google y encuentra qué griddata hace. En resumen, hace interpolación y aquí lo usamos para convertir mapeos dispersos a mapeos densos ya que cv2.remap requiere mapeos densos. Solo tenemos que convertir los valores en float32 ya que OpenCV se queja del tipo float64. Por favor déjame saber cómo va.

actualización: Si no quiere depender de Scipy, una forma es aplicar la función de interpolación 2d en su código, por ejemplo, ver el código fuente de gridData en Scipy o uno más sencillo como esto http://inasafe.readthedocs.org/en/latest/_modules/engine/interpolation2d.html que solo depende del numpy Sin embargo, sugiero utilizar Scipy u otra biblioteca para esto, aunque veo por qué requerir solo CV2 y numpy puede ser mejor para un caso como este. Me gustaría escuchar cómo tu código final resuelve Sudokus.

+1

Bien, eso fue maravilloso. Esto es lo que estaba buscando. Sabía que podía usar 'cv2.remap', pero no cómo usarlo. Pero, ¿es necesario usar scipy? ¿no se puede hacer con numpy y cv2 solamente? También puede ser el mismo método utilizado para toda la imagen en un solo paso (es decir, sin dividir en sub-bloques)? –

+0

Se hizo para una parte de la imagen para que sea más fácil escribir las coordenadas de los puntos rojos. En "fuente" tiene las coordenadas de los puntos rojos que ya ha detectado y en "destino" sus coordenadas en la cuadrícula regular. Si hubiera compartido su código, podría mostrarle cómo hacerlo en el código, sin necesidad de dividir la imagen en subregiones. Reg. sin uso de Scipy, mira la actualización en la respuesta. – fireant

+0

'Me gustaría saber cómo su código final resuelve el Sudokus'. ¿Cuál quieres? cómo resolver la cuadrícula de sudoku? o la versión de opencv sobre cómo hacer ocr, etc.? (resolver la cuadrícula de sudoku es tomada de un blog, una parte, etc. escrita por mí mismo) –

0

si tiene puntos de origen y puntos finales (solo necesita 4), puede conectarlos a cv2.getPerspectiveTransform, y usar ese resultado en cv2.warpPerspective. Te da un buen resultado plano.

Cuestiones relacionadas