저역통과필터가 블록내부의 값들을 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);
}
출력결과
'MFC' 카테고리의 다른 글
데이터 메모리 영역, 허프만 트리..를 만들어야 하지만 리스트 만들기 (0) | 2013.05.30 |
---|---|
DCT변환 (0) | 2013.05.23 |
이미지의 기하학적 변환 (1) | 2013.05.09 |
로우패스필터로 경계선을 흐리게 만들어보자. (0) | 2013.04.18 |
MFC 시작하기와 영상 입출력하기 (2) | 2013.04.17 |