opencv中文文档

opencv中文文档


边缘检测

<h1>目标</h1> <p>在本章中,我们将学习</p> <ul> <li>边缘检测的概念</li> <li>OpenCV函数:cv.Canny()</li> </ul> <h2>原理</h2> <p>Canny边缘检测是一种常用的边缘检测算法。它是由John F. Canny发明的</p> <ol> <li> <p>这是一个多阶段的算法,我们将经历每个阶段。</p> </li> <li> <p><strong>降噪</strong> 由于边缘检测容易受到图像中噪声的影响,第一步是用5x5高斯滤波器去除图像中的噪声。我们在前几章已经介绍过了。</p> </li> <li> <p><strong>寻找图像的强度梯度</strong> 然后对平滑后的图像进行水平方向和垂直方向的Sobel内核滤波,得到水平方向(Gx)和垂直方向(Gy)的一阶导数。从这两幅图像中,我们可以发现每个像素的边缘梯度和方向如下: <img src="https://www.showdoc.cc/server/api/common/visitfile/sign/178bd9c32791f5b5cee379b3b237adff?showdoc=.jpg" alt="" /> 梯度方向总是垂直于边缘。它是四角之一,代表垂直、水平和两个对角线方向。</p> </li> <li> <p><strong>非极大值抑制</strong> 在得到梯度大小和方向后,对图像进行全局扫描,去除可能不构成边缘的任何不需要的像素。为此,在每个像素处,检查像素在梯度方向上是否为其邻域内的局部最大值。如下图: <img src="https://www.showdoc.cc/server/api/common/visitfile/sign/bf022975c04ce916505aeffcab79d391?showdoc=.jpg" alt="" /> 点A在边缘上(垂直方向)。梯度方向垂直于边缘。点B和点C在梯度方向上。因此,点A与点B和点C进行检查,看它是否形成局部最大值。如果是,则将其考虑到下一阶段,否则将抑制它(使其为零)。 简而言之,您得到的结果是一个具有“细边”的二进制图像。</p> </li> <li><strong>滞后阈值法</strong> 这个阶段决定哪些是边哪些不是。为此,我们需要两个阈值,minVal和maxVal。任何强度梯度大于maxVal的边都肯定是边,小于minVal的边肯定是非边,所以丢弃。位于这两个阈值之间的根据它们的连接性对边缘或非边缘进行分类。如果它们连接到“确定边缘”像素,则被认为是边缘的一部分。否则,它们也会被丢弃。见下图: <img src="https://www.showdoc.cc/server/api/common/visitfile/sign/2934274337badaa1a0cd5cf3612fe1c4?showdoc=.jpg" alt="" /> 边缘A在maxVal之上,称为“确定边缘”。虽然C边低于maxVal,但它与A边相连,所以这条边也被认为是有效的边,我们得到了完整的曲线。但是B边虽然在minVal以上,与C边在同一区域,但是没有连接到任何“sure-edge”,所以被丢弃。因此,为了得到正确的结果,我们必须相应地选择minVal和maxVal,这是非常重要的。 这个阶段也消除了小像素噪声的假设下,边缘是长线。</li> </ol> <p>最终得到的是图像中的强边。</p> <h2>OpenCV中的Canny边缘检测</h2> <p>OpenCV将所有这些都放在一个函数中,即cv.Canny()。我们将学会如何使用它。第一个参数是输入图像。第二个和第三个参数分别是minVal和maxVal。第三个参数是aperture_size。它是用来寻找图像梯度的Sobel内核的大小。默认情况下是3。最后一个参数是L2gradient,它指定了求梯度大小的方程。如果为真,则使用上述更精确的方程,否则使用这个函数:Edge_Gradient(G)=|Gx|+|Gy|。默认情况下,它是假的。</p> <pre><code class="language-python">import numpy as np import cv2 as cv from matplotlib import pyplot as plt img = cv.imread('messi5.jpg',0) edges = cv.Canny(img,100,200) plt.subplot(121),plt.imshow(img,cmap = 'gray') plt.title('Original Image'), plt.xticks([]), plt.yticks([]) plt.subplot(122),plt.imshow(edges,cmap = 'gray') plt.title('Edge Image'), plt.xticks([]), plt.yticks([]) plt.show()</code></pre> <p>结果如下:</p> <p><img src="https://www.showdoc.cc/server/api/common/visitfile/sign/d24e9c777ca98055ac6eb635c50b51f5?showdoc=.jpg" alt="" /></p> <h2>其它资源</h2> <ol> <li>维基百科的边缘探测器</li> <li>Canny边缘检测教程比尔格林,2002年。</li> </ol> <h2>练习题</h2> <p>编写一个小的应用程序来寻找Canny边缘检测,其阈值可以使用两个轨迹条变化。这样,您就可以理解阈值的影响。</p>

页面列表

ITEM_HTML