Tuesday, May 18, 2010

Filtro de Sobel en OpenCV

Una forma más elaborada de detectar bordes es el filtro de Sobel, dado que usa una mayor cantidad de píxeles de la vecindad para calcular el borde.

#include <opencv/highgui.h>
#include <opencv/cv.h>

void sobel(IplImage *img) {
int i,j,indice;
uchar *pixels = (uchar*)(img->imageData);
uchar *new_pixels = (uchar*)malloc(img->widthStep*img->height*img->nChannels*sizeof(uchar));

uchar sup;
uchar sup_izq;
uchar sup_der;
uchar inf;
uchar inf_izq;
uchar inf_der;
uchar izq;
uchar der;
int A;
int B;
double SUM;
//el origen esta en esquina superior izquierda del pantalla
for( i=1 ; i < (img->width-1) ; i++) {
for( j=1 ; j < (img->height-1) ; j++) {
indice = j*img->widthStep + i*img->nChannels;
sup = pixels[indice - img->widthStep]; //pixel superior al actual
inf = pixels[indice + img->widthStep]; //pixel inferior al actual
izq = pixels[indice - img->nChannels]; //pixel izq al actual
der = pixels[indice + img->nChannels]; //pixel der al actual
sup_izq = pixels[indice - img->nChannels - img->widthStep];
sup_der = pixels[indice + img->nChannels - img->widthStep];
inf_izq = pixels[indice - img->nChannels + img->widthStep];
inf_der = pixels[indice + img->nChannels + img->widthStep];
A = sup_izq + 2*sup + sup_der - inf_izq - 2*inf - inf_der;
B = sup_izq + 2*izq + inf_izq - sup_der - 2*der - inf_der;
SUM = A*A + B*B;
new_pixels[indice] = 255-(uchar)sqrt(SUM);

}
}
memcpy(pixels, new_pixels, img->widthStep*img->height*img->nChannels*sizeof(uchar));
free(new_pixels);

}

int main() {
CvCapture *cap = cvCreateCameraCapture(0);
IplImage *img;
IplImage *imgGray;
int notCreated=1;
while(1) {
img = cvQueryFrame(cap);
cvNamedWindow("hahaha",CV_WINDOW_AUTOSIZE);
if(notCreated) {
imgGray = cvCreateImage( cvSize(img->width,img->height), IPL_DEPTH_8U, 1 );
notCreated = 0;
}
cvCvtColor(img, imgGray, CV_RGB2GRAY);
sobel(imgGray);
cvShowImage("hahaha",imgGray);
char key = cvWaitKey(40);
if(key == 27)
break;
}
cvReleaseImage(&img);
cvReleaseImage(&imgGray);
cvReleaseCapture(&cap);
cvDestroyWindow("hahaha");
return 0;
}