머리말
이전 글에서는 이미지 피라미드에 대해 설명했습니다. 이번 글에서는 아핀 변환에 대해 알아보겠습니다.
아핀?
모든 아핀 변환은 행렬(선형 변화)과 벡터(병진 변화)를 곱하여 변환될 수 있습니다.
사실 아핀은 두 사진의 변신 관계입니다.
예를 들어 아핀 변환(크기 조정, 회전, 이동 등)을 통해 이미지에 대한 작업을 수행할 수 있습니다.
수학 문제
아핀 문제를 풀기 전에 수학 문제부터 풀어볼까요.
그림과 같이 점 (x1, y1)은 원점을 기준으로 각도 a 만큼 회전하는데 이 점은 어디로 가는 걸까요?
좌표계를 극좌표계로 바꾸면 점 (x1, y1)은 (r, β)가 되고, 회전하면 (r, α β)가 됩니다.
데카르트 좌표계로 돌아가면 회전된 점은 (cos(α β) * r, sin(α β) * r)이 됩니다.
그런 다음 공식을 사용하세요 :
cos(α β)=cosαcosβ-sinαsinβ
sin(α β)=sinαcosβ cosαsinβ
원점은 (cosβ * r, sinβ * r)이므로 (x1 * cosα - y1 * sinα, x1 *로 새 점을 쉽게 얻을 수 있습니다. 시나α y1 *cosα).
여기에서 회전 변환 공식을 유도할 수 있습니다.
그러면 번역은 비교적 간단합니다. 벡터(c, d)를 추가하는 것과 같습니다.
변환 행렬 함수 구현 가져오기
보통 우리는 아핀 변환을 표현하기 위해 행렬을 사용합니다.
여기서 A는 회전 스케일링 변환이고 B는 변환 변환입니다. 그러면 결과 T는 다음을 충족합니다.
또는
즉,
var getRotationArray2D = 함수(__angle, __x, __y){
var sin = Math.sin(__angle) || 0,
cos = Math.cos(__angle) || | 0,
y = __y || 0;
return [cos, -sin, -x,
sin, cos, -y
};
이런 방식으로 아핀 변환 행렬을 얻습니다.
물론 이 구현 자체에는 원점이 왼쪽 상단에 고정되어 있기 때문에 몇 가지 문제가 있습니다.
아핀 변환 구현
var warpAffine = function(__src, __rotArray, __dst){
(__src && __rotArray) || error(arguments.callee, IS_UNDEFINED_OR_NULL/* {line} */)
if(__src.type && __src.type === "CV_RGBA"){
var height = __src.row,
width = __src.col,
dst = __dst || new Mat(height, width, CV_RGBA),
sData = new Uint32Array(__src.buffer),
dData = new Uint32Array(dst.buffer);
var i, j, xs, ys, x, y, nowPix; >for (j = 0, nowPix = 0; j xs = __rotArray[1] * j __rotArray[2]
ys = __rotArray[4] * j __rotArray[5] ;
for(i = 0; i
if(xs > 0 && ys > 0 && xs < 너비 && ys < 높이){
y = ys | 0
dData[nowPix] = sData x]
}else{
dData[nowPix] = 4278190080; //검정색
}
}
}
}else{
error(arguments.callee, UNSPPORT_DATA_TYPE /* {line} */);
}
return
};
이 함수는 먼저 행렬 데이터를 32비트 형식으로 변환하며, 각 요소를 연산하는 것은 각 픽셀을 연산하는 것과 동일합니다.
그런 다음 모든 요소를 순회하고 해당 지점에 값을 할당합니다.
효과