What I'm hacking now?

6 de abril de 2009

Introdução OpenCV

Filed under: OpenCV — pirunga @ 2:31 am
Tags: , ,

OpenCV é uma biblioteca de processamento de Imagens e Inteligência Artificial da Intel livre que utiliza licensa BSD, e eu vou mostrar algumas pequenas demonstrações com códigos exemplo e coisas assim. =) (Não se assuste com os tamanhos… é que os códigos estão MUITO comentados e em duas linguas diferentes )

Começando de leve:

Como exibir imagens:

#include <stdio.h>
#include <cv.h>
#include <highgui.h>

int main()
{
  IplImage* image = 0;
  /* Create a Pointer to the IplImage Structure */
  /* Cria um ponteiro para a estrutura IplImage */
  image = cvLoadImage( "/home/file.jpg", CV_LOAD_IMAGE_COLOR );
  if (!image)
    return -1; /*this line checks if the image was successfully loaded */
  /* Load an image from a file, now your pointer really points
  to an image structure.
  This is some definitions of highgui,
  #define CV_LOAD_IMAGE_COLOR       1
  #define CV_LOAD_IMAGE_GRAYSCALE   0
  #define CV_LOAD_IMAGE_UNCHANGED  -1
  if 1,  the image will be allocated in a 3-channel image structure
  if 0,  the image will be allocated in a single channel image structure
  converting to a grayscale if the image is coloured
  if -1, the image will be allocated "as it is"
  highgui supports:
    * Windows bitmaps - BMP, DIB
    * JPEG files - JPEG, JPG, JPE
    * Portable Network Graphics - PNG
    * Portabele Image format - PBM, PGM, PPM
    * Sun rasters - SR, RAS
    * TIFF files - TIFF, TIF

  Abre um arquivo de imagem, agora seu ponteiro realmente aponta
  para uma estrutura de imagem.
  Algumas definições da biblioteca highgui,
  #define CV_LOAD_IMAGE_COLOR       1
  #define CV_LOAD_IMAGE_GRAYSCALE   0
  #define CV_LOAD_IMAGE_UNCHANGED  -1
  se 1, força ser uma imagem de 3 canais
  se 0, força ser uma imagem de 1 canal, se a imagem for colorida
  ela será convertida para uma imagem grayscale
  se -1, a imagem será criada com o numero de canais originais
  A bibioteca highgui suporta os formatos mostrados acima, antes
  de começar a explicação em português.
  */

  cvNamedWindow( "My Picture", CV_WINDOW_AUTOSIZE);
  /* This create a window | Isto cria uma janela */

  cvShowImage( "My Picture", image );
  /* Displays the image in the window "My Picture" */
  /* Mostra a imagem na janela "My Picture"        */

  cvWaitKey(0);
  /* Wait a key press */
  /* Espera até que uma tecla seja pressionada */
  cvDestroyWindow( "My Picture" );
  /* Destroy the Window */
  /* Destroi a janela   */

  cvReleaseImage( &image );
  /* Free Memory */
  /* Libera memória */
  return 0;
}

Vamos a um exemplo um pouco mais interessante, encontrando os cantos… corner detection =)

#include <stdio.h>
#include <cv.h>
#include <highgui.h>

int main()
{
  IplImage* image;
  image = cvLoadImage("lena.jpg", CV_LOAD_IMAGE_COLOR );
  if (!image)
     return -1;
  int method=1;
  /* I will show three methods of finding corners */
  /* Mostrarei três métodos de encontrar os cantos*/
  printf("Digite o método:\n0-Laplaciano\n1-Sobel\n2-Canny\n");
  scanf("%d",&method);
  IplImage* workfile;
  IplImage* workfile2;
  IplImage* dst;
   CvSize size = cvGetSize(image);
  /* Allocate a CvSize, its a structure that have width and lenght, cvGetSize get the
  size of the original image, so our corner image will have the same width and height
  */
  workfile = cvCreateImage(size,IPL_DEPTH_8U,1);
  workfile2 = cvCreateImage(size,IPL_DEPTH_8U,1);
  dst = cvCreateImage(size,IPL_DEPTH_32F,1);
   /* This function cvCreate Images create and allocate the image, its arguments are
  in this order:
  size -> CvSize structure you can create images using cvSize(width,height)
  The second argument:
  IPL_DEPTH_8U - unsigned 8-bit integers
  IPL_DEPTH_8S - signed 8-bit integers
  IPL_DEPTH_16U - unsigned 16-bit integers
  IPL_DEPTH_16S - signed 16-bit integers
  IPL_DEPTH_32S - signed 32-bit integers
  IPL_DEPTH_32F - single precision floating-point numbers
  IPL_DEPTH_64F - double precision floating-point numbers
  The third argument is the number of channels, our image will be one single channel
  image
  */
  switch (method)
  {
    case 0:  cvCvtColor( image, workfile, CV_RGB2GRAY );
             cvLaplace( workfile, dst, 3 ); /* dst is IPL_DEPTH_32F, because cvLaplace
             only accepts 8u->16s, 8u->32f, 32f->32f */
             break;
    /* cvCvtColor is a function that convert an image from one color space to another
    Functions cvLaplace, cvSobel, cvCanny must receive images with same channel numbers
    This will calculate the laplacian of image and save it in workfile, the third
    argument is the aperture size, its the kernel that will be used to calculate,
    can be: 1, 3, 5 or 7 refer to:
    http://opencv.willowgarage.com/wiki/CvReference#cvSobel for more info
       Irá calcular o laplaciano da imagem e salvar em workfile, o terceiro argumento
    é o tamanho do kernel que será utilizado para calcular o laplaciano, olhe o link
    acima para mais informações
    */
    case 1: cvCvtColor( image, workfile, CV_RGB2GRAY );
            cvSobel( workfile, workfile2, 2, 0, 3 );
            cvSobel( workfile, workfile, 0, 2, 3 );
            cvAdd(workfile, workfile2, workfile, NULL);
            break;
    /* cvCvtColor is a function that convert an image from one color space to another
    This function cvSobel calculate the the first, second, third or mixed derivatives
    of an image the third argument is the x order, 4th is y order, 5th argument is the
    aperture size, refer to that site to more info about the kernels
    A função cvSobel calcula as derivadas de primeira, segunda, terceira ou mistas da
    imagem e as salva em workfile, 3° argumento é a ordem da derivada em x, 4° ordem
    da derivada em y, 5° é o tamanho do kernel, olhe o site acima para mais informações
    */
    case 2: cvCvtColor( image, workfile, CV_RGB2GRAY );
            cvCanny( workfile, workfile, 50,100, 3 );
            break;
    /* cvCvtColor is a function that convert an image from one color space to another
    I need to use this because the cvCanny only accepts single channel images for this
    algorithm, the 3rd argument is the first threshold, 4th is second threshold, and
    5th is the same aperture size as the other functions. I sugest to change 3rd and
    4th args to see the result.
       cvCvtColor faz a transformação de um espaço de cores para outro, esta função é
    necessaria porque cvCanny apenas aceita arquivos com um único canal, o 3° argumento
    é o primeiro threshold do algorítmo, 4° é o segundo threshold do algorítimo, o
    ultimo argumento é o tamanho do kernel utilizado, como nas outras funções
    */
  }
  cvNamedWindow( "Original", CV_WINDOW_AUTOSIZE);
  cvNamedWindow( "Corners", CV_WINDOW_AUTOSIZE);  

  cvShowImage("Original", image);
  if (method == 0)
     cvShowImage("Corners", dst);
  else
     cvShowImage("Corners", workfile);
  cvWaitKey(0); 

  cvDestroyAllWindows();
  /* Destroy all Windows */
  /* Destroy todas as janelas */

  if (method == 0)
    cvSaveImage( "output.jpg", dst );
  else
    cvSaveImage( "output.jpg", workfile );

  /* cvSaveImage save the image with the name inside "" */

  cvReleaseImage(&image);
  cvReleaseImage(&workfile);

  return 0;
}

Results Below

Original

Original

Laplacian Operator

Laplacian Operator

Sobel Operator

Sobel Operator

Canny Algorithm

Canny Algorithm

About these ads

3 Comentários »

  1. Hmmm. O Canny é mais pra achar “bordas” (edge), e não “cantos” (corner), mas tudo bem, porque o Laplaciano mesmo pode ser usado pros dois… :)

    Mas se nesse Sobel vc pegou a soma das derivadas segundas, então você calculou foi justamente o Laplaciano! Tinha que ser igual a figura de cima. Ela deve tar precisando de uma atenuação no nível, pq ela tá muito P&B…

    O que vc podia testar com o Sobel pra ver algo diferente era calcular o valor do módulo do gradiente em cada ponto, calculando as derivadas primeiras em cada direção, elevando ao quadrado cada uma, e aí somar e tirar a raiz quadrada (ou deixa ao quadrado mesmo). Isso é mais um achador de bordas do que de cantos tb.

    É legal ver a diferença: se sua imagem fosse um cone, o Laplaciano daria um pico no centro, e o módulo do gradiente seria constante. Já se for um parabolóide, o Laplaciano será constante, mas o módulo do gradiente vai começar do 0 e ir aumentando pra fora. O Canny eu não sei, vai provavelmente desenhar um círculo em algum lugar qualquer nos dois casos…

    Mas legal pra valer é calcular os auto-valores da matriz Hessiana em cada ponto, como é utilizado no famoso Harris detector. Diversão garantida. O opencv mesmo devolve a matriz com a multiplicação deles quando vc usa o Harris…

    Comentário por nic — 29 de maio de 2009 @ 1:20 am | Resposta

  2. A propósito. É interessante ver aí nesses Laplacianos que tem um certo quadriculado sobre a imagem. Isso é por causa da compressão JPEG. A imagem é dividida em quadradinhos, e são armazenados os coeficientes DCT de cada um. Quando você filtra, está amplificando os coeficientes de maior frequência, que costumam ser justamente os mais ruidosos. Nas regiões planas estamos vendo componentes que ficaram com um ruído particularmente alto… Em alguns casos dá até pra perceber que são componentes individuais!

    A Lena fica até mais bonita com essa nuvem de álgebra linear em volta!…

    Comentário por nic — 29 de maio de 2009 @ 1:29 am | Resposta

  3. Bom Dia,

    Me tire uma duvida, como que eu faço para salvar as informações que eu detecto de uma face em um banco de dados?
    Por acaso voce tem algum exemplo para me passar?

    Desde já eu agradeço

    Abraço

    Comentário por Felipe Luiz Carnevali — 13 de novembro de 2009 @ 10:21 am | Resposta


Feed RSS para comentários sobre este post. TrackBack URI

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

O tema Rubric. Blog no WordPress.com.

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

%d blogueiros gostam disto: