스무딩 또는 블러링은 매우 간단하면서도 빈번하게 사용되는 영상처리 기법이다. 스무딩 기법은 주로 영상의 잡음(noise) 또는 손상을 완화시키기 위해서 사용된다. 스무딩은 영상의 크기를 줄이는 경우에도 중요한 역할을 담당한다. OpenCV는 현재 다섯 가지 스무딩 방법을 제공한다. 모든 스무딩 연산은 하나의 함수 cvSmooth()에 구현되어 있으며, 함수의 인자에 의해 연산 방법이 결정된다.
public static void Smooth(CvArr src, CvArr dst);
public static void Smooth(CvArr src, CvArr dst, SmoothType smoothtype);
public static void Smooth(CvArr src, CvArr dst, SmoothType smoothtype, int param1);
public static void Smooth(CvArr src, CvArr dst, SmoothType smoothtype, int param1, int param2);
public static void Smooth(CvArr src, CvArr dst, SmoothType smoothtype, int param1, int param2, double param3);
public static void Smooth(CvArr src, CvArr dst, SmoothType smoothtype, int param1, int param2, double param3, double param4); |
Src와 dst는 각각 입력 영상과 출력 영상을 가리킨다. cvSmooth() 함수는 param1, param2, param3, param4 라는 평이한 이름의 매개변수 네 개를 갖는데, 이들 매개변수의 의미는 세 번째 인자 smoothtype에 의해 결정된다.
Smoothtype 값 | 이름 | 바꿔치기 | 채널개수 | 입력영상타입 | 출력영상타입 | 설명 |
CV_BLUR | 단술 블러 | O | 1,3 | 8u,32f | 8u,32f | Param1 x param2 크기의 이웃 필셀값의 평균 |
CV_BLUR_NO_SCALE | 스케일링 없는 단순 블러 | X | 1 | 8u | 입력이 8u이면 16s 32f 이면 32f | Param1 x param2 크기의 이웃 픽셁밧의 합 |
CV_MEDIAN | 중간값 블러 | X | 1,3 | 8u | 8u | Param1 x param2 크기의 이웃 픽셀값에서 중간값 |
CV_GAUSSIAN | 가우시안 블러 | O | 1,3 | 8u,32f | 입력이 8u이면 16s, 32f 이면 32f | Param1 x param2 크기의 이웃 픽셀값의 가중치 합 |
CV_BILATERAL | 양방향 블러 | X | 1,3 | 8u | 8u | 3 x 3 크기의 양방향 필터를 적용 색상 시그마 = param1 공간 시그마 = param2 |
단순 필터
CV_BLUR 값을 전달할 때 시행되는 단순 블러는 가장 간단한 형태의 스무딩 이다. 단순 블러는 1 또는 3채널, 8비트 또는 32 비트 실수형 영상에서 동작한다.
단순 블러, 부젼 픽셀값의 평균을 이용하여 스무딩을 수행한다. 왼쪽이 원본 영상이고 오른쪽이 결과 영상이다.
모든 스무딩 연산이 동일한 형태의 영상에서 동작하는 것은 아니다. Smoothtype 값에 CV_BLUR_NO_SCAL를 지정하면 스케일링 없는 단순 블러 연산이 수행된다. 이 연산은 기본적으로 단순 블러와 동일하지만 평균값 계산을 위한 나눗셈 연산이 없다. 이 때문에 입력 영상과 출력 영상은 서로 다른 데이터 타입을 가져야 하는데, 이는 계산 과정에서 오버플로가 생기는 것을 방지하기 위함이다. 스케일링 없는 단순 블러는 일반적으로 8비트 영상을 입력으로 받고, IPL_DEPTH_16S 또는 32S 데이터 타입의 출력 영상을 생성한다. 32비트 실수형 영상에서 실행할 경우, 결과 영상도 32비트 실수형 영상이다. 32비트 영상을 사용할 경우에도 반드시 지켜져야 만 한다. 스케일링 없는 단순 블러는 나눗셈 연산이 있는 단순 블러에 비해 연산 속도가 빠르다.
중간값 필터
중간값 필터는 픽셀 주변 사각형 영역에서 중간값을 선택하여 해당 픽셀의 값으로 교체하는 방식이며, smoothtype 값을 CV_MEDIAN으로 지정한다. 중간값 필터는 1 또는 3채널, 8비트 영상에서 동작하며, 원본 영상을 바꿔치기할 수 없다. 평균값을 사용하는 단순 블러는 홀로 독립되어 나타나는 잡음(이러한 잡음을 샷 잡음(shot noise)라고 부른다)에 민감하게 반응할 수 있다. 적은 개수의 픽셀에서 크게 튀는 값을 갖는 픽셀은 평균값 계산에 큰 영향을 줄 수 있기 때문이다. 중간값필터는 중간값을 선택함으로써 그러한 이상치를 무시할 수 있다. 중간값 블러, 주변 픽셀의 중간값을 이용하여 스무딩을 수행한다.
가우시안 필터
가우시안 필터는 동작이 빠른편은 아니지만 가장 유용한 필터이다. 가우시안 필터는 입력 영상의 각 픽셀에서 가우시안 커널과 컨볼루션을 하여 결과 영상을 생성한다. CvSmooth() 함수를 이용하여 가우시안 블러를 수행하려면 매개변수 값을 설정해 주어야 한다. Param1과 param2에서 필터 윈도우의 가로와 세로 크기를 지정한다. Param3에는 선택적으로 가우시안 커널의 시그마값(표준편차)을 지정한다. Param3이 기본값인 0으로 설정되면 시그마 값을 자체적으로 계산하여 사용한다. 비대칭 모양의 커널 윈도우를 사용하려면 param4를 지정할 수 있다. 이 경우, param3은 가로 방향의 시그마값을, pararm4는 세로 방향의 시그마값을 나타낸다.
만약 param3과 pararm4의 값을 지정하였는데 pararm1 = param2 = 0 으로 설정이되어 있다면, 커널 윈도우의 크기는 시그마값에 의해 자동으로 결정된다.
OpenCV는 자주 사용하는 가우시안 커널에 대하여 최적화된 성능의 스무딩을 보여준다. 표준 시그마값(param3 =0.0)을 갖는 3x3, 5x5, 7x7 크기의 가우시안 커널일 경우, 다른 커널에 비하여 연산 속도가 빠르다. 가우시안 블러는 8비트 또는 32비트 실수형을 갖는 1또는 3채널 영상에 대하여 적용할 수 있다.
양방향 필터
양방향 필터는 엣지 보존 스무딩 이라고 알려져 있는 영상 분석 방법 중의 하나이다. 양방향 필터는 가우시안 스무딩과 비교하면 쉽게 이해할 수 있다. 전형적인 가우시안 스무딩은 실제 영상의 픽셀값이 공간 상에서 천천히 변화하고, 이로 인하여 이웃 픽셀과 연관성을 많이 갖고 있지만 잡음은 갑작스럽게 값이 튄다는 점에서 착안되었다. 이러한 이유로 가우시안 스무딩은 신호는 보존하면서 잡음만 제거한다. 그러나 이 방법은 엣지 근처에서는 문제가 발생한다. 주변 값들과 상관성이 적은 엣지 부근에서도 가우시안 스무딩은 영상을 평탄하게 만듦으로써 엣지를 없애버린다. 양방향 필터는 약간의 연산 시간을 더 소모하지만 엣지를 보존하면서 영상의 스무딩을 수행한다.
가우시안 스무딩과 유사하게 양방향 필터 또한 각 픽셀과 주변 요소들로부터 가중 평균을 구한다. 이때 가중치는 두 개의 성분을 갖는데, 하나는 가우시안 스무딩에서 사용되는 가중치와 동일하다. 나머디 가중치 성분도 가우시안 가중치와 유사하지만 중심으로부터의 거리에 의해 결정되는 값이 아니라 중심 픽셀 값과의 밝기 차이에 의해 결정되는 가중치를 사용한다. 양방향 필터는 유사한 픽셀에 대하여 더 큰 가중치를 부여하는 가우시안 스무딩이라고 간주할 수 있다. 이 필터는 영상을 마치 수채화 그림처럼 바꿔주는 효과가 있다. 양방향 필터는 영상 분할을 위한 전처리 과정으로 사용되기도 한다. 양방향 필터는 두 개의 매개변수를 사용한다. Param1은 색 공간에서 사용되는 가우시안 커널의 크기를 나타낸다. Param1값이 클수록 더 넓은 분포의 밝기값(또는 생상값)이 평탄화 된다.param2는 공간 영역에서 사용되는 가우시안 커널의 너비를 나타낸다. 이는 가우시안 필터에서 시그마값과 유사하다.
namespace AboutOpenCV { /// <summary> /// Window1.xaml에 대한 상호 작용 논리 /// </summary> public partial class Window1 : Window { WriteableBitmap wb; WriteableBitmap resultwb; IplImage src;
public Window1() { InitializeComponent(); }
private void MenuItem_Click(object sender, RoutedEventArgs e) { string imgpath; // 경로저장변수
OpenFileDialog dlg = new OpenFileDialog();
dlg.DefaultExt = ".*"; //기본 확장자 dlg.Filter = "Image Files(.*)|*.*"; // 확장 파일 필터 dlg.ShowDialog(); imgpath = dlg.FileName;
src = new IplImage(imgpath, LoadMode.AnyColor);
wb = new WriteableBitmap(src.Width, src.Height, 96, 96, PixelFormats.Bgr24, null);
WriteableBitmapConverter.ToWriteableBitmap(src,wb);
image1.Source = wb;
} //스무딩
private void MenuItem_Click_1(object sender, RoutedEventArgs e) { if (src == null) return; IplImage dst = Cv.CreateImage(src.Size, BitDepth.U8, 3);
Cv.Smooth(src, dst,SmoothType.Bilateral,1,1); //Cv.Smooth(src, dst, SmoothType.Blur); //Cv.Smooth(src, dst, SmoothType.BlurNoScale); //Cv.Smooth(src, dst, SmoothType.Gaussian, 7);
resultwb = new WriteableBitmap(dst.Width, dst.Height, 96, 96, PixelFormats.Bgr24, null);
WriteableBitmapConverter.ToWriteableBitmap(dst, resultwb);
image2.Source = resultwb; } } } |
'Programing > OpenCV' 카테고리의 다른 글
영상 모폴로지 자체 커널 만들기 (0) | 2016.11.30 |
---|---|
영상 모폴로지 (0) | 2016.11.30 |
영상 파일 포맷의 종류 (0) | 2016.11.30 |
영상처리 컬러모델 (0) | 2016.11.30 |
gray scale (0) | 2016.11.30 |