The Savitzky–Golay method essentially performs a local polynomial regression (of degree

Savitzky–Golay 필터는 일정한 간격으로 주어진 데이터들이 있을 때(이들 데이터는 원래의 정보와 노이즈를 같이 포함한다), 각각의 점에서 주변의 점들을 가장 잘 피팅하는
간단한 예로, 2차의 다항식과 5개의 데이터 점
을 이용해서 중앙에서의 값을 결정하는 방법을 살펴보자. 사용하려고 하는 다항식은
이다. 다항식의 계수는 다항식의 값과 실제 데이터의 값과의 차이를 최소화시키도록 선택해야 한다. 즉, 최소자승의 원리를 적용하여서 구하면 된다. 계산된 다항식의 값과 실제 데이터 값 사이의 차의 제곱을 구하면:
이 식의
이 식을 만족시키는
위에서 계수

좌변의 5행 3열 행렬을
이 식은 임의의

2차 다항식일 때, 같은 방식으로 다양한 윈도 크기에 따른 계수를 구할 수 있다.
*크기(
std::vector<double> SavitzkyGolayFilter(std::vector<double>& data, double W[], int wsz) {
const int hwsz = wsz >> 1;
wsz = (hwsz<<1) + 1;
std::vector<double> padded(data.size() + 2 * hwsz);
// reflective boundary conditions;
// [hw]...[1][0][1][2]...[hw]....[n-1+hw][n-2+hw][n-3+hw]....[n-1];
for (int i = 0; i < hwsz; i++) {
padded[i] = data[hwsz-i];
padded[i+data.size()+hwsz] = data[data.size()-2-i];
}
for (int i = data.size(); i-->0;) padded[i+hwsz] = data[i];
//
std::vector<double> smoothed(data.size());
double wsum = 0;
for (int i = 0; i < wsz; i++) wsum += W[i];
for (int i = data.size(); i-->0;) {
double *ppad = &padded[i];
double fsum = 0;
for (int k = 0; k < wsz; k++) fsum += ppad[k] * W[k];
smoothed[i] = fsum / wsum;
}
return smoothed;
};

일반적인 찻수(order)에 대한 필터 계수 계산;
std::vector<double> sgFilterCoeffs(int width, int order/* = 2*/) {
// ASSERT(width >= order+1);
int hwidth = width >> 1;
width = (hwidth << 1) + 1; // width = odd number;
// design matrix;
std::vector<double> D((order+1) * width);
for (int i = 0; i < width; i++) {
double x = double(i) - hwidth; // -hwidth <= x <= hwidth;
double *pD = &D[i*(order+1)];
pD[0] = 1;
for (int k = 1; k <= order; k++)
pD[k] = pD[k-1] * x;
};
// scattering matrix;
std::vector<double> S((order+1)*(order+1)); // S=~D.D;
for (int i = 0; i <= order; i++)
for (int j = i; j <= order; j++) {
double s = 0;
for (int k = 0; k < width; k++)
s += D[k*(order+1) + i] * D[k*(order+1) + j];
S[i*(order+1) + j] = s;
}
for (int i = 0; i <= order; i++)
for (int j = 0; j < i; j++)
S[i*(order+1) + j]= S[j*(order+1) + i];
// ccmath library;
psinv(&S[0], order+1);
// filter coeffs = 0-th row fo S.~D;
std::vector<double> filter;
for (int i = 0; i < width; i++) {
double s = 0;
for (int k = 0; k <= order; k++)
s += S[k] * D[i*(order+1) + k];
filter.push_back(s);
}
return filter;
}
'Image Recognition' 카테고리의 다른 글
Adaboost (0) | 2010.12.28 |
---|---|
Blur Detection (0) | 2010.05.25 |
Watershed Algorithm 구현 (0) | 2010.03.19 |
Retinex 알고리즘 (11) | 2010.02.03 |
Gaussian Mixture Model & KMeans (4) | 2010.01.30 |