繁体   English   中英

如何使用OpenCV Python显示图像的轮廓?

[英]How do I display the contours of an image using OpenCV Python?

我遵循了官方文档中的本教程。 我运行他们的代码:

import numpy as np
import cv2

im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0,255,0), 3)

没关系:没有错误,但是什么也没显示我想显示他们在图片上显示的结果:

在此处输入图片说明

如何显示这样的国家/地区的结果(只是左边的结果还是右边的结果)? 我知道我必须使用cv2.imshow(something)但是在这种特定情况下如何使用?

首先,该示例仅向您展示如何使用简单的近似值绘制轮廓。 请记住,即使您使用简单的近似值绘制轮廓,也可以将其可视化为完全围绕矩形绘制的蓝色轮廓,如左图所示。 简单地将轮廓绘制到图像上将无法获得正确的图像。 另外,您想比较两组轮廓-右侧的简化版本与左侧的完整表示。 具体来说,您需要将cv2.CHAIN_APPROX_SIMPLE标志替换为cv2.CHAIN_APPROX_NONE以获取完整的表示形式。 请参阅findContours上的OpenCV文档以了解更多详细信息: http : //docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#findcontours

另外,即使您在图像上绘制轮廓,它也不会显示结果。 您需要为此调用cv2.imshow 但是,绘制轮廓本身不会显示完整版本和简化版本之间的区别。 本教程提到您需要在每个轮廓点绘制圆 ,因此我们不应为此任务使用cv2.drawContours 您应该做的是提取轮廓点并在每个点处绘制圆。

这样,创建两个图像,如下所示:

# Your code
import numpy as np
import cv2

im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)

## Step #1 - Detect contours using both methods on the same image
contours1, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
contours2, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

### Step #2 - Reshape to 2D matrices
contours1 = contours1[0].reshape(-1,2)
contours2 = contours2[0].reshape(-1,2)

### Step #3 - Draw the points as individual circles in the image
img1 = im.copy()
img2 = im.copy()

for (x, y) in contours1:
    cv2.circle(img1, (x, y), 1, (255, 0, 0), 3)

for (x, y) in contours2:
    cv2.circle(img2, (x, y), 1, (255, 0, 0), 3)

请注意,上面的代码是针对OpenCV 2的。对于OpenCV 3, cv2.findContours还有一个附加输出,在这种情况下,这是您可以忽略的第一个输出:

_, contours1, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
_, contours2, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

现在,让我们慢慢地遍历代码。 代码的第一部分是您提供的。 现在我们进入新内容。

步骤#1-使用两种方法检测轮廓

使用阈值图像,我们使用完整近似值和简单近似值检测轮廓。 这存储在两个列表中, contours1contours2

步骤#2-重塑为2D矩阵

轮廓本身将存储为NumPy数组的列表。 对于所提供的简单图像,应该仅检测到一个轮廓,因此提取出列表的第一个元素,然后使用numpy.reshape将3D矩阵重塑为2D形式,其中每一行都是(x, y)点。

步骤#3-将点绘制为图像中的单个圆圈

下一步将是从每组轮廓中提取每个(x, y)点并将其绘制在图像上。 我们以彩色形式制作原始图像的两个副本,然后使用cv2.circle并遍历两组轮廓的每对(x, y)点,并填充两个不同的图像-一组轮廓。


现在,要获得上面看到的图形,可以通过两种方法执行此操作:

  1. 创建一个图像,将两个结果并排存储在一起,然后显示此组合图像。
  2. 使用matplotlib ,结合subplotimshow ,让您可以在一个窗口中显示两个图像。

我将向您展示如何使用这两种方法:

方法1

只需将两个图像并排堆叠,然后显示以下图像:

out = np.hstack([img1, img2])

# Now show the image
cv2.imshow('Output', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

我将它们水平堆叠,以使其成为组合图像,然后使用cv2.imshow进行显示。

方法#2

您可以使用matplotlib

import matplotlib.pyplot as plt

# Spawn a new figure
plt.figure()
# Show the first image on the left column
plt.subplot(1,2,1)
plt.imshow(img1[:,:,::-1])
# Turn off axis numbering
plt.axis('off')

# Show the second image on the right column
plt.subplot(1,2,2)
plt.imshow(img2[:,:,::-1])
# Turn off the axis numbering
plt.axis('off')

# Show the figure
plt.show()

这将在整体图形窗口中的单独子图中显示两个图像。 如果您看看我在这里如何调用imshow ,您会发现我正在交换RGB通道,因为OpenCV读取BGR格式的图像。 如果要使用matplotlib显示图像,则需要反转通道,因为图像为RGB格式(应如此)。


为了在注释中解决您的问题,您将采用所需的轮廓结构( contours1contours2 )并搜索轮廓点。 contours是所有可能轮廓的列表,每个轮廓内是一个以N x 1 x 2格式成形的3D矩阵。 N将是代表轮廓的点总数。 我将删除单例第二维,以便使它成为N x 2矩阵。 另外,让我们现在使用轮廓的完整表示:

points = contours1[0].reshape(-1,2)

我将假设您的图像只有一个对象,因此我用索引0索引到contours1 1中。我解开矩阵,使其成为单个行向量,然后对矩阵进行整形,使其变为N x 2 接下来,我们可以通过以下方法找到最小点:

min_x = np.argmin(points[:,0])
min_point = points[min_x,:]

np.argmin查找您提供的数组中最小值的位置 在这种情况下,我们要沿x坐标或列进行操作。 找到此位置后,我们只需索引到2D轮廓点数组中并提取轮廓点即可。

在末尾添加以下两行:

cv2.imshow("title", im)
cv2.waitKey()

另外,请注意,最后一行中包含img而不是im

您应该在代码末尾添加cv2.imshow(“ Title”,img)。 它看起来应该像这样:

import numpy as np
import cv2

im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(im, contours, -1, (0,255,0), 3)
cv2.imshow("title", im)
cv2.waitKey()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM