์ด๋ฒ ํฌ์คํ ์ ์ฌ๋ฌ๊ฐ์ง ํํฐ์ ๋ํด์ ์์๋ณด๊ณ OpenCV๋ก ์ง์ ์ค์ตํ๋ ๋ด์ฉ์ ๋ด์๋ค.
๋จผ์ Low-pass, High-pass filter๊ฐ ๋ญ์ง ์์๋ณด๊ณ
Uniform Mean, Gaussian, Sobel, Laplacian filter์ ๋ํด์ ์์๋ณธ๋ค.
์ ๋ฒ ํฌ์คํ ์์ ํํฐ๋ง ์ฐ์ฐ์ ๋ํด์ ๊ฐ๋ณ๊ฒ ๋ค๋ฃจ์๊ธฐ ๋๋ฌธ์ ๊ธฐ์ด์ ์ธ ์ฐ์ฐ ๋ฐฉ๋ฒ ์ ๋ฆฌ๋ ์ ์ธํ์๋ค. ๊ทธ๋๋ ๋ด๊ฐ ์ฝ์ผ๋ ค๊ณ ์ฐ๋ ๊ธ์ด๋๊น ์ต๋ํ ์ฝ๊ฒ... ์ฐ๋ ์ค์ด๋ค.
https://he-kate1130.tistory.com/139
[Computer Vision/OpenCV] 10. Spatial Filtering & Convolution ๊ฐ๋
์ง๋์๊ฐ์๋ ์ด๋ฏธ์ง์ ํ์คํ ๊ทธ๋จ์ ์ด์ฉํด ํฝ์ ๊ฐ๋ค์ ๋ค๋ฃจ๋ ๋ฐฉ๋ฒ๋ค์ ์ ๋ฆฌํ๋ค.์ค๋๋ถํฐ๋ ์ด๋ฏธ์ง์ spatial data๋ฅผ ๋ค๋ฃจ๋ ๋ฐฉ์๋ค์ ๋ํด์ ์ ๋ฆฌํ๋ค.์ด๋ฏธ์ง์ ๊ณต๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์
he-kate1130.tistory.com
1. Low/High-pass Filters
์์์์ ์ฃผํ์๋ ์ด๋ฏธ์ง ๋ด๋ถ์์ ๋ฐ๋ณต์ ์ผ๋ก ๋ํ๋๋ ํจํด์ด๋ ๋ณํ์ ์ ๋๋ฅผ ์๋ฏธํ๋ค.
๊ฐ๋จํ๊ฒ ์ผ๋ง๋ ์์ฃผ ์ฃผ๋ณ ํฝ์ ์ intensity๊ฐ ๋ณํ๋๋๋ฅผ ์๋ฏธํ๋ค๊ณ ์ดํดํ ์ ์๋ค.
๋์ frequency๋ผ ํ๋ฉด ํ์ฅ์ด ์งง์, ๋ณํ๊ฐ ๊ธ๊ฒฉํ ์์ญ์ ์๋ฏธํ๋ค.
์ด๋ฏธ์ง์์ ๋ฌผ์ฒด๊ฐ์ ๊ฒฝ๊ณ์ ๋ถ๋ถ, ์์ ๋ํ ์ผ๋ค์ฒ๋ผ ๋ณํ๊ฐ ํฐ ๊ณณ์ด ๊ณ ์ฃผํ ์ฑ๋ถ์ ๊ฐ์ก๋ค.
๋ฎ์ frequency๋ผ ํ๋ฉด ํ์ฅ์ด ๊ธด, ๋ณํ๊ฐ ์๋งํ๊ณ ๋ถ๋๋ฌ์ด ์์ญ์ ์๋ฏธํ๋ค.
์ด๋ฏธ์ง์์์ ํฐ ํน์ง์ด๋, ์ ์ฒด์ ์ธ ๋ฐ๊ธฐ ๊ฐ์ ๊ฒ๋ค์ด ๋ฎ์ ์ฃผํ์ ์ฑ๋ถ์ ๊ฐ์ก๋ค.
์ด๋ฏธ์ง์์ ์ด๋ค ๋ถ๋ถ์ ๊ฐ์กฐํด ๋ณด๊ณ ์ถ๋์ ๋ฐ๋ผ์ Filter์ ์ข ๋ฅ๋ฅผ ๋ค๋ฅด๊ฒ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง๋ฅผ ์ฒ๋ฆฌํ๋ค.
๋ฎ์ ์ฃผํ์๋ถ๋ถ์ ๋ณด๊ณ ์ถ์ผ๋ฉด Low-pass Filter๋ฅผ ์ฌ์ฉํ๋ค.
Low-pass Filter: Uniform Mean Filter, Gaussian Filter ...
๋์ ์ฃผํ์ ๋ถ๋ถ์ ๋ณด๊ณ ์ถ์ผ๋ฉด High-pass Filter๋ฅผ ์ฌ์ฉํ๋ค.
High-pass Filter: Sobel Filter, Laplacian Filter ...
2. Uniform Mean Filter
Low-pass Filter ์ค์์ ๊ฐ์ฅ ๊ฐ๋จํ ํํ๋ฅผ ๊ฐ์ง ํํฐ๋ค.
ํํฐ ์ปค๋์ ๋ค์์ฒ๋ผ ์๊ฒผ๋ค,


๊ฐ element๋ฅผ ๋ชจ๋ 1๋ก ํ๊ณ , normalizeํ๋ค (ํํฐ ์ปค๋์ ํฉ์ด ํญ์ 1์ด ๋์ด์ผ ํ๋ฏ๋ก)
์ด๋ฐ์์ผ๋ก ์ปค๋์ ์ฒด ํฉ์ผ๋ก ๋๋์ด์ normalizeํ๋ ์ปค๋๋ค์ Average(Mean) Filter ๋ผ๊ณ ํ๋๋ฐ, ์๋ ๋ชจ๋ ๊ฐ์ด 1์ด๋ฏ๋ก Uniform Mean Filter๋ผ๊ณ ๋ถ๋ฅธ๋ค.
ํํฐ๋ฅผ ์ ์ฉํ๋ฉด ์ ๋ ๊ฒ ์ด๋ฏธ์ง๊ฐ ๋ธ๋ฌ๋๋ ํ์์ด ๋ํ๋๋ค.

Uniform Mean Filtering์ ์ฅ์ ์ Separable Filter๋ผ์ ๋๊ฐ ๋ฒกํฐ์ ๊ณฑ์ผ๋ก ๋ค์์ฒ๋ผ ๋ถ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ด๋ค.
ํํฐ๋ง ๋ฐํ์์ ์์ฒญ ๋์๋๋ค..!!
Convolution ์ฐ์ฐ์ ๊ฒฐํฉ๋ฒ์น์ด ์ฑ๋ฆฝํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฅํ ์ด์ผ๊ธฐ๋ค.
2. 1. Uniform Mean Filter OpenCv


์ด๋ฏธ์ง boundary๋ถ๋ถ์ zero padding์ ์ฌ์ฉํ์๋ค. ์ปค๋์ด ์ด๋ฏธ์ง ๋ฐ์ผ๋ก ์์ ธ๋๊ฐ๊ธฐ ๋๋ฌธ์ ๊ทธ ๋ถ๋ถ์ ๊ฐ์ 0์ผ๋ก ๊ณ์ฐํ์๋ค.
๊ทธ๋์ ์ด๋ฏธ์ง์ boundary์ ์์ด ์ข ์ด๋์ด ๊ฒ์ ๋ณผ ์ ์๋ค.
ํ์ต์ ์ํด ์ง์ Uniform Mean Filter ๊ตฌํ์ ํด๋ณด์๋ค. ๊ตฌํ์ separable๋ฐฉ์์ผ๋ก ํด๋์๋ค
์ง์ ๊ตฌํ ํค๋ : filter.h
#pragma once
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstring>
using namespace cv;
using namespace std;
#define IM_TYPE CV_8UC1 //๊ธฐ๋ณธ 8bit grayscale
#if (IM_TYPE == CV_8UC1)
typedef uchar G;
#elif (IM_TYPE == CV_16UC1)
typedef ushort G;
#elif (IM_TYPE == CV_32FC1)
typedef float G;
#endif
// =======================================
// ํํฐ ํจ์ ์ ์ธ
// =======================================
// Uniform Mean Filter ๊ตฌํ. Separable Filter๋ก ๋ง๋ ๋ค.
Mat UniformMeanFilter(const Mat input, int nx, int ny, const char* opt) {
int row = input.rows;
int col = input.cols;
int kernel_x = 2 * nx + 1;
int kernel_y = 2 * ny + 1;
float kx = 1.0f / kernel_x;
float ky = 1.0f / kernel_y;
Mat temp = Mat::zeros(row, col, input.type()); // ๊ฐ๋ก ํํฐ๋ง ๊ฒฐ๊ณผ
Mat output = Mat::zeros(row, col, input.type()); // ์ธ๋ก ํํฐ๋ง ๊ฒฐ๊ณผ
// --- Pass 1: ๊ฐ๋ก ๋ฐฉํฅ ํํฐ๋ง ---
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
float sum = 0.0f;
float weight = 0.0f;
for (int b = -nx; b <= nx; b++) {
int jj = j + b;
if (!strcmp(opt, "zero-paddle")) {
if (jj >= 0 && jj < col)
sum += kx * (float)input.at<G>(i, jj);
}
else if (!strcmp(opt, "mirroring")) {
if (jj < 0) jj = -jj;
else if (jj >= col) jj = 2 * col - jj - 2;
sum += kx * (float)input.at<G>(i, jj);
}
else if (!strcmp(opt, "adjustkernel")) {
if (jj >= 0 && jj < col) {
sum += kx * (float)input.at<G>(i, jj);
weight += kx;
}
}
}
if (!strcmp(opt, "adjustkernel") && weight != 0)
temp.at<G>(i, j) = (G)(sum / weight);
else
temp.at<G>(i, j) = (G)(sum);
}
}
// --- Pass 2: ์ธ๋ก ๋ฐฉํฅ ํํฐ๋ง ---
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
float sum = 0.0f;
float weight = 0.0f;
for (int a = -ny; a <= ny; a++) {
int ii = i + a;
if (!strcmp(opt, "zero-paddle")) {
if (ii >= 0 && ii < row)
sum += ky * (float)temp.at<G>(ii, j);
}
else if (!strcmp(opt, "mirroring")) {
if (ii < 0) ii = -ii;
else if (ii >= row) ii = 2 * row - ii - 2;
sum += ky * (float)temp.at<G>(ii, j);
}
else if (!strcmp(opt, "adjustkernel")) {
if (ii >= 0 && ii < row) {
sum += ky * (float)temp.at<G>(ii, j);
weight += ky;
}
}
}
if (!strcmp(opt, "adjustkernel") && weight != 0)
output.at<G>(i, j) = (G)(sum / weight);
else
output.at<G>(i, j) = (G)(sum);
}
}
return output;
}
OpenCV ํจ์ ์ฌ์ฉ
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// ์ง์ ๊ตฌํํ ํํฐ ํจ์ ํฌํจ๋ ํค๋
#include "filter.h"
int main() {
Mat src = imread("lena.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {
cout << "์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค." << endl;
return -1;
}
int nx = 3; // ๊ฐ๋ก ๋ฐฉํฅ ์ ๋ฐ ํฌ๊ธฐ โ ์ ์ฒด ์ปค๋ ํฌ๊ธฐ: 7
int ny = 3; // ์ธ๋ก ๋ฐฉํฅ ์ ๋ฐ ํฌ๊ธฐ โ ์ ์ฒด ์ปค๋ ํฌ๊ธฐ: 7
// ์ง์ ๊ตฌํํ ํํฐ (zero-padding ๋ฐฉ์), separable filter๊ตฌํ
Mat custom_filtered = UniformMeanFilter(src, nx, ny, "zero-paddle");
// OpenCV sepFilter2D ์ฌ์ฉ, separable filter
int kernel_x = 2 * nx + 1;
int kernel_y = 2 * ny + 1;
Mat kernelX = Mat::ones(1, kernel_x, CV_32F) / static_cast<float>(kernel_x);
Mat kernelY = Mat::ones(kernel_y, 1, CV_32F) / static_cast<float>(kernel_y);
Mat sep_filtered;
sepFilter2D(src, sep_filtered, -1, kernelX, kernelY, Point(-1, -1), 0, BORDER_CONSTANT);
// OpenCV boxFilter ์ฌ์ฉ
Mat box_filtered;
boxFilter(src, box_filtered, -1, Size(kernel_x, kernel_y), Point(-1, -1), true, BORDER_CONSTANT);
// OpenCV blur ์ฌ์ฉ: ์๋ Border Default ์ฌ์ฉ
Mat blur_filtered;
blur(src, blur_filtered, Size(kernel_x, kernel_y));
// ๊ฒฐ๊ณผ ์ถ๋ ฅ
imshow("Original", src);
imshow("Custom Uniform Mean Filter", custom_filtered);
imshow("OpenCV sepFilter2D", sep_filtered);
imshow("OpenCV boxFilter", box_filtered);
imshow("OpenCV blur", blur_filtered);
waitKey(0);
return 0;
}
3. Gaussian Filter
๊ฐ์ฐ์์ ํํฐ๋ ์ ๊ท๋ถํฌ๋ฅผ ์ด์ฉํ ํํฐ๋ง์ด๋ค.


๋ฌธ์ ๋ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ํํฐ๋ ํฌ๊ธฐ๊ฐ ์ ํด์ ธ ์๋ค. ์๊น์ Uniform Mean Filter๋ 3x3์ง๋ฆฌ๋ก ๋ง๋ค์ด์ ๋ณด์๋ค.
๊ทผ๋ฐ, ๊ฐ์ฐ์์ ๋ถํฌ๋
๋ฐ๋ผ์ ๊ฐ์ฐ์์์ผ๋ก๋ง ์ปค๋์ ๋ง๋ค๋ฉด ์ ๋ถ๊ฐ์ด 1์ด ๋์ง ์๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ํํฐ์ ์ ๋ถ๊ฐ์ผ๋ก ํ๋ฒ normalizeํด๋ฌ์ผ ํ๋ค.

๊ฐ์ฐ์์ ํํฐ์ ์ฅ์ ์ ์๋Separable Filter๋ผ๋ ๊ฒ์ด๋ค.
๊ทธ๋์ ํํฐ๋ง ์์ ํ์
ํ๊ฒ

4. Sobel Filter
์๋ฒจ ํํฐ๋ ์์์ฒ๋ฆฌ์์ ์ฃ์ง ๊ฒ์ถ์ ์ฌ์ฉ๋๋ ํํฐ๋ง ๋ฐฉ์์ด๋ค.
์ด๋ฏธ์ง์์ ๊ฐ ํฝ์ ์ ๋ฐ๊ธฐ ๊ฐ์ ์ค์ฌ์ผ๋ก ๊ทธ ์ฃผ๋ณ ํฝ์ ๋ค์ ๋ฐ๊ธฐ ๊ฐ์ ์กฐํฉํ์ฌ ๊ทธ ํฝ์ ์ gradient๋ฅผ ๊ณ์ฐํ์ฌ ์ฌ์ฉํ๋ค.

๋ง์คํฌ ๋ด๋ถ์ x,y์ถ intensity์ ๋ํ ๋ฏธ๋ถ ๊ฐ์ ๊ฐ๊ฐ
์ด๋ ๊ฒ๋ง ๋ณด๋ฉด ๋ฌด์จ๋ง์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ๋ค...

๋ณดํต ์ด๋ฏธ์ง์์ ์ฃ์ง๋ถ๋ถ์ ์ ๋ ๊ฒ Intensity๊ฐ ๊ธ๊ฒฉํ๊ฒ ๋ณํ๋ ๋ถ๋ถ์ด๋ค.
์ด ์ฃ์ง ๋ถ๋ถ์ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด, ์ด ์ง์ ์์ ๋ฏธ๋ถ๊ฐ์ด ๊ทน๋๊ฐ ๋๋ ๊ฒ์ ์ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ๊ฐ Sobel Filtering์ผ๋ก ๊ฒ์ถํ๊ณ ์ถ์ ๋ถ๋ถ์ด๋ค.
๊ทธ๋์ ์๋ฒจ ํํฐ๋ง์์๋ ์ปค๋์ ์ด์ฉํด ๋ฏธ๋ถ๊ฐ์ ๊ณ์ฐํ๋ ค ํ๋ค.
์ด ๋ฏธ๋ถ๊ฐ์ x์ ๋ํด์, y์ ๋ํด์ ์ด ๋๋ฒ ๊ตฌํ๊ฒ ๋๊ณ
๊ทธ ๊ฐ์ ํฉํ์ฌ ํฝ์ ์ ๊ฐ์ ๊ฒฐ์ ํ๊ฒ ๋ค๋ ๊ฒ์ด๋ค.
๊ทธ๋์ ์๋ฒจ ํํฐ๋ง์๋ x์ถ ํํฐ ๋ง์คํฌ, y์ถ ํํฐ ๋ง์คํฌ๊ฐ ๋ฐ๋ก ์๋ค.
๊ทธ๋์ ๋ฏธ๋ถ๊ฐ์ ์ด๋ป๊ฒ ๊ณ์ฐํ๋๊ฑธ๊น?
๋ฏธ๋ถ์ ๊ณ์ฐํ๋ 3๊ฐ์ง ๋ํ ๋ฐฉ์ ์ค ์ค์์ฐจ๋ถ ๋ฐฉ์์ ์ฐจ์ฉํ์ฌ ๊ณ์ฐํ๋ค.

์ฆ, ์ฃผ๋ณ ์ด์์ ๊ฐ์ผ๋ก ๋ฏธ๋ถ์ ํ๋ ๊ฒ์ด๋ ์ฌํ ๋ฐฐ์ด ํํฐ๋ง๊ณผ ์ ๊ทผ์ ๋น์ทํ ์ ์ด๋ค.

๊ทธ๋์ x์ถ ๋ฏธ๋ถ์ ํ ๋์๋
(
๋ค์ ์๋ฒจ ํํฐ๋ง
์ด์ ๋ฏธ๋ถ์ ์ด๋ป๊ฒ ํ๋์ง ์์์ผ๋ฉด ์ด์ ๋ ์๋ฒจ ํํฐ๋ง์ x,y์ถ ๋ง์คํฌ๋ฅผ ๋ณด์.

๋นจ๊ฐ ๋ฐ์ค ์์ ๋ ํํฐ๊ฐ ๊ฐ๊ฐ ์๋ฒจ ํํฐ ๋ง์คํฌ์ x๋ง์คํฌ, y๋ง์คํฌ์ ํด๋น๋๋ค.
๊ทธ ์ผ์ชฝ์ Prewitt ํํฐ๋ง์ด ์ฐ๋ฆฌ๊ฐ ์์์ ์ดํด๋ณธ ๋ฏธ๋ถ ๋ฐฉ์์ ๋ณํ์์ด ๋ค๊ณ ์จ ๊ฒ์ด๋ค.
์๋ฒจ ํํฐ๋ง์ ํ๊ฒ ํฝ์ ์ ๋ฐ๋ก ์ธ์ ํ ํฝ์ ๋ค์ ๊ฐ์ค์น๋ฅผ 2 ๋ถ์ฌํ๋ค.
์ด ๋ง์คํฌ๋ฅผ ๊ฐ์ง๊ณ ๊ฐ๊ฐ

5. Laplacian Filter
์๋ฒจ ํํฐ์์๋ ์ฃ์ง ๊ฒ์ถ์ ์ํด ๋ฏธ๋ถ์ ์ฌ์ฉํด ํํฐ๋ง ํ๋ค.
๋ผํ๋ผ์์์ ์ด์ ์ด์ฐจ ๋ฏธ๋ถ์ ํ๋ค...

๋ผํ๋ผ์์ ํํฐ๋ ์ด๋ ๊ฒ ์ด์ฐจ ๋ฏธ๋ถ ๊ฐ ํฉ์ ์ ๋๊ฐ์ output์ผ๋ก ํ๋ค.
๋ฐ๋ผ์ ๋ง์คํฌ๋ ๋ค์์ฒ๋ผ ์๊ธฐ๊ฒ ๋๋ค. (๋คํํ ํ๋ฒํ๊ฒ ์๊ฒผ๋ค.)

'๐ฆAI > Computer Vision' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Computer Vision/OpenCV] 13. Image Noise & Degradation (0) | 2025.04.05 |
---|---|
[Computer Vision/OpenCV] 12. Unsharp Masking (0) | 2025.04.04 |
[Computer Vision/OpenCV] 10. Spatial Filtering & Convolution ๊ฐ๋ (0) | 2025.03.31 |
[Computer Vision/OpenCV] 9. Histogram Matching (0) | 2025.03.27 |
[Computer Vision/OpenCV] 8. Histogram Equalization (0) | 2025.03.23 |