| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- Unity
- Binary
- Gaussian
- stream
- c++
- aduino
- Read
- compare
- memory
- digitalRead
- file access
- Filtering
- atmega328
- public
- UNO
- Encapusulation
- APP
- Contour
- flutter
- edge
- Pointer
- mfc
- sensor
- wpf
- Gradient
- Class
- Android
- subpixel
- parameter
- SERIAL
- Today
- Total
폴크(FOLC)
치수 계산하기 - smooth filtering 본문
Savitzky-Golay 필터는 신호 처리에서 널리 사용되는 데이터 평활화 기법으로, 특히 노이즈를 줄이면서 신호의 주요 특성(예: 피크, 경향선 등)을 보존해야 할 때 효과적입니다.
이동 윈도우 내의 다항 회귀를 통해 중심값을 재계산하여 평활화하는 방법입니다. 보통 단순 이동 평균은 신호를 과도하게 평탄화하여 중요한 피크나 변화를 손실할 수 있는데, 이 필터는 신호의 형상 보존에 강점이 있습니다.
원리
- 주어진 윈도우 크기와 다항 차수를 바탕으로, 해당 구간의 데이터를 최소자승법(Least Squares) 으로 다항식에 맞추고 중심값을 계산합니다.
- 이는 선형 컨볼루션처럼 미리 계산된 계수를 사용하여 구현할 수 있습니다.
파라미터
- window size (odd integer): 적용할 데이터 포인트의 개수
- polynomial order: 다항식 차수 (2~4 정도가 보통 사용됨)
예제
#include <iostream>
#include <vector>
#include <numeric>
#include <cmath>
std::vector<double> savitzkyGolaySmooth(const std::vector<double>& data, int windowSize, int polyOrder) {
int halfWindow = windowSize / 2;
int size = data.size();
std::vector<double> result(size, 0.0);
// Precompute convolution coefficients (assuming polyOrder == 2 for simplicity)
// For general implementation, you need to use matrix inversion.
std::vector<double> coeffs(windowSize);
int m = halfWindow;
for (int i = -m; i <= m; ++i) {
coeffs[i + m] = 1.0 - (3.0 * i * i) / (m * (m + 1)); // Quadratic S-G
}
// Normalize coefficients
double coeffSum = std::accumulate(coeffs.begin(), coeffs.end(), 0.0);
for (auto& c : coeffs) c /= coeffSum;
// Apply filter
for (int i = 0; i < size; ++i) {
double smoothed = 0.0;
for (int j = -m; j <= m; ++j) {
int idx = i + j;
if (idx < 0) idx = 0;
if (idx >= size) idx = size - 1;
smoothed += data[idx] * coeffs[j + m];
}
result[i] = smoothed;
}
return result;
}
int main() {
std::vector<double> rawData = {10, 12, 15, 14, 13, 15, 18, 20, 19, 17};
int windowSize = 5; // Must be odd
int polyOrder = 2;
std::vector<double> smoothed = savitzkyGolaySmooth(rawData, windowSize, polyOrder);
for (double v : smoothed) {
std::cout << v << " ";
}
std::cout << std::endl;
return 0;
}