Computer Vision

소벨 윤곽선 검출(Sobel Edge Detector) 소벨 검출기 소벨 에지 디텍터

익플루 2014. 7. 10. 12:30
반응형

윤곽선 검출기 중 소벨 에지 디텍터에 대해 알아봅시다.

 

-Sobel edge                              

 

-1

0

1

-2

0

2

-1

0

1

 

<수직 마스크>

  

1

2

1

0

0

0

-1

-2

-1

<수평 마스크>

 

소벨 마스크는 모든 방향의 에지를 추출한다.잡음에 강한 편이다.

수직, 수평 에지 보다 대각선 방향 에지에 더 민감하게 반응한다.

 

마스크의 크기가 반드시 3x3 으로 고정되는 것은 아니다. 실제로 5x5, 7x7 크기의 마스크도 존재한다.

 

소벨 마스크 5x5

 

마스크가 커지면 에지는 두꺼워져서 선명하게 나타난다.

반면에 명암값의 변화 구간이 촘촘하거나 복잡한 영상일 경우 효과가 낮다.

 

여기서는 소벨 마스크의 3x3 에 대해서 구현한 것만 이야기 하겠습니다~

 

 

 


#include <math.h>
#include <windows.h>
#include <stdio.h>
using namespace std;


int main()
{
 
 int height= 256;
 int width=256;
 int i,j,vmax,vmin;
 int m_HistoArr[256];
 unsigned char InImg[256][256];
 unsigned char OrgImg[256][256];
 

 FILE *infile= fopen("AVE256.raw","rb");
 if(infile==NULL){printf("error!");return 0;}
 fread(InImg, sizeof(char),256*256,infile);
 fclose(infile);
  


 int MaskSobelX[3][3]={{-1,0,1},
                                 {-2,0,2},
                                 {-1,0,1}};
 int MaskSobelY[3][3]={{1,2,1},
                                 {0,0,0},
                                {-1,-2,-1}};
 int heightm1=height-1;
 int widthm1=width-1;
 int mr,mc;
 int newValue;
 
 int *pImgSobelX,*pImgSobelY;
 int min,max,where;
 float constVal1,constVal2;

 //정수값을 갖는 이미지 동적 메모리 할당
 pImgSobelX=new int[height*width];
 pImgSobelY=new int[height*width];

 //결과 이미지 0으로 초기화
 for(i=0;i<height;i++)
  for(j=0;j<width;j++)
  {
   OrgImg[i][j]=0;
   where=i*width+j;
   pImgSobelX[where]=0;
   pImgSobelY[where]=0;
  }

  //X 방향 에지 강도 계산
  for(i=1; i<heightm1; i++)
  {
   for(j=1; j<widthm1; j++)
   {
    newValue=0; //0으로 초기화
    for(mr=0;mr<3;mr++)
     for(mc=0;mc<3;mc++)
      newValue += (MaskSobelX[mr][mc]*InImg[i+mr-1][j+mc-1]);
    pImgSobelX[i*width+j]=newValue;
   }
  }
  

//Y 방향 에지 강도 계산
  for(i=1; i<heightm1; i++)
  {
   for(j=1; j<widthm1; j++)
   {
    newValue=0; //0으로 초기화
    for(mr=0;mr<3;mr++)
     for(mc=0;mc<3;mc++)
      newValue += (MaskSobelY[mr][mc]*InImg[i+mr-1][j+mc-1]);
    pImgSobelY[i*width+j]=newValue;
   }
  }
  

//에지 강도 계산 절대값(X)+절대값(Y)후 pImgSobelX[]에 저장
  for(i=1;i<heightm1;i++)
   for(j=1;j<widthm1;j++)
   {
    where=i*width+j;
    constVal1=pImgSobelX[where];
    constVal2=pImgSobelY[where];
    if(constVal1<0)
     constVal1=-constVal1;
    if(constVal2<0)
     constVal2=-constVal2;
    pImgSobelX[where]=constVal1+constVal2;
   }
  

 //디스플레이를 위해 0에서 255사이로 값의 범위를 매핑
   //이를 위해 먼저 최대,최소값을 찾은후 이를 이용하여 매핑한다.
   min=(int)10e10;
   max=(int)-10e10;
   for(i=1; i<heightm1; i++)
   {
    for(j=1; j<widthm1; j++)
    {
     newValue=pImgSobelX[i*width+j];
     if(newValue<min)
      min=newValue;
     if(newValue>max)
      max=newValue;
    }
   }

   //변환시 상수값을 미리 계산
   constVal1=(float)(255.0/(max-min));
   constVal2=(float)(-255.0*min/(max-min));
   for(i=1; i<heightm1; i++)
   {
    for(j=1; j<widthm1; j++)
    {

     //[min,max]사이의 값을 [0,255]값으로 변환
     newValue=pImgSobelX[i*width+j];
     newValue=constVal1*newValue+constVal2;
     OrgImg[i][j]=(BYTE)newValue;
    }
   }

   //동적 할당 메모리 해제
   delete [] pImgSobelX;
   delete [] pImgSobelY;

 

 FILE *outfile = fopen("result.raw","wb");
 fwrite(OrgImg,sizeof(char),256*256,outfile);
 fclose(outfile);
 

 return 0;
}

 

 

왼쪽이 전이고 오른쪽이 결과이다.

AVE256.RAWresult.raw

 

 

 

AIRFIELD256X256.RAWresult.raw

 

윤곽선이 검출되었는데 변화가 클수록 좀 더 명확하게 검출된다.

 

 

 

반응형