Programing/OpenCV
#OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝 - 10
CouqueD'asse
2022. 6. 14. 16:00
7.3 샤프닝 : 영상 날카롭게 하기
샤프닝 : 초점이 잘 맞는 사진처럼 사물의 윤곽이 뚜렷하고 선명한 느낌이 나도록 영상을 변경하는 필터리 기법
7.3.1 언샤프 마스크 필터
언샤프(블러링이 적용된 영상)한 영상을 이용하여 역으로 날카로운 영상을 생성하는 필터
void unsharp_mask()
{
Mat src = imread("rose.bmp", IMREAD_GRAYSCALE);
if (src.empty())
{
return;
}
imshow("src", src);
for (int sigma = 1; sigma <= 5; sigma++)
{
Mat blurred;
GaussianBlur(src, blurred, Size(), sigma);
float alpha = 1.f;
Mat dst = (1 + alpha) * src - alpha * blurred;
String desc = format("sigma : %d", sigma);
putText(dst, desc, Point(10, 30), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255), 1, LINE_AA);
imshow("dst", dst);
waitKey();
}
destroyAllWindows();
}
7.4 잡음 제거 필터링
7.4.1 영상과 잡음 모델
영상에서 잡음은 주로 영상을 획득하는 과정에서 발생하며, 디지털 카메라에서 사진을 촬영하는 경우에는 광학적 신호로 변환하는 센서에서 주로 잡음이 추가됨
잡음이 생성되는 방식을 잡음 모델이라고 하며, 대표적인 잡음 모델은 가우시안 잡음 모델
가우시안 잡음 모델 : 보통 평균이 0인 가우시안 분포를 따르는 잡음
void noise_gaussian()
{
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty())
{
return;
}
imshow("src", src);
for (int stddev = 10; stddev <= 30; stddev += 10)
{
Mat noise(src.size(), CV_32SC1);
randn(noise, 0, stddev);
Mat dst;
add(src, noise, dst, Mat(), CV_8U);
String desc = format("stddev : %d", stddev);
putText(dst, desc, Point(10, 30), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255), 1, LINE_AA);
imshow("dst", dst);
waitKey();
}
destroyAllWindows();
}
7.4.2 양방향 필터
에지 성분은 그대로 유지하면서 가우시안 잡음을 효과적으로 제거하는 알고리즘
수식이 픽셀 값에 의존적이기 때문에 모든 픽셀에서 서로 다른 형태를 갖게 됨. 즉, 모든 픽셀 위치에서 주변 픽셀과의 밝기 차이에 의한 고유의 필터 마스크 행렬을 만들어서 마스크 연산을 수행
void filter_bilateral()
{
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty())
{
return;
}
Mat noise(src.size(), CV_32SC1);
randn(noise, 0, 5);
add(src, noise, src, Mat(), CV_8U);
Mat dst1;
GaussianBlur(src, dst1, Size(), 5);
Mat dst2;
bilateralFilter(src, dst2, -1, 10, 5);
imshow("src", src);
imshow("dst1", dst1);
imshow("dst2", dst2);
waitKey();
destroyAllWindows();
}
7.4.3 미디언 필터
입력 영상에서 자기 자신 픽셀과 주변 값 중에서 중간값을 선택하여 결과 영상 픽셀 값으로 설정하는 필터링 기법
주변 픽셀 값들의 중간값을 선택하기 위해 내부에서 픽셀 값 정렬 과정이 사용됨
잡음 픽셀 값과 큰 차이가 있는 경우에 효과적으로 동작함
void filter_median()
{
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty())
{
return;
}
int num = (int)(src.total() * 0.1);
for (int i = 0; i < num; i++)
{
int x = rand() % src.cols;
int y = rand() % src.rows;
src.at<uchar>(y, x) = (i % 2) * 255;
}
Mat dst1;
GaussianBlur(src, dst1, Size(), 1);
Mat dst2;
medianBlur(src, dst2, 3);
imshow("src", src);
imshow("dst1", dst1);
imshow("dst2", dst2);
waitKey();
destroyAllWindows();
}