평균값 필터 직접구현(블러링)

#include<iostream>
#include"opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main(void) {
	Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);

	if (src.empty()) {
		cerr << "Img load failed!" << endl;
		return -1;
	}
	/*
	float data[] =   // 입력 데이터에 따라 필터 종류도 달라지는 거 같다. 엠보싱과 한번 비교해보자.
	{
		1 / 9.f ,1 / 9.f ,1 / 9.f,
		1 / 9.f ,1 / 9.f ,1 / 9.f,
		1 / 9.f ,1 / 9.f ,1 / 9.f,
	}; // 이와 같이 원소가 모두 동일 시 Mat::ones 사용해 굳이 data[] 만들 필요없다.

	Mat kernel(3, 3, CV_32FC1, data);
	cout << kernel << endl;
	*/

	Mat kernel = Mat::ones(3, 3, CV_32FC1)/ 9.f;
	cout << kernel << endl;
	Mat dst;
	filter2D(src, dst, -1, kernel);

	imshow("src", src);
	imshow("dst", dst);
	waitKey();

}

 

평균값필터는 blur라는 함수를 제공해 간편히 평균값필터를 사용할 수 있다

cv::filter2D (InputArray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor=Point(-1,-1), double delta=0, int borderType=BORDER_DEFAULT)
**when ddepth = -1, the output image will have the same depth as the source. 결과 영상 깊이가 src 깊이와 동일.
**Poin(-1,-1):고정점 좌표. Point(-1, -1)을 지정하면 커널 중심을 고정점으로 사용

 

#include<iostream>
#include"opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main(void) {
	Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);

	if (src.empty()) {
		cerr << "Img load failed!" << endl;
		return -1;
	}

	Mat kernel = Mat::ones(3, 3, CV_32FC1)/ 9.f;
	cout << kernel << endl;
	Mat dst;

	imshow("src", src);
	for (int ksize = 3; ksize <= 7; ksize += 2) {
		blur(src, dst, Size(ksize, ksize));

		String desc = format("Mean: %dx%d", ksize, ksize);
		putText(dst, desc, Point(10, 30), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255), 1, LINE_AA);

		imshow("dst", dst);
		waitKey();
	}

}

산술평균 사용시 원하는 부분(현재 위치의 픽셀값)이 아닌 전체 부분에 동일한 가중치로 필터를 적용하게 된다. 

 

결과 영상에서 같은 위치에 있는 입력영상의 픽셀값 비중은 1/n 이며 나머지 픽셀들의 비중이 (n-1)/n 이 되어 원본 영상의

 

같은 위치 픽셀값보다 주변에 위치한 픽셀값들에의해 영향을 많이 받게 된다.

 

이에, 현위치와 가까이 있는 픽셀들에게 가중치를 크게 주고 멀리 떨어진 픽셀들에겐 가중치를 적게 주는 형태로 필터링해

 

야한다.

 

 

해결법: 가우시안 블러링.

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;
int main(void) {
	Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
	if (src.empty()) {
		cerr << "Image load failed!" << endl;
		return -1;
	}

	Mat dst;
	GaussianBlur(src, dst, Size(), 2.0);  // sigma값 1.0 입력 시 내부적으로 7x7 필터사이즈 크기로 블러링 됨
	Mat dst2;
	blur(src, dst2, Size(7, 7)); //그러나 위보단, 직접 7,7 로 입력하여 블러링한게 좀 더 블러링이 된다. 필터사이즈가 커짐에따라 결과영상 품질은 좋지 않다.
	//7x7 평균값필터 적용 시 GaussianBlur의 sigma값을 증가시켜서 좀 더 자연스러운 블러링을 할 수 있다. 간단한 블러링의 경우 평균값 필터 사용할 수 있다.
	imshow("src", src);
	imshow("dst", dst);
	imshow("dst2", dst2);
	waitKey();
}

 시그마 사이즈가 커지면 내부에서 연산량이 증가하여 시간 또한 증가하게 될 것이다.

+ Recent posts