<div class="htmledit_views" id="content_views">html
<p>理論</p> <p><a href="http://www.cnblogs.com/wangguchangqing/p/4045150.html" rel="nofollow" target="_blank">http://www.cnblogs.com/wangguchangqing/p/4045150.html</a><br></p> <p>翻開任意一本圖像處理的書,都會講到圖像的幾何變換,這裏麪包括:仿射變換(affine transformation)、投影變換(projecttive transformation)。前者針對的是平面上的物體位姿變化,如水平/垂直方向位移、旋轉、縮小/放大,常見的應用有ORC字符識別。後者針對的是三維空間中的位置變化,受限於物體依然是平面的,也稱爲二維投影變換,常見的應用有車牌識別。</p> <p>圖像變換:以上全部變換都可以經過矩陣描述,將輸入圖像與變換矩陣進行矩陣乘法獲得變換後的圖像座標。顯然,這種方式很是適合編程實現。</p> <p><br></p> <p>opencv仿射變換函數說明</p> <p>opencv提供了,從變換矩陣計算,到圖像變換,每一個流程的一攬子解決方案。</p> <p>以opencv 3.0爲例,<a href="http://docs.opencv.org/3.0-beta/modules/imgproc/doc/geometric_transformations.html" rel="nofollow" target="_blank">參考幾何變換模塊說明</a>:</p> <p>一、getAffineTransform</p> <p></p> <pre><code class="language-cpp hljs"><span class="hljs-function">Mat <span class="hljs-title">getAffineTransform</span><span class="hljs-params">(InputArray src, InputArray dst)</span></span></code><div class="hljs-button signin" data-title="登陸後複製" onclick="hljs.signin(event)"></div></pre>該函數須要已知變換前與變換後的座標,返回相應的變換矩陣,至因而何種變換無需事先知道。適用於目標檢測場合,經過檢測獲得的特徵點進行圖像匹配。 <p></p> <p><br> 二、getRotationMatrix2D</p> <p></p> <pre><code class="language-cpp hljs"><span class="hljs-function">Mat <span class="hljs-title">getRotationMatrix2D</span><span class="hljs-params">(Point2f center, <span class="hljs-keyword">double</span> angle, <span class="hljs-keyword">double</span> scale)</span></span></code><div class="hljs-button signin" data-title="登陸後複製" onclick="hljs.signin(event)"></div></pre>已知旋轉中心座標(座標原點爲圖像左上端點)、旋轉角度(單位爲度°,順時針爲負,逆時針爲正)、放縮比例,返回旋轉/放縮矩陣。與getAffineTransform相比,無需知道變換後坐標,適用於通常狀況下的圖像變換。<br><br><p></p> <p>三、warpAffine</p> <p></p> <pre><code class="language-cpp hljs"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">warpAffine</span><span class="hljs-params">(InputArray src, OutputArray dst, InputArray M, Size dsize, <span class="hljs-keyword">int</span> flags=INTER_LINEAR, <span class="hljs-keyword">int</span> borderMode=BORDER_CONSTANT, <span class="hljs-keyword">const</span> Scalar& borderValue=Scalar()</span>)</span></code><div class="hljs-button signin" data-title="登陸後複製" onclick="hljs.signin(event)"></div></pre>根據etAffineTransform或getRotationMatrix2D獲得的變換矩陣,計算變換後的圖像。<br> src爲輸入圖像 <p></p> <p>dst爲變換後圖像,類型與src一致。</p> <p>M爲變換矩陣,須要經過其它函數得到,固然也能夠手動輸入。</p> <p>dsize爲輸出圖像的大小<br></p> <p>flags,插值算法,詳細以下:</p> <p></p> <pre><code class="language-cpp hljs"><ol class="hljs-ln" style="width:1659px"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">enum</span> InterpolationFlags{</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">/** nearest neighbor interpolation */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> INTER_NEAREST = <span class="hljs-number">0</span>, <span class="hljs-comment">//最近鄰插值</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">/** bilinear interpolation */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> INTER_LINEAR = <span class="hljs-number">1</span>, <span class="hljs-comment">//雙線性插值</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">/** bicubic interpolation */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> INTER_CUBIC = <span class="hljs-number">2</span>, <span class="hljs-comment">//雙三次插值</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment"><span class="hljs-comment">/** resampling using pixel area relation. It may be a preferred method for image decimation, as</span></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment"> it gives moire'-free results. But when the image is zoomed, it is similar to the INTER_NEAREST</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment"> method. */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> INTER_AREA = <span class="hljs-number">3</span>, <span class="hljs-comment">//區域插值,使用象素關係重採樣。當圖像縮小時候,該方法能夠避免波紋出現。當圖像放大時,相似於 <span style="font-family: Arial, Helvetica, sans-serif;">INTER_NEAREST</span>方法</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">/** Lanczos interpolation over 8x8 neighborhood */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="13"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> INTER_LANCZOS4 = <span class="hljs-number">4</span>, <span class="hljs-comment">//Lanczos插值(超過8×8像素鄰域的Lanczos插值)</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="14"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment">/** mask for interpolation codes */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="15"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> INTER_MAX = <span class="hljs-number">7</span>,</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="16"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment"><span class="hljs-comment">/** flag, fills all of the destination image pixels. If some of them correspond to outliers in the</span></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="17"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment"> source image, they are set to zero */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="18"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> WARP_FILL_OUTLIERS = <span class="hljs-number">8</span>, <span class="hljs-comment">//填充全部輸出圖像的象素</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="19"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-comment"><span class="hljs-comment">/** flag, inverse transformation</span></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="20"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment"></span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="21"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment"> For example, polar transforms:</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="22"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment"> - flag is __not__ set: \f$dst( \phi , \rho ) = src(x,y)\f$</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="23"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment"> - flag is set: \f$dst(x,y) = src( \phi , \rho )\f$</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="24"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-comment"> */</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="25"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> WARP_INVERSE_MAP = <span class="hljs-number">16</span> <span class="hljs-comment">//逆變換</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="26"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">};</div></div></li></ol></code><div class="hljs-button signin" data-title="登陸後複製" onclick="hljs.signin(event)"></div></pre>borderMode,邊界處理方式 <p></p> <p></p> <pre><code class="language-cpp hljs"><ol class="hljs-ln" style="width:773px"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"><span class="hljs-keyword">enum</span> BorderTypes {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> BORDER_CONSTANT = <span class="hljs-number">0</span>, <span class="hljs-comment">//!< `iiiiii|abcdefgh|iiiiiii` with some specified `i`</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> BORDER_REPLICATE = <span class="hljs-number">1</span>, <span class="hljs-comment">//!< `aaaaaa|abcdefgh|hhhhhhh`</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> BORDER_REFLECT = <span class="hljs-number">2</span>, <span class="hljs-comment">//!< `fedcba|abcdefgh|hgfedcb`</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> BORDER_WRAP = <span class="hljs-number">3</span>, <span class="hljs-comment">//!< `cdefgh|abcdefgh|abcdefg`</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> BORDER_REFLECT_101 = <span class="hljs-number">4</span>, <span class="hljs-comment">//!< `gfedcb|abcdefgh|gfedcba`</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> BORDER_TRANSPARENT = <span class="hljs-number">5</span>, <span class="hljs-comment">//!< `uvwxyz|absdefgh|ijklmno`</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="8"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> </div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="9"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> BORDER_REFLECT101 = BORDER_REFLECT_101, <span class="hljs-comment">//!< same as BORDER_REFLECT_101</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="10"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> BORDER_DEFAULT = BORDER_REFLECT_101, <span class="hljs-comment">//!< same as BORDER_REFLECT_101</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="11"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> BORDER_ISOLATED = <span class="hljs-number">16</span> <span class="hljs-comment">//!< do not look outside of ROI</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="12"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">};</div></div></li></ol></code><div class="hljs-button signin" data-title="登陸後複製" onclick="hljs.signin(event)"></div></pre><br><br><br><p></p> <p>opencv實現圖像旋轉(其它仿射變換的流程與此一致)</p> <p></p> <pre><code class="language-cpp hljs"><ol class="hljs-ln"><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="1"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> Mat src;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="2"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-function">Mat <span class="hljs-title">dst</span><span class="hljs-params">(src.size()</span>,src.<span class="hljs-title">type</span><span class="hljs-params">()</span>)</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="3"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line">...</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> cv::<span class="hljs-function">Point2f <span class="hljs-title">center</span><span class="hljs-params">(x0,y0)</span></span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword">double</span> ang = <span class="hljs-number">-30</span>;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="6"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> cv::Mat rotMat = cv::getRotationMatrix2D(center,ang,<span class="hljs-number">1</span>);</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="7"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> cv::warpAffine(src,dst,rotMat,src.size());</div></div></li></ol></code><div class="hljs-button signin" data-title="登陸後複製" onclick="hljs.signin(event)"></div></pre>順時針旋轉30度 <p></p> <p><br></p> <p>更多請參考:</p> <p><a href="http://blog.csdn.net/xiaowei_cqu/article/details/7616044" rel="nofollow" target="_blank">http://blog.csdn.net/xiaowei_cqu/article/details/7616044</a><br></p> <p><a href="http://blog.csdn.net/godenlove007/article/details/9364971" rel="nofollow" target="_blank">http://blog.csdn.net/godenlove007/article/details/9364971</a><br></p> </div>算法