| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- APP
- Class
- UNO
- stream
- Encapusulation
- Pointer
- parameter
- flutter
- digitalRead
- Read
- subpixel
- atmega328
- Android
- edge
- mfc
- sensor
- file access
- wpf
- Binary
- Contour
- c++
- compare
- SERIAL
- public
- Gaussian
- Gradient
- Unity
- Filtering
- aduino
- memory
- Today
- Total
폴크(FOLC)
치수 계산하기 - robust edge detection 4 본문
Total Variation (TV)과 Sparsity 기반의 영상 복원 혹은 영상 복구 알고리즘은 잡음 제거, 압축 센싱 복원, 이미지 인페인팅 등 다양한 영상 처리 분야에서 널리 활용됩니다.
Total Variation (TV) Regularization
TV 정규화는 영상의 급격한 변화(예: 에지)는 유지하면서, 잡음과 같은 고주파 성분을 억제하는 정규화 방법입니다. 주로 isotropic TV 또는 anisotropic TV로 나뉩니다

이는 영상의 gradient의 L1 norm을 최소화하여 결과적으로 평탄한 영역은 부드럽게 만들고, edge는 보존합니다.
Sparsity Constraint
Sparsity는 이미지가 특정 basis(예: Wavelet, DCT 등)에서 희소 표현이 가능하다는 가정을 활용합니다. 일반적으로 다음과 같은 형태로 표현됩니다:

결합된 모델: TV + Sparsity
이미지 복구 문제를 TV 및 Sparsity로 정식화하면 다음과 같은 최적화 문제가 됩니다:

예제
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cmath>
using namespace cv;
using namespace std;
// Parameters
const double lambda_tv = 0.1;
const double lambda_sp = 0.05;
const int maxIter = 100;
const double tau = 0.125;
// Total Variation Gradient Descent Step
void computeTVGradient(const Mat& u, Mat& grad) {
grad = Mat::zeros(u.size(), CV_64F);
for (int y = 0; y < u.rows - 1; ++y) {
for (int x = 0; x < u.cols - 1; ++x) {
double dx = u.at<double>(y, x+1) - u.at<double>(y, x);
double dy = u.at<double>(y+1, x) - u.at<double>(y, x);
double norm = sqrt(dx*dx + dy*dy + 1e-8);
grad.at<double>(y, x) -= lambda_tv * (dx / norm + dy / norm);
}
}
}
// Soft thresholding for sparsity
void softThreshold(Mat& coeffs, double thresh) {
for (int y = 0; y < coeffs.rows; ++y) {
for (int x = 0; x < coeffs.cols; ++x) {
double& val = coeffs.at<double>(y, x);
val = std::copysign(std::max(std::abs(val) - thresh, 0.0), val);
}
}
}
// Main Optimization Loop
Mat tvSparsityDenoise(const Mat& noisy) {
Mat u = noisy.clone();
Mat grad, dctCoeffs;
for (int i = 0; i < maxIter; ++i) {
// TV gradient
computeTVGradient(u, grad);
// Gradient descent step
u -= tau * grad;
// Sparsity in DCT domain
dct(u, dctCoeffs);
softThreshold(dctCoeffs, lambda_sp);
idct(dctCoeffs, u);
}
return u;
}
int main() {
Mat input = imread("noisy_image.png", IMREAD_GRAYSCALE);
if (input.empty()) {
cout << "Image not found!" << endl;
return -1;
}
input.convertTo(input, CV_64F, 1.0 / 255.0);
Mat denoised = tvSparsityDenoise(input);
denoised.convertTo(denoised, CV_8U, 255.0);
imshow("Original", input);
imshow("Denoised", denoised);
waitKey(0);
return 0;
}