【问题标题】:Finding the boundary points of a contour in opencv numpy在opencv numpy中找到轮廓的边界点
【发布时间】:2018-09-29 15:37:47
【问题描述】:

complete noob at open cv 和 numpy here。这是图片:这是我的代码:

import numpy as np
import cv2

im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
imgray = cv2.medianBlur(imgray, ksize=7)

ret, thresh = cv2.threshold(imgray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

print ("number of countours detected before filtering %d -> "%len(contours))
new = np.zeros(imgray.shape)

new = cv2.drawContours(im,contours,len(contours)-1,(0,0,255),18)

cv2.namedWindow('Display',cv2.WINDOW_NORMAL)
cv2.imshow('Display',new)
cv2.waitKey()

mask = np.zeros(imgray.shape,np.uint8)
cv2.drawContours(mask,[contours[len(contours)-1]],0,255,-1)
pixelpoints = cv2.findNonZero(mask)
cv2.imwrite("masked_image.jpg",mask)

print(len(pixelpoints))
print("type of pixelpoints is %s" %type(pixelpoints))

像素点的长度接近 200 万,因为它包含了轮廓覆盖的所有点。但我只需要该轮廓的边界点。我该怎么做?我尝试了 opencv 文档中的几种方法,但总是出现元组和排序操作错误。请...帮忙?

我只需要轮廓的边界点:(

【问题讨论】:

  • this 文档中,它清楚地说明了使用哪个参数来去除冗余点并获取端点。我不敢相信你的说法,“我已经尝试了 opencv 文档中的几种方法”
  • 您能否上传您用于查找轮廓的二进制图像以及预期输出?
  • @RickM.,我可能以某种方式把你弄错了。我道歉。我了解您正在谈论将 cv2.CHAIN_APPROX_NONE 更改为 cv2.CHAIN_APPROX_SIMPLE 但在没有直线的图片中应用此功能不起作用。我仍然得到200万分。如果你看文档,它强调减少线点,而不是弧线。我试过了。
  • @ZdaR 图片添加
  • @MonirulIslam this one 怎么样?如果您还上传预期的输出,那将会很有帮助。从您上传的图片中,几乎不可能说出您要提取的轮廓。

标签: python numpy opencv contour opencv-contour


【解决方案1】:

这就是轮廓的边界点吗?

你看到的白线是我在蓝色轮廓上用白色标出的点。右下角有一个小点,因为我认为你的黑色背景很可能不是真正的黑色,所以当我进行阈值处理和填充来得到这个时,

在同一个地方有一个小白点。但是,如果您使用参数并进行更适当的阈值处理和填充,则应该不是问题。 在 openCV 的 drawContours 函数中,cnts 将包含轮廓列表,每个轮廓将包含一个点数组。每个点也是 numpy.ndarray 类型。如果要将每个轮廓的所有点放在一个位置,以便返回一组边界点(如上图中的白点轮廓),您可能希望将它们全部附加到列表中。你可以试试这个:

#rgb is brg instead
contoured=cv2.drawContours(black, cnts, -1, (255,0,0), 3)

#list of ALL points of ALL contours
all_pixels=[]

for i in range(0, len(cnts)):
    for j in range(0,len(cnts[i])):
        all_pixels.append(cnts[i][j])

当我尝试时

print(len(all_pixels))

它给了我 2139 分。

如果您想为可视化目的标记点(例如我的白点),请执行此操作:

#contouredC is a copy of the contoured image above
contouredC[x_val, y_val]=[255,255,255]

如果您想要更少的点,只需在迭代时使用阶梯函数来绘制白点。像这样:

在 python 中,for 循环很慢,所以我认为有更好的方法可以用 np.where() 函数或其他方法替换嵌套的 for 循环。如果/当我弄清楚时会更新这个。此外,这需要更好的阈值处理和二值化技术。泛洪技术引用自:Python 2.7: Area opening and closing binary image in Python not so accurate

希望对你有帮助。

【讨论】:

  • 代码不起作用,因为您使用了未定义的变量。请以人们可以实际重现结果而不是出现类似NameError: name 'x_val' is not defined 的错误的方式重写您的代码。
  • 您好,感谢您的评论。我想我没有包含整个脚本,因为我还在上面编写了一些其他的东西(因此太长了),当我提到其他 stackoverflow 答案时,似乎它们中的大多数都没有显示整个代码。但是很好的建议,下次我会尝试包含更多代码。如果有帮助,我可以向您解释 x_val 是什么?所以 x_val 是我自己定义的,而 contouredC 是形成轮廓的点集。通过将这些点中的每一个设置为白色([255 255 255]),我们可以可视化并看到它们。在我最下面的图片中,我使用了一个 for 循环(带步骤)
  • 产生间隔的白点。如果我能再次找到这个脚本,我会更新这个答案:)
  • @Ran_Reine_ 你是怎么找到x_val的?我需要边界中每个像素的颜色。
  • @RishabhGupta 您实际上设置了边界中每个像素的颜色。在上面的示例中,我将点设置为白色 ([255,255,255])。 cv2.drawContours(black, cnts, -1, (255,0,0), 3) 用于在图像中的所有轮廓周围绘制轮廓(并因此获取点)(因为我将第三个参数设置为 -1 )。
猜你喜欢
  • 1970-01-01
  • 2022-08-05
  • 2016-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-04
相关资源
最近更新 更多