저역통과필터가 블록내부의 값들을 1/9로 산술하여 평균값을 도출해서 픽셀값을 대처했다면

메디안필터란 블록내의 9개 픽셀값들을 전부 정렬하여 그 중간값을 픽셀에 집어넣음.

->그러려면 일단 오름차순이 됬던, 내림차순이 됬던 정렬하는 방법이 필요하겠지??

 

중요 : 정렬(재배열)의 종류, 이제부터 정렬의 방법을 배워보자.

 

-선택정렬(selection sort) :

요령:

1)배열[0]에 가장 작은 값을 넣는다

2)방금 배열[0]에는 최소값이 저장됬을것이므로 이번에는 배열[1]에 가장 작은 값을 넣는다. 이짓거리를 반복한다.

3)최소값들이 앞 배열, 앞 배열에 순서대로 들어가 있을것이다.

즉, 가장 마지막 배열[last]은 자연스럽게 최대값이 들어가 있을것이다.

※그렇다면 배열이 5개라면 굳이 [5]까지 처리할 필요가 없다. i는 0부터 4까지만 처리하면 된다.

 

tip : 비쥬얼스튜디오2010은 빌드했을때 비쥬얼스튜디오6.0처럼 press any key를 콘솔상에서 기다려주지 않는다.

(결과창이 순식간에 뿅하고 나타난다는 얘기;) 이를 해결하려면 프로젝트>속성>시스템>하위시스템>콘솔로 변경하라.

빌드할때는 ctrl + f5로 눌러라. (f5누르면 뿅하고 사라짐)  

 

//소스코드

#include<stdio.h>
#define N 5 //이렇게하면 N은 상수 5가 된다.
void main()
{
 int arr[N] = {30,40,12,18,22};
 for(int i=0; i<N-1; i++){ //N을 -1해주는 이유는 ※를 참고하라.
  for(int j=i+1; j<N; j++){ //[0]을 처리했으면 이제 [0]은 냅두고, [1]을 처리하면 되고, 하여튼 위의 2)를 참고해봐라.
   if(arr[i]>arr[j]){
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
   }
  }
 }

 for(int i=0; i<N; i++)
  printf("%d ", arr[i]);
 printf("\n");
}

 

 

 

 

-버블정렬(bubble sort)

이건 자바시간에서도 익히 배웠기 때문에 잘 알것이다.

바로 소스코드로 들어가보자.

//소스코드
#include<stdio.h>
#define N 5
void main()
{
 int arr[N] = {30,40,12,18,22};
 for(int i=0; i<N; i++){
  for(int j=0; j<N-1; j++){ //여기서 N-1을 해줘야한다.
   if(arr[j]>arr[j+1]){
    int temp = arr[j];
    arr[j] = arr[j+1];
    arr[j+1] = temp;
   }
  }
 }

 for(int i=0; i<N; i++)
  printf("%d ", arr[i]);
 printf("\n");
}

 

그러나 버블소트의 원래 취지는 맥주거품처럼 뒤에서부터 쌓인다는 의미(?)를 가지므로 사실 i루프는 역으로 돌아야 한다.

//소스코드
#include<stdio.h>
#define N 5
void main()
{
 int arr[N] = {30,40,12,18,22};
 for(int i=N-1; i>0; i--){
  for(int j=0; j<N-1; j++){//N-1 대신 i 사용 가능
   if(arr[j]>arr[j+1]){
    int temp = arr[j+1];
    arr[j+1 ] = arr[j];
    arr[j] =  temp;
   }
  }
 }

 for(int i=0; i<N; i++)
  printf("%d ", arr[i]);
 printf("\n");
}

tip : 플래그값을 하나 선언해서 if안에 집어넣는다. 그래서 플래그가 만족되면 break를 걸어준다.

이 방법은 불필요한 i루프 횟수를 줄여주는 효과가 있다.

아래 소스코드를 참고

#include<stdio.h>
#define N 5
void main()
{
 int arr[N] = {30,40,12,18,22};
 int flag=1; //bool타입도 가능. false, true로 값을 주면 된다.
 for(int i=N-1; i>0; i--){
  for(int j=0; j<N-1; j++){//N-1 대신 i 사용 가능
   if(arr[j]>arr[j+1]){
    int temp = arr[j+1];
    arr[j+1 ] = arr[j];
    arr[j] = temp;
    flag=1;
   }
  }
  if(flag==0) break;//플래그를 삽입
 }

 
 for(int i=0; i<N; i++)
  printf("%d ", arr[i]);
 printf("\n");
}

 

-삽입정렬(insertion sort)

집합 개념이 적용된다. 즉, 정렬이 된 집합과 정렬이 안된 집합을 나눠서 정렬이 안된얘들을 정렬된 집합속으로 삽입하는 개념.

//소스코드
#include<stdio.h>
#define N 5
void main()
{
 int arr[N] = {30,40,12,18,22};
 int temp, n; //n은 arr[n]에서 n위치를 기억시키기 위한 임시변수이다.
 
 for(int i=1; i<N; i++){
  //i=1에 주목하자. 맨 처음에는 대상이 딸랑 하나이기 때문에 정렬된 집합이냐, 아니냐로 나누고 자실것도 없다.
  for(int j=i-1; j>=0; j--){
   temp = arr[i];
   n = i;//n은 arr[n]에서 n위치를 기억시키기 위한 임시변수이다.
   for(int j=i-1; j>=0; j--){
    if(temp<arr[j]){
     arr[j+1] = arr[j];
     n=j;
    }
   }
   arr[n] =temp;
  }
 }
 
 for(int i=0; i<N; i++)
  printf("%d ", arr[i]);
 printf("\n");
}

 

 

이제 에지 검출을 하는 MFC를 작성해보자. 오픈cv로 작성해보자.

 

#include<cv.h>
#include<cxcore.h>
#include<highgui.h>
void CtestDoc::MedianFilter()
{
 // TODO: 여기에 명령 처리기 코드를 추가합니다.
 IplImage* ori8u=cvLoadImage("circuit.bmp", IPL_DEPTH_8U);
 IplImage* sobel16=cvCreateImage(cvGetSize(ori8u), IPL_DEPTH_16S, 1);
 IplImage* sobel8=cvCreateImage(cvGetSize(ori8u), IPL_DEPTH_8U, 1);
 IplImage* canny=cvCreateImage(cvGetSize(ori8u), IPL_DEPTH_8U, 1);
 cvSobel(ori8u, sobel16, 1, 1);
 cvCvtScale(sobel16, sobel8, 1, 0);
 cvCanny(ori8u, canny, 150, 200);
 cvShowImage("sobel8", sobel8);
 cvShowImage("canny", canny);
 cvWaitKey(0);
}

 

 

출력결과

 

,