라즈베리파이에서 Processing을 이용한 영상처리- 영역처리(2)

메카 2017-04-18 (화) 10:06 1년전 1212  

[실습7-3] 샤프닝(Sharpening)

샤프닝은 블러링의 반대효과를 가진다. 이것은 영상강화라고도 하는데, 영상에서 상세한 부분들을 더욱더 강조하는 효과를 가지게 된다. 그러므로 샤프닝은 고주파 공간적 필터라 할 수 있다. 즉 저주파가 제거가 된다. 그리고 영상을 샤프닝하는 것은 대비 효과를 증가시키게 된다.

샤프닝에서 사용되는 convolution 마스크는 마스크의 중심에서는 양의 값을 가지며 가장자리는 음의 값을 가지게된다. 일반적인 샤프닝 마스크는 그림 7-6과 같다.

 

51bf74f7783ee53843ce3bb5ed2dd15c_1492477 

그림 7-6. 샤프닝 윈도우 마스크

 

a) 소스코드 및 결과 영상

 

 PImage img;

double[][] SharpMask1 = {{0.0, -1.0, 0.0}, {-1.0, 5.0, -1.0}, {0.0, -1.0, 0.0}};

double[][] SharpMask2 = {{-1.0, -1.0, -1.0}, {-1.0, 9.0, -1.0}, {-1.0, -1.0, -1.0}};

double[][] SharpMask3 = {{1.0, -2.0, 1.0}, {-2.0, 5.0, -2.0}, {1.0, -2.0, 1.0}};

void setup() {

img=loadImage("Street.jpg");

size(640, 240);

}

void draw() {

PImage img_Sharpening = createImage( img.width, img.height, RGB );

image(img, 0, 0);

img.loadPixels();

for ( int y = 1; y < img.height-1; y++) {

for ( int x = 1; x < img.width-1; x++) {

float S=0.0;

for (int i = -1; i <= 1; i++) {

for (int j = -1; j <=1; j++) {

int pos = (x+j) + (y+i)*img.width;

float val = red(img.pixels[pos]);

S += SharpMask1[i+1][j+1]*val;

}

}

if(S>255.0) S=255.0;

if(S<0.0) S=0.0;

img_Sharpening.pixels[x + y*img.width]=color(S,S,S);

}

}

img_Sharpening.updatePixels();

image(img_Sharpening, 256, 0);

}

  

51bf74f7783ee53843ce3bb5ed2dd15c_1492477

(a)

51bf74f7783ee53843ce3bb5ed2dd15c_1492477
(b)

51bf74f7783ee53843ce3bb5ed2dd15c_1492477
(c)

 

그림 7-7. 샤프닝 소스코드 및 결과 영상, (a) SharpMask1[]을 사용한 결과, (b) SharpMask2[]을 사용한 결과, (c) SharpMask3[]을 사용한 결과.

 

b) 코드 설명

윈도우 마스크 3x3을 사용하였으며, SharpMask[] 배열에 있는 계수 값의 합은 1이 된다. 파란색으로 된 EmboMask?[]에서 숫자를 변경해서 실행 하면 그림 7-7과 같은 결과를 얻을 수 있다. 블러링과 비교해서 세세한 부분이 추출된 것을 확인 할 수 있다.

 

 

[실습7-4] 에지 검출(Edge Detection)

영상의 에지는 입력영상에 대한 많은 정보를 가지고 있다. 에지는 영상의 밝기가 급격하게 변화하는 지점에 존재한다. 즉 영상의 발기 값이 큰 값에서 작은 값으로 작은 값에서 큰 값으로 변하는 지점에 나타난다.

에지를 검출하는 방법은 다양하게 있다. 본 강좌에서는 기본적으로 폭넓게 사용하고 있는 방법에 대해 논술한다. 이러한 에지 검출은 다양한 특수 효과를 내기우해 사용되기도 한다.

 

1) 1차 미분 연산자

일반적인 기울기 연산자는 수평과 수직 에지를 검출한다. 이러한 연산자는 convolution 기법에 의해 수행된다. 식으로 나타내면 아래와 같다.

                  fx(x, y) = f(x+1, y) - f(x, y)

                  fy(x, y) = f(x, y+1) - f(x, y)

에지 검출에 사용되는 convolution mask는 아래와 같다.

 

51bf74f7783ee53843ce3bb5ed2dd15c_1492477
 

 에지 검출에서 마스크 계수의 합은 0이 된다. 에지의 크기는 다음 식과 같이 hxhy의 벡터 합으로 계산한다.

 

51bf74f7783ee53843ce3bb5ed2dd15c_1492477 

계산을 간단하게 하기위해
 

51bf74f7783ee53843ce3bb5ed2dd15c_1492477

 

에지의 방향은 다음 식에 의해 구해진다.

 

51bf74f7783ee53843ce3bb5ed2dd15c_1492478

 

 Roberts 연산자는 크기가 작아 매우 빠른 속도로 동작하여 효과적으로 사용 가능하다. 단점은 돌출된 값을 평균화 할 수 없기 때문에 잡음 해결이 불가능하다(잡음에 민감하다).  소벨 연산자는 수평과 수직 에지보다 대각선 방향 에지에 더 민감한 반응을 보인다. 그리고 돌출한 값을 비교적 잘 평균화 하므로 잡음에 대체적으로 강하다. 그리고 소벨은 3x3으로 고정된 것은 아니다.  Prewitt 연산자는 소벨 마스크를 convolution한 결과와 비슷하다. 소벨 마스크보다 응답시간이 빠르다. 대각선 방향 에지보다 수직과 수평 에지에 더 민감하게 반응한다.

일반적인 미분 연산자는 고주파 성분을 강조하는 효과가 있다, 노이즈는 일반적 인 발기 정보에 비해서 고주파 성분이 강하다.

 

    a) 소스 코드 및 실험 결과 - Sobel 연산자

 

 PImage img;

double[][] SobelMask_R = {{1.0, 0.0, -1.0}, {2.0, 0.0, -2.0}, {1.0, 0.0, -1.0}};

double[][] SobelMask_C = {{-1.0, -2.0, -1.0}, {0.0, 0.0, 0.0}, {1.0, 2.0, 1.0}};

void setup() {

img=loadImage("Lena.JPG");

size(512, 512);

}

void draw() {

PImage img_Edge = createImage( img.width, img.height, RGB );

PImage img_Edge_R = createImage( img.width, img.height, RGB );

PImage img_Edge_C = createImage( img.width, img.height, RGB );

image(img, 0, 0);

img.loadPixels();

for ( int y = 1; y < img.height-1; y++) {

for ( int x = 1; x < img.width-1; x++) {

float S_r=0.0;

float S_c=0.0;

float S=0.0;

for (int i = -1; i <= 1; i++) {

for (int j = -1; j <=1; j++) {

int pos = (x+j) + (y+i)*img.width;

float val = red(img.pixels[pos]);

S_r += SobelMask_R[i+1][j+1]*val;

S_c += SobelMask_C[i+1][j+1]*val;

}

}

S=sqrt(pow(S_r,2.0)+pow(S_c,2.0));

if(S>255.0) S=255.0;

if(S<0.0) S=0.0;

img_Edge.pixels[x + y*img.width]=color(S,S,S);

img_Edge_R.pixels[x + y*img.width]=color(S_r,S_r,S_r);

img_Edge_C.pixels[x + y*img.width]=color(S_c,S_c,S_c);

}

}

img_Edge.updatePixels();

img_Edge_R.updatePixels();

img_Edge_C.updatePixels();

image(img_Edge, 256, 0);

image(img_Edge_R, 0, 256);

image(img_Edge_C, 256, 256);

}

 

 

 51bf74f7783ee53843ce3bb5ed2dd15c_1492478 

그림 7-8. 소벨 연산자 결과. (a) 원 영상, (b) 소벨 결과 영상, (c) X축 계산 결과 영상, (d) Y축 계산 결과 영상

  

b) 코드 설명

입력 영상을 "Lena.JPG"로 사용 하였다. 소벨 연산은 수평과 수직을 계산 해 주어야 하기에 X축과 Y축에 해당하는 SobelMask_R SobelMask_C 마스크를 선언하였다. 가로(X 방향) 에지 영상 결과는 img_Edge_R 이미지 변수에 저장하며 img_Edge_C는 세로(Y방향) 에지 결과를 각각 저장한다. 소벨 연산의 최종 값은 아래 식에 의해 최종 값으로 결정된다.

 

51bf74f7783ee53843ce3bb5ed2dd15c_1492478

 

소스 프로그램에서는 S를 계산 하는 식에 해당 된다. 다른 연산자도 마스크 내의 값을 변경하면서 프로그램을 실행하면 결과를 볼 수 있다.

 

2) 2차 미분 연산자

1차 미분 영상은 에지가 존재하는 부분을 지날 때 반응하는 부분이 많이 나타난다. 특히 완만한 경사를 이루는 에지 일 경우 더욱 두드러지게 나타난다. 에지의 중심에 위치한 임의의 에지만을 찾을 수 있으면 가장 이상적이다. 이것에 가장 적합한 것이 2차 미분 연산자이다. Laplacian 연산자는 2차 미분 연산자의 좋은 예이다. 2차 미분을 이용한 에지 검출기는 미분을 한번더 수행 하므로 1차 미분의 단점을 완화시켜 둔감하게 반응하도록 만든다. 2차 미분을 이용한 에지 검출기의 장점은 검출된 에지는 폐곡선을 형성한다. 반면에 단점은 고립된 잡음에 민감하고 강도만 검출할 수 있으며 방향은 구하지 못한다. 영상처리에서 자주 사용하는 convolution 마스크는 아래와 같으며, 합은 0이다

 

 

51bf74f7783ee53843ce3bb5ed2dd15c_1492478

 

a) 소스 코드 및 실험 결과 - Laplacian 연산자

 

 PImage img;

double[][] LaplaMask_1 = {{0.0, -1.0, 0.0}, {-1.0, 4.0, -1.0}, {0.0, -1.0, 0.0}};

double[][] LaplaMask_2 = {{1.0, -2.0, 1.0}, {-2.0, 4.0, -2.0}, {1.0, -2.0, 1.0}};

double[][] LaplaMask_3 = {{-1.0, -1.0, -1.0}, {-1.0, 8.0, -1.0}, {-1.0, -1.0, -1.0}};

void setup() {

img=loadImage("Lena.JPG");

size(512, 512);

}

void draw() {

PImage img_Laplace_1 = createImage( img.width, img.height, RGB );

PImage img_Laplace_2 = createImage( img.width, img.height, RGB );

PImage img_Laplace_3 = createImage( img.width, img.height, RGB );

image(img, 0, 0);

img.loadPixels();

for ( int y = 1; y < img.height-1; y++) {

for ( int x = 1; x < img.width-1; x++) {

float S1=0.0;float S2=0.0;float S3=0.0;

for (int i = -1; i <= 1; i++) {

for (int j = -1; j <=1; j++) {

int pos = (x+j) + (y+i)*img.width;

float val = red(img.pixels[pos]);

S1 += LaplaMask_1[i+1][j+1]*val;

S2 += LaplaMask_2[i+1][j+1]*val;

S3 += LaplaMask_3[i+1][j+1]*val;

}

}

if(S1>255.0) S1=255.0; if(S1<0.0) S1=0.0;

if(S2>255.0) S2=255.0; if(S2<0.0) S2=0.0;

if(S3>255.0) S3=255.0; if(S3<0.0) S3=0.0;

img_Laplace_1.pixels[x + y*img.width]=color(S1,S1,S1);

img_Laplace_2.pixels[x + y*img.width]=color(S2,S2,S2);

img_Laplace_3.pixels[x + y*img.width]=color(S3,S3,S3);

}

}

img_Laplace_1.updatePixels();

img_Laplace_2.updatePixels();

img_Laplace_3.updatePixels();

image(img_Laplace_1, 256, 0);

image(img_Laplace_2, 0,256);

image(img_Laplace_3, 256, 256);

}

 

 

 51bf74f7783ee53843ce3bb5ed2dd15c_1492478 

 

 

그림 7-9. Laplacian 연산자 결과. (a) 원 영상, (b) LaplaMask_1 사용 결과 영상, (c) LaplaMask_2 사용 결과 영상, (d) LaplaMask_3 사용 결과 영상

 

 

b) 코드 설명

1차 미분의 convolution 마스크는 행과 열의 마스크가 있었지만 2차 미분의 Laplacian convolution 마스크에는 행과 열이 합쳐져 한 개만 있다. 소벨 연산과 마찬 가지로 마스크 내의 값을 변경하면서 프로그램을 실행하면 결과를 볼 수 있다.

 


모바일 버전으로 보기