Saltar al contenido

¿Cómo uso la función de reasignación de OpenCV?

Investigamos por diferentes foros para así traerte la respuesta para tu problema, si tienes inquietudes puedes dejarnos tu pregunta y contestaremos con mucho gusto.

Solución:

Esto es solo un simple malentendido de la documentación, y no lo culpo a usted, también me tomó algunos torpezas entenderlo. Los documentos son claros, pero esta función probablemente no funcione de la forma esperada; de hecho, funciona en el opuesto dirección de lo que esperaba al principio.

Qué remap()no Lo que debe hacer es tomar las coordenadas de la imagen de origen, transformar los puntos y luego interpolar. Qué remap()lo hace hacer es, por cada píxel en el destino imagen, búsqueda de dónde viene en la imagen de origen y luego asigna un valor interpolado. Debe funcionar de esta manera ya que, para interpolar, debe observar los valores alrededor de la imagen de origen en cada píxel. Déjame expandirme (podría repetirme un poco, pero no lo tomes a mal).

Desde el remap() docs:

mapa1 – El primer mapa de cualquiera (x,y) puntos o simplemente x valores que tienen el tipo CV_16SC2 , CV_32FC1 , o CV_32FC2 . Ver convertMaps() para obtener detalles sobre la conversión de una representación de punto flotante en punto fijo para la velocidad.

mapa2 – El segundo mapa de y valores que tienen el tipo CV_16UC1 , CV_32FC1 , o ninguno (mapa vacío si map1 es (x,y) puntos), respectivamente.

El verbage aquí en map1 con el primero map of … “es algo engañoso. Recuerde, estas son estrictamente las coordenadas de donde se mapea su imagen de… los puntos se están mapeando desrc a map_x(x, y), map_y(x, y) y luego se coloca en dst a x, y. Y deben tener la misma forma que la imagen que desea deformar. para. Tenga en cuenta la ecuación que se muestra en los documentos:

dst(x,y) =  src(map_x(x,y),map_y(x,y))

Aquí map_x(x, y) está mirando hacia arriba map_x en las filas y columnas dadas por x, y. Luego, la imagen se evalúa en esos puntos. Está buscando las coordenadas mapeadas de x, y en srcy luego asignar ese valor a x, y en dst. Si miras esto el tiempo suficiente, comienza a tener algún sentido. En píxel (0, 0) en la imagen del nuevo destino, miro map_x y map_y que me dice la ubicación del píxel correspondiente en la imagen de origen, y luego puedo asignar un valor interpolado en (0, 0) en la imagen de destino mirando los valores cercanos en la fuente. Esta es una de las razones fundamentales por las que remap() funciona de esta manera; necesita saber de donde vino un pixel para que pueda ver los píxeles vecinos para interpolar.

Ejemplo pequeño y artificial

img = np.uint8(np.random.rand(8, 8)*255)
#array([[230,  45, 153, 233, 172, 153,  46,  29],
#       [172, 209, 186,  30, 197,  30, 251, 200],
#       [175, 253, 207,  71, 252,  60, 155, 124],
#       [114, 154, 121, 153, 159, 224, 146,  61],
#       [  6, 251, 253, 123, 200, 230,  36,  85],
#       [ 10, 215,  38,   5, 119,  87,   8, 249],
#       [  2,   2, 242, 119, 114,  98, 182, 219],
#       [168,  91, 224,  73, 159,  55, 254, 214]], dtype=uint8)

map_y = np.array([[0, 1], [2, 3]], dtype=np.float32)
map_x = np.array([[5, 6], [7, 10]], dtype=np.float32)
mapped_img = cv2.remap(img, map_x, map_y, cv2.INTER_LINEAR)
#array([[153, 251],
#       [124,   0]], dtype=uint8)

Entonces, ¿qué está pasando aquí? Recuerde que estos son los índices de img que se mapeará A la fila y columna en la que se encuentran. En este caso, es más fácil examinar las matrices:

map_y
=====
0  1
2  3

map_x
=====
5  6
7  10

Entonces, la imagen de destino en (0, 0) tiene el mismo valor que la imagen de origen en map_y(0, 0), map_x(0, 0) = 0, 5 y la imagen de origen en la fila 0 y la columna 5 es 153. Tenga en cuenta que en la imagen de destino mapped_img[0, 0] = 153. No hay interpolación aquí ya que las coordenadas de mi mapa son números enteros exactos. También incluí un índice fuera de límites (map_x[1, 1] = 10, que es más grande que el ancho de la imagen), y observe que simplemente se le asigna el valor 0 cuando está fuera de los límites.

Ejemplo de caso de uso completo

Aquí hay un ejemplo de código completo, usando una homografía de verdad del suelo, deformando las ubicaciones de los píxeles manualmente y usando remap() para luego mapear la imagen de los puntos transformados. Tenga en cuenta aquí que mi homografía se transforma true_dstparasrc. Por lo tanto, hago un conjunto de tantos puntos que quiero y luego calculo dónde se encuentran esos puntos en la imagen de origen transformándolos con la homografía. Luego remap() se utiliza para buscar esos puntos en la imagen de origen y asignarlos a la imagen de destino.

import numpy as np
import cv2

# read images
true_dst = cv2.imread("img1.png")
src = cv2.imread("img2.png")

# ground truth homography from true_dst to src
H = np.array([
    [8.7976964e-01,   3.1245438e-01,  -3.9430589e+01],
    [-1.8389418e-01,   9.3847198e-01,   1.5315784e+02],
    [1.9641425e-04,  -1.6015275e-05,   1.0000000e+00]])

# create indices of the destination image and linearize them
h, w = true_dst.shape[:2]
indy, indx = np.indices((h, w), dtype=np.float32)
lin_homg_ind = np.array([indx.ravel(), indy.ravel(), np.ones_like(indx).ravel()])

# warp the coordinates of src to those of true_dst
map_ind = H.dot(lin_homg_ind)
map_x, map_y = map_ind[:-1]/map_ind[-1]  # ensure homogeneity
map_x = map_x.reshape(h, w).astype(np.float32)
map_y = map_y.reshape(h, w).astype(np.float32)

# remap!
dst = cv2.remap(src, map_x, map_y, cv2.INTER_LINEAR)
blended = cv2.addWeighted(true_dst, 0.5, dst, 0.5, 0)
cv2.imshow('blended.png', blended)
cv2.waitKey()

Reasignar para deformaciones

Imágenes y homografías de verdad fundamental del Visual Geometry Group de Oxford.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *