当前位置: 首页 > 知识库问答 >
问题:

如何正确使用opencv 4.4.0版上的cv2.findContour()?

严瑞
2023-03-14

我正在尝试使用cv2。opencv 4.4.0版上的FindOnTours()。(我使用的是Python版本3.8.5),但它抛出了一个错误,我想不出来。我不确定代码出了什么问题。以下是一些背景:

>

我找了一些例子来确保如何正确地实现它,以下是我发现的:例子1_,轮廓,_=cv2.find轮廓(binary_image,cv2。RETR_LISTcv2CHAIN_APPROX_SIMPLE)

例2(_, cnts,_)=cv2.find轮廓(thresholded.copy(), cv2。RETR_EXTERNALcv2CHAIN_APPROX_SIMPLE)

这些都是我在网上找到的工作项目,有很多这样的例子。所以,我试图实现一些代码,我从视频中获得一些关于这个主题的理解,但它似乎不适合我,我找不到为什么。下面是代码:

import cv2 
import numpy as np 

imagen =cv2.imread('lettuce.jpg')
gray = cv2.cvtColor(imagen,cv2.COLOR_BGR2GRAY)
_,binary = cv2.threshold(gray,100,255,cv2.THRESH_BINARY)

image,contours,hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

cv2.drawContours(image,contours, -1, (0,255,0),3)

错误:回溯(最近一次调用last):第8行,在图像中,轮廓,层次=cv2。findContours(二进制,cv2.RETR\u列表,cv2.CHAIN\u近似值\u简单)值错误:没有足够的值来解包(预期为3,获得2)

共有2个答案

宗政卓
2023-03-14

问题是cv2。findContour函数将返回两件事,而不是三件事。

  1. 等高线
  2. 等级制度

这是cv2。findContours函数接受三个输入参数。第一个参数是应为灰度图像的图像。第二种是检索模式,第三种是近似模式。当我们应用findContours方法时,原始图像将受到影响。最佳做法是在处理findContours方法之前复制图像。

OpenCV将等高线存储在列表的列表中。每个列表表示不同的轮廓。在列表中,该等高线的所有坐标都将添加到该列表中。我们可以以不同的方式存储这些坐标。我们如何储存这些?近似模式开始发挥作用。

使用cv2。CHAIN_APPROX_NONE存储所有边界点。但是我们不一定需要所有的边界点。如果点形成一条直线,我们只需要该直线的起点和终点。使用cv2。CHAIN_APPROX_SIMPLE只提供这些边界轮廓的起始点和终结点,从而更有效地存储轮廓信息。

什么是检索模式?检索模式本质上定义了轮廓的层次结构,就像您想要子轮廓、外部轮廓还是所有轮廓一样。

在OpenCV的检索模式中有四种类型。

  • cv2。翻新清单→ 检索所有等高线
  • cv2。外部修复→ 仅检索外部或外部轮廓
  • cv2。复印机→ 检索两级层次结构中的所有
  • cv2。再生树→ 检索完整层次结构中的所有

层次结构以以下格式存储[下一个、上一个、第一个子、父]。

苏涛
2023-03-14

在Python/OpenCV 4.4.0中,findContour只返回2个值,列出3个。

你展示:

image,contours,hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

OpenCV 4.4.0,列表:

contours, hierarchy = cv.findContours(image, mode, method[, contours[, hierarchy[, offset]]])

请务必检查留档。看到没

https://docs.opencv.org/4.4.0/d3/dc0/group__imgproc__shape.html#gadf1ad6a0b82947fa1fe3c3d497f260e0

如果您只想得到轮廓,那么以独立于版本的方式处理此问题的一种方法是(归功于@Nathance):

contours = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]

如果不需要所有嵌套轮廓,请使用RETR_EXTERNAL和not RETR_LIST。

 类似资料:
  • 这是java-version的输出: java版本“1.7.0_25”java(TM)SE运行时环境(build 1.7.0_25-B15)java HotSpot(TM)64位服务器VM(build 23.25-B01,混合模式) 这是mvn-version的输出: Java版本:1.6.0_51,供应商:Apple Inc.Java Home:/system/library/Java/java

  • 问题内容: 我只想检索UserAccount类中的某些列,所以我有以下代码: 我得到了空值作为回报。但是,如果我注释掉setProjections,我将获得具有所有属性的用户。在这种情况下,如何正确使用setProjection? 问题答案: 它返回一个Object数组,因此代码应为:

  • 问题内容: 我不知道我在哪里错了:/。当我运行这段代码时,我得到的只是一个空白元素。我似乎无法让insertRule方法执行任何操作(甚至不会产生错误)。我想念什么吗? 问题答案: 这有点令人困惑,但是您的代码确实可以工作,只是您看不到返回的XML树中插入的规则。 为了验证您的代码是否有效,您可以执行两个测试: 运行上面的代码片段,您可以看到CSS规则确实适用。并且属性也在控制台中更改。 当浏览器

  • 问题内容: 如何使用从类路径中查找递归资源? 例如 在“目录”中查找所有资源:想象一下 不幸的是,这只会检索到恰好该“目录”。 所有资源都已命名(递归) 但这返回一个空。 还有一个额外的问题:与有什么不同? 问题答案: 没有办法递归搜索类路径。您需要知道资源的完整路径名才能以这种方式检索它。该资源可能位于文件系统中的目录中,也可能位于jar文件中,因此它不像执行“类路径”的目录列表那样简单。您将需

  • 问题内容: 我最近开始使用ScriptManager。我有一个通过JavaScript填充的ASP.NET DropDownList控件。但是,我正在使用事件验证。因此,如果我不使用下拉菜单中的“ RegisterForEventValidation”调用,则会遇到以下错误。我怎么知道在第二个参数中设置什么值(我有“值”)?我正在通过JavaScript填充下拉列表,因此我不知道后面的代码中包含哪

  • 我正在尝试正确地使用ByteBuffer和BigEndian字节顺序格式。。 我有几个字段,我试图把它存储在Cassandra数据库之前放在一个单一的ByteBuffer中。 我将要写入Cassandra的字节数组由三个字节数组组成,如下所述- 现在,我将写,和一起到一个字节数组和由此产生的字节数组我将写入Cassandra,然后我将有我的C程序来检索它字节数组数据从Cassandra,然后反序列