Documente Academic
Documente Profesional
Documente Cultură
Scanner 3D
Introduccin:
La reconstruccin 3D es el proceso mediante el cual, objetos reales, son
reproducidos en la memoria de una computadora, manteniendo sus
caractersticas fsicas (dimensiones, volumen y forma). Existen dentro de la
visin artificial, multitud de tcnicas de reconstruccin y mtodos de mallado
3D, cuyo objetivo principal es obtener un algoritmo que sea capaz de realizar la
conexin del conjunto de puntos representativos del objeto en forma de
elementos de superficie, ya sean tringulos, cuadrados o cualquier otra forma
geomtrica.
Los algoritmos desarrollados hasta el momento, se debaten entre el coste
computacional y la calidad del mallado obtenido. A priori, los algoritmos que
trabajan con nubes de puntos, tratan de obtener la denominada matriz de
conexiones. Esta matriz, almacena que puntos del conjunto inicial deben estar
conectados entre s. Si empleamos tringulos (mtodo bastante comn), esta
matriz tiene la forma de 3 x n (siendo el nmero total de tringulos que
contiene la pieza), es decir que cada fila de la matriz representa un tringulo
en el plano o en el espacio.
La eficiencia del algoritmo es la que define la calidad final del mallado. Si
suponemos un conjunto de puntos mal representado, existirn puntos definidos
que no cumplan las condiciones ptimas para el mallado. Los puntos que se
encuentran muy cercanos entre s, los puntos ruidosos y los puntos
redundantes, no ofrecen ninguna informacin para la reconstruccin.
Imaginemos por ejemplo, que si queremos representar un cubo en el espacio,
simplemente con ocho puntos y doce tringulos seran suficiente, el resto de la
informacin sera redundante.
En nuestro caso, la reconstruccin tridimensional, se realiza partiendo de
un conjunto de puntos demasiado grande, en el cual, una gran parte de los
puntos no ofrecen ninguna informacin y deben ser eliminados. Como se puede
ver en la Figura, la representacin de la nube de puntos (a la derecha), existen
puntos ruidosos y puntos innecesarios. El primer objetivo es la reduccin del
conjunto de puntos, que se detalla en el apartado siguiente.
A la hora de trabajar con sistemas de visin 3D, uno de los primeros asuntos
que hay que abordar es la calibracin de las cmaras. Este es un factor
sumamente importante y, aunque uno quisiera ponerse manos a la obra lo
antes posible con el problema de visin 3D a resolver, es una tarea que hay
que realizar a conciencia para no comprometer la precisin de todo el sistema.
La calibracin puede ser un trabajo arduo especialmente cuando se tiene una
configuracin multiview, es decir, con muchas cmaras, pues hay que repetir el
proceso con cada una de ellas.
Afortunadamente, la librera OpenCV cuenta con un mdulo especial de
funciones para calibracin de cmaras y reconstruccin 3D que resulta de gran
ayuda: calib3d.
En esta entrada voy a explicar los pasos necesarios para hacer una buena
calibracin utilizando OpenCV.
Este tablero debe ser un plano, por tanto es conveniente fijarlo sobre una base
plana rgida. En mi caso he usado una caja de cartn. Aunque en la imagen se
ve la esquina del papel algo despegada, lo importante es que se mantenga
plano el interior del patrn.
Funcin findChessboardCorners. Esta funcin recibe una imagen donde
aparezca el tablero, encuentra sus esquinas interiores y nos devuelve las
coordenadas en un vector. La imagen debe estar en niveles de gris. Adems,
hay que indicarle la cantidad de filas y columnas de nuestro tablero, pero no de
los casilleros, sino de las esquinas interiores:
Una buena opcin es implementar una pequea funcin que nos permita con
un botn del teclado ir capturando imgenes en tiempo real a medida que
movemos el tablero enfrente de la cmara. Al pulsar el botn del teclado, la
funcin slo debera guardar una imagen si es til, o sea, si el patrn es
reconocido por la funcin findChessboardCorners.
Sobre bordes y gradiantes
El Gradiante de una imagen y los bordes de la misma: No son lo mismo!
Es cierto que el gradiante de una imagen revela la ubicacin de los bordes,
pero hay otras funciones que muestran los bordes de una imagen sin ser el
gradiante.
Por lo tanto, hay que tener cuidado, cuando algn algoritmo de procesamiento
requiere el clculo del gradiante, de no sustituirlo por un simple mapa de
bordes.
En Matlab: una forma de calcular el gradiente es el filtro de Sobel. Muy bien,
Matlab proporciona la funcin edge que, con la propiedad sobel, permite filtrar
una imagen y obtener sus bordes, sin embargo, aunque el gradiente
ciertamente es un detector de bordes, no es el gradiente lo que edge devuelve,
sino una imagen binarizada con cierto umbral que no refleja la magnitud ni el
signo de las derivadas del gradiente. La siguiente imagen muestra el resultado
que se obtendra. Observar que los bordes tienen magnitud 1 en todos sus
puntos.
Procedimiento realizado:
grabar
el
"stdafx.h"
<opencv2\opencv.hpp>
<opencv\highgui.h>
<opencv\cv.h>
<opencv\cxcore.h>
<math.h>
<stdio.h>
PI 3.14159265
SIZE 200
// buffer size
MAXFRAMES 60
// maximum # video frames for 360 degrees
MAXCOLS 640
// video width
MAXROWS 480
// video heigth
CvPoint
centerPoint1, axisPoint1, axisPoint2, roiPoint1, roiPoint2;
IplImage*
frame, *frame2;
int
drag = 0; // defines if you are dragging the mouse
int
numPoints = 0; // used to count # of profile points found
CvScalar
c1;
const char* message = "";
char buf[SIZE];
CvFont font;
double hScale = 0.4; // font hScale
double vScale = 0.4; // font vScale
int lineWidth = 1; // font lineWidth
void on_mouse_axis(int event, int x, int y, int flags, void* param) {
/* user press left button */
if (event == CV_EVENT_LBUTTONDOWN && !drag) {
axisPoint1 = cvPoint(x, y);
drag = 1;
}
************
// cycle throught all pixels and find highest value in each row
// *********** convert myPoints array to vector to allow dynamic size
// y is height (Z)
for (int y = 0; y<frame->height; ++y) {
//next row, reset highest value
highestVal = 0;
// x is radius
for (int x = 0; x<frame->width; ++x) {
c1 = cvGetAt(frame, y, x);
// if point is inside region of interest
if (x >= roiPoint1.x && x <= roiPoint2.x && y >=
roiPoint1.y && y <= roiPoint2.y) {
/* DEBUG CODE BELOW */
/*
frame2 = (IplImage*)
cvClone(frame);
_snprintf_s(buf, SIZE, "b=%f g=%f r=%f\n",
c1.val[0], c1.val[1], c1.val[2]); //windows
message = buf;
cvPutText(frame2,message, cvPoint(10,15), &font,
cvScalar(255,255,255));
cvLine(frame2, cvPoint(x,y), cvPoint(x,y),
CV_RGB(255, 0, 0), 4, CV_AA, 0 );
cvShowImage( "3D SCANNER", frame2 );
cvWaitKey(0);*/
// if redness of point (2x red - blue - green = red)
redVal = c1.val[2] * 2 - c1.val[0] - c1.val[1];
// brightness of point
brightnessVal = c1.val[2] + c1.val[0] + c1.val[1];
highestVal = brightnessVal;
myPoints[frameCount][y] = x;
}
}
// display best point found on last row processed
if (myPoints[frameCount][y] != 0) {
cvLine(frame, cvPoint(myPoints[frameCount][y], y),
cvPoint(myPoints[frameCount][y], y), CV_RGB(0, 0, 255), 2, CV_AA, 0);
}
}
cvShowImage("3D SCANNER", frame);
cvWriteFrame(writer, frame);
char myChar = cvWaitKey(33);
if (myChar == 27) break; // ESC to break
frameCount++;
}
for (int frameNum = 0; frameNum<frameCount; ++frameNum) {
for (int z = 0; z<MAXROWS; ++z) {
if (myPoints[frameNum][z] != 0) {
numPoints++;
}
}
}
// print ply header (use Meshlab to open PLY file)
printf("ply\nformat ascii 1.0\nelement vertex %d\nproperty float x\nproperty
float y\nproperty float z\nend_header\n", numPoints);
double dist = 0;
double x, y, z2;
for (int frameNum = 0; frameNum<frameCount; ++frameNum) {
for (int z = 0; z<MAXROWS; ++z) {
if (myPoints[frameNum][z] != 0) {
// dist is distance from profile point to axis of rotation (it
should now be vertical so use X)
// * PI / 180 TO CONVERT TO RADIANS
dist = ((double)centerPoint1.x (double)myPoints[frameNum][z]) / sin((double)camAngle * PI / 180.0);
if ((float)dist > 0) {
z2 = (double)z - abs(((double)dist * tan((double)
(camAngle)* PI / 180.0)));
}
else {
z2 = (double)z + abs(((double)dist * tan((double)
(camAngle)* PI / 180.0)));
}
x = dist*sin((double)(360.0 /
(double)frameCount*(double)frameNum) * PI / 180.0);
y = dist*cos((double)(360.0 /
(double)frameCount*(double)frameNum) * PI / 180.0);
printf("%f %f %f\n", x, y, z2);
}
}
}
cvReleaseCapture(&capture);
cvReleaseImage(&frame);
cvReleaseImage(&frame2);
//
cvReleaseMat( &rot_mat );
cvReleaseVideoWriter(&writer);
cvDestroyWindow("3D SCANNER");
return 0;
}
12.Vemos que la nube de puntos toma la forma del objeto inicial que
tenamos.
Referencias
http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/find_contours/fin
d_contours.html
http://harismoonamkunnu.blogspot.in/2013/06/opencv-find-biggest-contourusing-c.html
http://tecnicasdevision.blogspot.com/2014/05/calibrar-una-camara-conopencv.html
http://docs.opencv.org/modules/calib3d/doc/calib3d.html
http://tecnicasdevision.blogspot.com/2014/09/sobre-los-bordes-y-elgradiante.html
http://dasl.mem.drexel.edu/~noahKuntz/openCVTut10.html
https://www.youtube.com/watch?v=DrXIQfQHFv0
http://cdn.oreillystatic.com/books/9780596516130/ch11.pdf
http://mesh.brown.edu/calibration/software.html
http://www.jesusllor.es/?p=37
http://maztories.blogspot.com/2013/07/calibracion-de-una-camara-conopencv.html
http://www.elai.upm.es/webantigua/spain/Investiga/GCII/personal/lrodriguez/we
b3D/reconstruccion_3d.htm
http://sabia.tic.udc.es/gc/Contenidos
%20adicionales/trabajos/Hardware/scanner3D/Escaner3D.html
http://www.efefuturo.com/noticia/una-camara-laser-que-mejora-y-abarata-lareconstruccion-3d/
http://www.redalyc.org/articulo.oa?id=47724934011
http://oefa.blogspot.com/2008/09/triangulacin-de-delaunay.html
http://personal.us.es/almar/docencia/practicas/triangulaciones/tema4.html
http://lands.asuni.es/help/html/Modelado%20de%20terreno.htm
http://littlecodes.wordpress.com/2013/06/24/calibracion-de-camaras-yprocesamiento-de-imagenes-ii/
http://web-sisop.disca.upv.es/imd/cursosAnteriors/2k32k4/copiaTreballs/serdelal/trabajoIMD.xml
http://nuigroup.com/forums/viewthread/3414/
http://szeliski.org/Book/
http://research.microsoft.com/en-us/um/people/zhang/Calib/