물론, 이들 central moment을 이용해서 만든 공분산 행렬(covariance matrix)
$$ \Sigma = \left( \begin{array}{cc} \mu_{20} & \mu_{11} \\ \mu_{11} & \mu_{02} \end{array} \right) $$의 두 eigenvalue 중 큰 값에 해당하는 eigenvector가 물체의 정렬 방향을 알려준다.
두 점 $A$와 $B$가 만드는 선분 $\overline{AB}$가 있고, 한 점 $P$에서 이 선분까지 거리를 구하려고 할 때 단순히 $\overline{AB}$를 통과하는 직선과 점 $P$의 거리를 구해서 쓰면 안 된다. 그림처럼 $P$가 $P'$의 위치에 있는 경우에 $\overline{AB}$를 통과하는 직선과의 거리가 더 짧지만, 선분과의 거리는 $P'$와 $A$와 거리로 주어진다. 마찬가지로 $P$가 $P''$에 있을 때는 점 $B$와 거리가 최단거리다. 정리하면, 1. 선분 $\overline{AP}$와 $\overline{AB}$의 사이각이 $90^\circ$를 넘는 경우는 $A$까지 거리; $$\cos (\text{사이각}) = \frac{(P.x - A.x)*(B.x - A.x) + (P.y - A.y)*(B.y - A.y)}{\overline{AP}\text{ 길이} * \overline{AB}\text{ 길이}} < 0 .$$ 2. 선분 $\overline{AP}$의 $\overline{AB}$로의 정사영 길이가 $\overline{AB}$의 길이보다 클 때는 $B$까지 거리: $$\text{정사영 길이} = \frac{(P.x - A.x)*(B.x - A.x) + (P.y - A.y)*(B.y - A.y)}{ \overline{AB}\text{ 길이}} > \overline{AB}\text{ 길이} .$$ 3. 직선 $\overline{AB}$까지 거리 = $\overline{AP}$의 수선으로 정사영 길이: $$\text{수선으로 정사영} = \frac{-(P.x - A.x)*(B.y - A.y) + (P.y - A.y)*(B.x - A.x)}{\overline{AB}\text{ 길이}} .$$
이미지 처리에서 픽셀 좌표는 간격이 1인 2차원 그리드의 교차점으로 볼 수 있다. 이미지를 확대하거나 축소할 때, 픽셀과 픽셀 사이 구간에서 값이 필요한 경우가 생긴다. 간단하게는 가장 가까운 주변 픽셀의 값을 그대로 가져다 쓰거나, 또는 주변의 4 픽셀 값을 선형보간해서 사용할 수 있다. 2차원 그리드에서 선형보간은 bilinear interpolation이다. 이 보간법은 속도는 빠르지만 픽셀 값이 인접 그리드에서의 값으로 부드럽게 이어지지 않는 단점이 있다. 인접 그리드 경계에서 픽셀 값이 부드럽게 이어지기 위해서는 적어도 1차 미분이 연속인 보간법을 사용해야 하는데, 이러한 조건을 만족시키는 가장 낮은 찾수의 다항식 보간법이 bicubic interpolation이다.
4점 $(0,0), (0,1), (1,0),(1,1)$을 꼭짓점으로 하는 정사각형 내의 임의 지점 $D=\{(x, y)| 0 \le x\le1, 0\le y \le 1\}$ 에서 픽셀 값을 주는 보간곡면 $f(x, y)$을 주변의 16개 점 $\{(i, j)| -1 \le i \le 2, -1 \le j \le 2\}$에서 픽셀 값을 사용하는 bicubic interpolation을 이용해서 추정할 수 있다. 곡면 $f(x, y)$은 $x$와 $y$의 3차 함수로 다음과 같이 쓸 수 있다.
이 역행렬은 mathematica나 maple 등의 프로그램을 이용하면 쉽게 구할 수 있다. 이렇게 구한 $f(x, y)$는 $[0,1]\times [0,1]$ 영역에서 연속인 smooth 한 곡면을 형성한다. 또한 인접하는 그리드 영역의 곡면과 경계에서 smooth 하게 연결된다.
* 원본 4x4 이미지(RGB): nearest-neighbor interploation으로 256x256 크기로 만듦;
* bicubic interpolation 결과 (256x256):
* bilinear interpolation 결과 (256x256):
코드 구현 일부: bicubic interpolation은 주변의 16개 픽셀 정보가 필요한데, 가장자리 픽셀인 경우는 이를 충족시킬 수 없으므로 이를 해결하기 위해 영역 밖은 가장자리 픽셀이 반복된 것으로 처리하는 것이 가장 쉽다. 그리고 소스 영상이 큰 경우에는 문제가 되지 않지만 예제처럼 작은 소스 영상의 경우는 가장자리 부근에서 단순 채움을 사용하면 왜곡이 발생한다. 이를 해소하기 위해서는 소스 픽셀 위치가 픽셀의 중간을 나타낸 것으로 처리하면 된다.
for (int y = 0; y < dstHeight; y++) {
BYTE *pdst = (BYTE *)dst.GetLinePtr(y);
double src_fy = y * scaley - 0.5;
int src_iy = int(floor(src_fy));
double ry = src_fy - src_iy;
for (int x = 0; x < dstWidth; x++) {
double src_fx = x * scalex - 0.5;
int src_ix = int(floor(src_fx));
double rx = src_fx - src_ix;
// Fill interpolation matrices for R,G,B;
for (int by = 0; by < 4; by++) {
int yy = by + src_iy - 1;
CLAMP(yy, 0, srcHeight - 1);
BYTE *psrc = (BYTE *)src.GetLinePtr(yy);
for (int ax = 0; ax < 4; ax++) {
int xx = ax + src_ix - 1;
CLAMP(xx, 0, srcWidth - 1);
B[ax][by] = psrc[3 * xx + 0];
G[ax][by] = psrc[3 * xx + 1];
R[ax][by] = psrc[3 * xx + 2];
}
}
int bb = (int)BicubicInterpolate(B, rx, ry);
int gg = (int)BicubicInterpolate(G, rx, ry);
int rr = (int)BicubicInterpolate(R, rx, ry);
*pdst++ = bb < 0 ? 0: bb > 255 ? 255: bb;
*pdst++ = gg < 0 ? 0: gg > 255 ? 255: gg;
*pdst++ = rr < 0 ? 0: rr > 255 ? 255: rr;
}
};