cv::getAffineTransform
仿射變換
(1)一個任意的仿射變換都能表示為乘以一個矩陣(線性變換)接着再加上一個向量(平移)。
所以,我們能夠用仿射變換來表示:
旋轉(線性變換)
平移(向量加)
縮放操作(線性變換)
仿射變換代表的是兩幅圖之間的聯系。
我們通常使用矩陣來表示仿射變換。
考慮到我們要使用矩陣和
對二維向量
做變換, 所以也能表示為下列形式:
(2)求仿射變換
上文有提到過仿射變換基本表示的就是兩幅圖片之間的聯系。關於這種聯系的信息大致可從以下兩種場景獲得:
我們已知 和T而且我們知道他們是有聯系的。接下來我們的工作就是求出矩陣
我們已知 Xand T。要想求得 。我們只要應用算式即可。對於這種聯系的信息可以用矩陣M清晰的表達(即給出明確的2×3矩陣)或者也可以用兩幅圖片點之間幾何關系來表達.
因為矩陣聯系着兩幅圖片,我們以其表示兩圖中各三點直接的聯系為例。見下圖:
點1,2和3(在圖一中形成一個三角形)與圖二中三個點一一映射, 仍然形成三角形,但形狀已經大大改變。如果我們能通過這樣兩組三點求出仿射變換(你能選擇自己喜歡的點), 接下來我們就能把仿射變換應用到圖像中所有的點。
Opencv接口
1 Mat cv::getAffineTransform(const Point2f src[], 2 const Point2f dst[] 3 ) 4 參數 5 src 源圖像中三角形頂點的坐標。 6 dst 目標圖像中相應三角形頂點的坐標。
從三對對應點計算仿射變換。
該函數計算2×3矩陣的仿射變換為:
1 void ES::ImageProcessing::affineTransformOper(cv::Mat* dst) 2 { 3 Mat src = imread("lena.jpg", IMREAD_COLOR); 4 cv::resize(src, src, Size(src.rows / 4 * 3, src.cols / 4 * 3)); 5 ImageProcessingParams* img_params = static_cast<ImageProcessingParams*>(m_params); 6 //源圖像和目標圖像上分別一一映射的三個點
7 Point2f srcTri[3]; 8 Point2f dstTri[3]; 9 srcTri[0] = Point2f(0, 0); 10 srcTri[1] = Point2f(src.cols - 1, 0); 11 srcTri[2] = Point2f(0, src.rows - 1); 12 // dstTri[0] = Point2f(src.cols*0.0, src.rows*0.33); 13 // dstTri[1] = Point2f(src.cols*0.85, src.rows*0.25); 14 // dstTri[2] = Point2f(src.cols*0.15, src.rows*0.7);
15 for (int index = 0; index < img_params->m_ptScales.size() / 2; ++index) 16 { 17 dstTri[index] = Point2f(img_params->m_ptScales[2 * index] * src.cols, 18 img_params->m_ptScales[2 * index + 1] * src.rows); 19 } 20 //通過這兩組點, 使用getAffineTransform來求出仿射變換
21 Mat warp_mat(2, 3, CV_32FC1); 22 warp_mat = getAffineTransform(srcTri, dstTri); 23 //求得的仿射變換應用到源圖像
24 Mat mat; 25 warpAffine(src, mat, warp_mat, mat.size()); 26 // 27 Mat mergeMat(src.rows, src.cols + mat.cols, src.type()); 28 Mat submat = mergeMat.colRange(0, src.cols); 29 src.copyTo(submat); 30 submat = mergeMat.colRange(src.cols, src.cols + mat.cols); 31 mat.copyTo(submat); 32 mergeMat.copyTo(*dst); 33 }