<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>算法