使用OpenCV和Python(正確)旋轉(zhuǎn)圖像(P2)
實(shí)現(xiàn)旋轉(zhuǎn)功能,不會(huì)切斷圖像
首先,我要說的是,用于在OpenCV中旋轉(zhuǎn)圖像的?CV2.getRotationMatrix2D 和CV2.warpAffine?函數(shù)沒有任何問題。
實(shí)際上,這些函數(shù)給了我們更多的自由度,這可能是我們無法接受的(有點(diǎn)像是比較手動(dòng)內(nèi)存管理和C語言,以及自動(dòng)垃圾收集和Java語言)。
CV2.getRotationMatrix2D函數(shù)不關(guān)心是否要保留整個(gè)旋轉(zhuǎn)圖像。
它不在乎圖像是否被切斷。
如果你在使用這個(gè)功能時(shí)射中了自己的腳,這對(duì)你沒有任何幫助(我是通過艱難的方式發(fā)現(xiàn)這一點(diǎn)的,用了3周時(shí)間才止血)。
相反,你需要做的是理解旋轉(zhuǎn)矩陣是什么,以及它是如何構(gòu)造的。
你看,當(dāng)你用OpenCV旋轉(zhuǎn)圖像時(shí),你稱之為CV2.getRotationMatrix2D返回一個(gè)矩陣M,如下所示:

這個(gè)矩陣看起來很嚇人,但我向你保證:不是。
為了理解它,讓我們假設(shè)我們想要以一定的比例(即更小或更大)圍繞某個(gè)中心(c_{x},c_{y})坐標(biāo)旋轉(zhuǎn)圖像0度。
然后我們可以插入\alpha和\beta的值:
\α=標(biāo)度*cos\theta和β=標(biāo)度*sin\theta
對(duì)于簡(jiǎn)單的旋轉(zhuǎn)來說,這一切都很好,但它沒有考慮到如果圖像沿著邊界被切掉會(huì)發(fā)生什么。我們?nèi)绾窝a(bǔ)救?
答案就在rotate_-bound函數(shù)中。imutils的py:
(這里的第幾行就看上面的代碼是第幾行)
在第1行,我們定義了rotate_界函數(shù)。
此方法接受輸入圖像和旋轉(zhuǎn)角度。
我們假設(shè)我們將圍繞圖像的中心(x,y)坐標(biāo)旋轉(zhuǎn)圖像,所以我們?cè)诘?行和第5行確定這些值。
根據(jù)這些坐標(biāo),我們可以稱之為CV2。獲取旋轉(zhuǎn)矩陣x2d以獲得旋轉(zhuǎn)矩陣M(第8行)。
然而,為了調(diào)整任何圖像邊界截?cái)鄦栴},我們需要應(yīng)用一些我們自己的手動(dòng)計(jì)算。
我們首先從旋轉(zhuǎn)矩陣M(第9行和第10行)中獲取余弦和正弦值。
這使我們能夠計(jì)算旋轉(zhuǎn)圖像的新寬度和高度,確保圖像的任何部分都不會(huì)被切斷。
一旦我們知道了新的寬度和高度,我們就可以通過再次修改旋轉(zhuǎn)矩陣來調(diào)整第17行和第18行的平移。
最后是CV2。在第21行調(diào)用warpAffine,使用OpenCV旋轉(zhuǎn)實(shí)際圖像,同時(shí)確保沒有任何圖像被切斷。
對(duì)于使用OpenCV時(shí)旋轉(zhuǎn)切斷問題的其他一些有趣的解決方案(一些比其他更好),請(qǐng)務(wù)必參考此StackOverflow線程和此線程。