opencv中文文档

opencv中文文档


图像基本操作

<h1>目标</h1> <p>学习:</p> <ul> <li>访问像素值并修改它们</li> <li>访问图像属性</li> <li>设置感兴趣区域(ROI)</li> <li>分割和合并图像</li> </ul> <p>本节中几乎所有的操作都主要与Numpy有关,而不是OpenCV。要使用OpenCV编写更好的优化代码,需要良好的Numpy知识。</p> <p><em>(示例将在Python终端中显示,因为大多数示例都是单行代码)</em></p> <h2>访问和修改像素值</h2> <p>让我们先加载一个彩色图像:</p> <pre><code class="language-python">&gt;&gt;&gt; import numpy as np &gt;&gt;&gt; import cv2 as cv &gt;&gt;&gt; img = cv.imread('messi5.jpg')</code></pre> <p>您可以通过它的行和列坐标访问像素值。对于BGR图像,它返回一个由蓝色、绿色和红色值组成的数组。对于灰度图像,只返回相应的强度。</p> <pre><code class="language-python">&gt;&gt;&gt; px = img[100,100] &gt;&gt;&gt; print( px ) [157 166 200] # accessing only blue pixel &gt;&gt;&gt; blue = img[100,100,0] &gt;&gt;&gt; print( blue ) 157</code></pre> <p>您可以用同样的方法修改像素值。</p> <pre><code class="language-python">&gt;&gt;&gt; img[100,100] = [255,255,255] &gt;&gt;&gt; print( img[100,100] ) [255 255 255]</code></pre> <h4>警告</h4> <pre><code>Numpy是一个用于快速数组计算的优化库。因此,简单地访问每个像素值并修改它将是非常缓慢的,这是不鼓励的。</code></pre> <h4>注意</h4> <pre><code>上面的方法通常用于选择数组的一个区域,比如前5行和后3列。对于单个像素访问,Numpy数组方法array.item()和array.itemset()被认为更好,但是它们总是返回标量。如果想访问所有的B、G、R值,需要分别调用</code></pre> <p>更好的像素访问和编辑方法:</p> <pre><code class="language-python"># accessing RED value &gt;&gt;&gt; img.item(10,10,2) 59 # modifying RED value &gt;&gt;&gt; img.itemset((10,10,2),100) &gt;&gt;&gt; img.item(10,10,2) 100</code></pre> <h2>访问图像属性</h2> <p>图像属性包括行数、列数和通道数、图像数据类型、像素数等。</p> <p>图像的形状由img.shape访问。它返回一个由行、列和通道组成的元组(如果图像是彩色的):</p> <pre><code class="language-python">&gt;&gt;&gt; print( img.shape ) (342, 548, 3)</code></pre> <h4>注意</h4> <pre><code>如果图像是灰度的,则返回的元组只包含行数和列数,因此检查加载的图像是灰度还是彩色是一种很好的方法。</code></pre> <p>通过img.size访问总像素数:</p> <pre><code class="language-python">&gt;&gt;&gt; print(img.size) 562248</code></pre> <p>图像数据类型由'img.dtype'获得:</p> <pre><code class="language-python">&gt;&gt;&gt; print(img.dtype) uint8</code></pre> <h4>注意</h4> <pre><code>img.dtype在调试时非常重要,因为OpenCV-Python代码中的大量错误是由无效的数据类型引起的。</code></pre> <h2>图像ROI</h2> <p>有时候,你需要处理特定区域的图像。对于图像中的眼睛检测,首先对图像进行人脸检测。当获得人脸时,我们只选择人脸区域,并在其中搜索眼睛,而不是搜索整个图像。它提高了准确性(因为眼睛总是盯着人脸:D)和性能(因为我们搜索的区域很小)。</p> <p>再次使用Numpy索引获得ROI。这里我选择球,并复制到图像中的另一个区域:</p> <pre><code class="language-python">&gt;&gt;&gt; ball = img[280:340, 330:390] &gt;&gt;&gt; img[273:333, 100:160] = ball</code></pre> <p>检查以下结果:</p> <p><img src="https://www.showdoc.cc/server/api/common/visitfile/sign/2c61a037e78d2185088762938451ea86?showdoc=.jpg" alt="" /></p> <h2>分割和合并图像通道</h2> <p>有时你需要单独处理图像的B、G、R通道。在本例中,需要将BGR图像分割为单个通道。在其他情况下,您可能需要将这些单独的通道连接到BGR映像。你可以简单地做:</p> <pre><code class="language-python">&gt;&gt;&gt; b,g,r = cv.split(img) &gt;&gt;&gt; img = cv.merge((b,g,r))</code></pre> <p>或者</p> <pre><code class="language-python">&gt;&gt;&gt; b = img[:,:,0]</code></pre> <p>假设您想将所有的红色像素设置为零,您不需要首先分割通道。Numpy索引更快:</p> <pre><code class="language-python">&gt;&gt;&gt; img[:,:,2] = 0</code></pre> <h4>警告</h4> <pre><code>cv.split()是一个耗费时间的操作(就时间而言)。所以只有在你需要的时候才去做。否则使用Numpy索引。</code></pre> <h2>为图像创建边框(填充)</h2> <p>如果想在图像周围创建边框,比如相框,可以使用cv.copyMakeBorder()。但它在卷积运算、补零等方面有更多的应用。这个函数接受以下参数:</p> <ul> <li>src - 输入的图像</li> <li>top, bottom, left, right - 边框宽度,以对应方向的像素数为单位</li> <li>borderType - 标志,定义要添加的边框类型。它可以是以下类型: -- cv.BORDER_CONSTANT - 添加一个固定的彩色边框。该值应该作为下一个参数给出. -- cv.BORDER_REFLECT - 边框将是边框元素的镜像反射,就像这样 : fedcba|abcdefgh|hgfedcb -- cv.BORDER_REFLECT_101 or cv.BORDER_DEFAULT - 和上面一样,但是有一点变化,像这样 : gfedcb|abcdefgh|gfedcba -- cv.BORDER_REPLICATE - 最后一个元素被复制,就像这样: aaaaaa|abcdefgh|hhhhhhh -- cv.BORDER_WRAP - 无法解释, 就像这样 : cdefgh|abcdefgh|abcdefg</li> <li>value - 当边框的类别为cv.BORDER_CONSTANT时,指定边框的颜色</li> </ul> <p>下面是一个示例代码,演示了所有这些边界类型,以便更好地理解:</p> <pre><code class="language-python">import cv2 as cv import numpy as np from matplotlib import pyplot as plt BLUE = [255,0,0] img1 = cv.imread('opencv-logo.png') replicate = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REPLICATE) reflect = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT) reflect101 = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT_101) wrap = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_WRAP) constant= cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_CONSTANT,value=BLUE) plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL') plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE') plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT') plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101') plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP') plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT') plt.show()</code></pre> <p>参见下面的结果。(图像用matplotlib显示。因此,红蓝通道将互换):</p> <p><img src="https://www.showdoc.cc/server/api/common/visitfile/sign/eb491d3d44dd4fdea29e1866d449a897?showdoc=.jpg" alt="" /></p>

页面列表

ITEM_HTML