matlab - una - Alinear imágenes rgb y de profundidad ya capturadas
procesamiento digital de imagenes con matlab pdf (2)
Estoy tratando de alinear dos imágenes, una rgb y otra profundidad usando MATLAB. Tenga en cuenta que he verificado varios lugares para esto, como here , here que requiere un dispositivo kinect, y here here que dice que los parámetros de la cámara son necesarios para la calibración. También me sugirieron usar la GEOMETRÍA EPIPOLAR para unir las dos imágenes, aunque no sé cómo. El conjunto de datos al que me refiero se da en el conjunto de datos de cara rgb-dt . Uno de estos ejemplos se ilustra a continuación:
La verdad básica que básicamente significa que los cuadros delimitadores que especifican la región de la cara de interés ya se proporcionan y los uso para recortar solo las regiones de la cara. El código matlab se ilustra a continuación:
I = imread(''1.jpg'');
I1 = imcrop(I,[218,198,158,122]);
I2 = imcrop(I,[243,209,140,108]);
figure, subplot(1,2,1),imshow(I1);
subplot(1,2,2),imshow(I2);
Las dos imágenes recortadas rgb y profundidad se muestran a continuación:
¿Hay alguna manera de registrar / alinear las imágenes? Tomé la pista de here donde se ha utilizado el operador básico básico en las imágenes rgb y de profundidad para generar un mapa de borde y luego se necesitarán generar puntos clave para propósitos de coincidencia. Los mapas de bordes para ambas imágenes se generan aquí.
Sin embargo, son tan ruidosos que no creo que podamos hacer coincidir puntos clave para estas imágenes.
¿Alguien puede sugerir algunos algoritmos en matlab para hacer lo mismo?
Bueno, he intentado hacerlo después de leer muchos blogs y todo. Todavía no estoy seguro de si lo estoy haciendo correctamente o no. Por favor, siéntase libre de hacer comentarios si algo no funciona. Para esto utilicé un envío de fex de mathworks que se puede encontrar aquí: función ginputc .
El código matlab es el siguiente:
clc; clear all; close all;
% no of keypoint
N = 7;
I = imread(''2.jpg'');
I = rgb2gray(I);
[Gx, Gy] = imgradientxy(I, ''Sobel'');
[Gmag, ~] = imgradient(Gx, Gy);
figure, imshow(Gmag, [ ]), title(''Gradient magnitude'')
I = Gmag;
[x,y] = ginputc(N, ''Color'' , ''r'');
matchedpoint1 = [x y];
J = imread(''2.png'');
[Gx, Gy] = imgradientxy(J, ''Sobel'');
[Gmag, ~] = imgradient(Gx, Gy);
figure, imshow(Gmag, [ ]), title(''Gradient magnitude'')
J = Gmag;
[x, y] = ginputc(N, ''Color'' , ''r'');
matchedpoint2 = [x y];
[tform,inlierPtsDistorted,inlierPtsOriginal] = estimateGeometricTransform(matchedpoint2,matchedpoint1,''similarity'');
figure; showMatchedFeatures(J,I,inlierPtsOriginal,inlierPtsDistorted);
title(''Matched inlier points'');
I = imread(''2.jpg''); J = imread(''2.png'');
I = rgb2gray(I);
outputView = imref2d(size(I));
Ir = imwarp(J,tform,''OutputView'',outputView);
figure; imshow(Ir, []);
title(''Recovered image'');
figure,imshowpair(I,J,''diff''),title(''Difference with original'');
figure,imshowpair(I,Ir,''diff''),title(''Difference with restored'');
Paso 1
Utilicé el detector de bordes sobel para extraer los bordes de las imágenes de profundidad y rgb y luego usé valores de umbral para obtener el mapa de bordes. Trabajaré principalmente solo con la magnitud del gradiente. Esto me da dos imágenes como esta:
Paso 2
Luego uso la función
ginput
o
ginputc
para marcar puntos clave en ambas imágenes.
La correspondencia entre los puntos la establecí de antemano.
Intenté usar las funciones
SURF
pero no funcionan bien en imágenes de profundidad.
Paso 3
Use la transformación
tform
estimategeometrictransform
para obtener la forma de matriz de transformación y luego use esta matriz para recuperar la posición original de la imagen movida.
El siguiente conjunto de imágenes cuenta esta historia.
De acuerdo, sigo creyendo que los resultados pueden mejorarse aún más si las selecciones de puntos clave en cualquiera de las imágenes se realizan de manera más juiciosa. También creo que el método @Specktre es mejor. Acabo de notar que usé un par de imágenes por separado en mi respuesta en comparación con el de la pregunta. Ambas imágenes provienen del mismo conjunto de datos que se encuentra aquí vap rgb-dt dataset .
prólogo
Esta respuesta se basa en la respuesta anterior mía:
- ¿La vista infrarroja de Kinect tiene un desplazamiento con la vista de profundidad de Kinect?
Recorto manualmente su imagen de entrada para separar los colores y las imágenes de profundidad (ya que mi programa las necesita separadas. Esto podría causar un cambio de desplazamiento menor en pocos píxeles. Además, como no tengo las profundidades (la imagen de profundidad es de 8
8bit
solo debido a la escala de grises
RGB
) entonces la precisión de profundidad con la que trabajo es muy pobre, vea:
Así que mis resultados se ven afectados por todo esto negativamente. De todos modos, esto es lo que debes hacer:
-
determinar el campo de visión para ambas imágenes
Así que encuentre alguna característica medible visible en ambas imágenes. Cuanto más grande sea el tamaño, más preciso será el resultado. Por ejemplo, elijo estos:
-
formar una nube de puntos o malla
Utilizo la imagen de profundidad como referencia, por lo que mi nube de puntos está en su FOV . Como no tengo las distancias, sino valores de 8
8bit
, lo convertí a cierta distancia multiplicando por constante. Así que escaneo imágenes de profundidad completa y por cada píxel creo puntos en mi matriz de nubes de puntos. Luego convierta la coordenada de píxeles del departamento a FOV de imagen en color y copie también su color. algo como esto (en C ++ ):picture rgb,zed; // your input images struct pnt3d { float pos[3]; DWORD rgb; pnt3d(){}; pnt3d(pnt3d& a){ *this=a; }; ~pnt3d(){}; pnt3d* operator = (const pnt3d *a) { *this=*a; return this; }; /*pnt3d* operator = (const pnt3d &a) { ...copy... return this; };*/ }; pnt3d **xyz=NULL; int xs,ys,ofsx=0,ofsy=0; void copy_images() { int x,y,x0,y0; float xx,yy; pnt3d *p; for (y=0;y<ys;y++) for (x=0;x<xs;x++) { p=&xyz[y][x]; // copy point from depth image p->pos[0]=2.000*((float(x)/float(xs))-0.5); p->pos[1]=2.000*((float(y)/float(ys))-0.5)*(float(ys)/float(xs)); p->pos[2]=10.0*float(DWORD(zed.p[y][x].db[0]))/255.0; // convert dept image x,y to color image space (FOV correction) xx=float(x)-(0.5*float(xs)); yy=float(y)-(0.5*float(ys)); xx*=98.0/108.0; yy*=106.0/119.0; xx+=0.5*float(rgb.xs); yy+=0.5*float(rgb.ys); x0=xx; x0+=ofsx; y0=yy; y0+=ofsy; // copy color from rgb image if in range p->rgb=0x00000000; // black if ((x0>=0)&&(x0<rgb.xs)) if ((y0>=0)&&(y0<rgb.ys)) p->rgb=rgb2bgr(rgb.p[y0][x0].dd); // OpenGL has reverse RGBorder then my image } }
donde
**xyz
es mi matriz 2D de nube de puntos asignada a una resolución de imagen de profundidad. Lapicture
es mi clase de imagen para DIP, así que aquí algunos miembros relevantes:-
xs,ys
es la resolución de la imagen en píxeles -
p[ys][xs]
es el acceso directo de píxeles de la imagen como unión deDWORD dd; BYTE db[4];
DWORD dd; BYTE db[4];
entonces puedo acceder al color como una variable de 32 bits o cada canal de color por separado. -
rgb2bgr(DWORD col)
simplemente reordena los canales de color de RGB a BGR .
-
-
hazlo
Yo uso OpenGL para esto, así que aquí el código:
glBegin(GL_QUADS); for (int y0=0,y1=1;y1<ys;y0++,y1++) for (int x0=0,x1=1;x1<xs;x0++,x1++) { float z,z0,z1; z=xyz[y0][x0].pos[2]; z0=z; z1=z0; z=xyz[y0][x1].pos[2]; if (z0>z) z0=z; if (z1<z) z1=z; z=xyz[y1][x0].pos[2]; if (z0>z) z0=z; if (z1<z) z1=z; z=xyz[y1][x1].pos[2]; if (z0>z) z0=z; if (z1<z) z1=z; if (z0 <=0.01) continue; if (z1 >=3.90) continue; // 3.972 pre vsetko nad .=3.95m a 4.000 ak nechyti vobec nic if (z1-z0>=0.10) continue; glColor4ubv((BYTE* )&xyz[y0][x0].rgb); glVertex3fv((float*)&xyz[y0][x0].pos); glColor4ubv((BYTE* )&xyz[y0][x1].rgb); glVertex3fv((float*)&xyz[y0][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x1].rgb); glVertex3fv((float*)&xyz[y1][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x0].rgb); glVertex3fv((float*)&xyz[y1][x0].pos); } glEnd();
Debe agregar la inicialización de OpenGL y la configuración de la cámara, etc. de grueso. Aquí el resultado no alineado:
-
alinearlo
Si nota que agregué
ofsx,ofsy
variables acopy_images()
. Este es el desplazamiento entre cámaras. Los cambio en las pulsaciones de teclas de flechas por1
píxel y luego llamocopy_images
y renderizo el resultado. De esta manera, encontré manualmente el desplazamiento muy rápidamente:Como puede ver, el desplazamiento es
+17
píxeles en el eje xy+4
píxeles en el eje y. Aquí vista lateral para ver mejor las profundidades:
Espero que ayude un poco