Homography 筆記(附 OpenCV 程式碼)
翻譯自 https://www.learnopencv.com/homography-examples-using-opencv-python-c/ 。
依個人口味略作修改,侵權刪。
據聖經神話的記載,巴別塔(The Tower of Babel)是人類的第一個工程災難。這個專案具備了所有的條件,但是仍然失敗了。因為上帝混淆了人類的語言,從而使得他們無法再有效的溝通協作,進而導致了通天塔的崩潰和人類的混亂。
在我看來,像 Homography 這樣的術語在時刻提醒我們,我們仍在為語言構成的溝通鴻溝而掙扎。Homography 就是一個很簡單的概念卻起了一個很唬人的名字。
什麼是 Homography?
考慮 同一個平面(比如書皮)的兩張圖片,紅點表示同一個物理座標點在兩張圖片上的各自位置。在 CV 術語中,我們稱之為對應點。
Homography 就是將一張影象上的點對映到另一張影象上對應點的3x3變換矩陣.
A Homography is a transformation ( a 3×3 matrix ) that maps the points in one image to the corresponding points in the other image.
因為 Homography 是一個 3x3 的 矩陣,所以我們可以把它寫成
對於圖中的一對兒對應點,位於圖一的 (x1, y1) 和 位於圖二的 (x2, y2). H 把二者對映關係建立起來
使用 Homography 進行影象對齊(Image Alignment)
對於所有的對應點,只要它們都位於同一個物理平面上,上述 Homography 就是成立的。換句話說,就是可以把圖一中書皮上的所有點都對映到圖二的書皮上,也就是看起來,圖一中的書皮和圖二中的書皮對齊了!如下圖:
那麼對於不在此平面上的點呢?這時再應用 Homography 就無法再對齊到對應點了。比如 上圖中的 桌面,地面,櫥櫃面。對於這種影象中有多個平面的情況,我們就需要針對每一個平面使用其對應的Homography了。
全景拼接:Homography 的一個重要應用
在前面的例子中,我們知道,如果已知 兩個影象的 Homography,那麼我們可以把一張影象 warp 到 另外一張影象內去。但是,這裡有一個很嚴重的bug:兩張影象必須包含同一個平面,並且僅有這個平面上的點是準確對齊的。事實上,可以證明,如果你用相機拍攝一張任意風景的照片(不僅僅是一個平面)然後旋轉相機再任意拍攝一張,這兩張照片可以用一個 Homography 聯絡起來!
如何計算 Homography?
對於 H 矩陣,一般設 H22 為 1, 所以 H 有 8 個未知引數。至少需要8 個等式才能求解。而一組對應點可以提供 2 個等式,所以,至少需要 4 組對應點(任意三點不共線)來求得 H。 如果有更多組對應點,效果更佳。 OpenCV 可以魯棒地計算出一個最好地擬合所有對應點的 Homography。通常,影象間的這些對應點通過 SIFT 或者 SURF 這樣演算法進行自動特徵提取和匹配。當然,對於簡單的demo,手動選取對應點就足夠了。
OpenCV C++
//pts_src : 源影象點座標
//pts_dst : 結果影象座標
// 資料型別都是 vector<Point2f>.
// 需要至少4組對應點.
Mat h = findHomography(pts_src, pts_dst);
//im_src : 源影象
// im_dst : 結果影象
// h: 上一步計算得到的 Homography
// size : im_dst 的 大小(寬度,高度)
// 將 im_src 通過 h warp 到 im_dst 上去
warpPerspective(im_src, im_dst, h, size);
下面是一個例子
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
int main( int argc, char** argv)
{
// Read source image.
Mat im_src = imread("book2.jpg");
// Four corners of the book in source image
vector<Point2f> pts_src;
pts_src.push_back(Point2f(141, 131));
pts_src.push_back(Point2f(480, 159));
pts_src.push_back(Point2f(493, 630));
pts_src.push_back(Point2f(64, 601));
// Read destination image.
Mat im_dst = imread("book1.jpg");
// Four corners of the book in destination image.
vector<Point2f> pts_dst;
pts_dst.push_back(Point2f(318, 256));
pts_dst.push_back(Point2f(534, 372));
pts_dst.push_back(Point2f(316, 670));
pts_dst.push_back(Point2f(73, 473));
// Calculate Homography
Mat h = findHomography(pts_src, pts_dst);
// Output image
Mat im_out;
// Warp source image to destination based on homography
warpPerspective(im_src, im_out, h, im_dst.size());
// Display images
imshow("Source Image", im_src);
imshow("Destination Image", im_dst);
imshow("Warped Source Image", im_out);
waitKey(0);
}
Homography 應用
虛擬廣告牌
在很多直播體育賽事中,廣告是動態插入到直播視訊流中去的,從而根據觀眾的個人喜好,地域習俗等展示個性化的廣告。
以下是第一張上傳到網際網路的圖片
下圖是 時代廣場的 圖片
好了,我們想把 第一張圖嵌入到 時代廣場的 廣告屏上去,4 步搞定
- 選擇時代廣場上廣告屏的 4 個頂點,作為 pts_dst
- 選取欲嵌入的影象的 4 個頂點,假設影象尺寸 W x H, 那麼 四個頂點就是 (0,0), (0, W-1), (H - 1, 0), (H - 1, W - 1)
- 使用 pts_dst 和 pts_src 計算 Homography
- 對 源影象應用計算得到的 Homography 從而 混合到 目標影象上。得到下圖