Bas*_*ian 2 python opencv numpy
我无法使用 OpenCV 的findContours(...)方法在单通道图像中查找轮廓。该图像实际上是一个 numpy 数组,其形状(128, 128)和元素的实际值介于 之间[0.0,1.0]。最初的形状是(1,128,128,1)但我用过np.squeeze(...)去掉第一个和最后一个维度。保留其中任何一个都不能解决我的问题。
我尝试过的:
image = np.squeeze(array) #using np.squeeze(array, [0]) won't help.
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
contours, hierarchy = cv2.findContours(image, 1, 2)
Run Code Online (Sandbox Code Playgroud)
上面的代码会导致以下异常:
error: (-215) scn == 3 || scn == 4 in function cv::cvtColor
Run Code Online (Sandbox Code Playgroud)
我也尝试过:
如果我直接申请findContours(...),那么不使用cvtColor(...),我会得到一个不同的错误:
error: (-210) [Start]FindContours supports only CV_8UC1 images when mode != CV_RETR_FLOODFILL otherwise supports CV_32SC1 images only in function cvStartFindContours_Impl
Run Code Online (Sandbox Code Playgroud)
一些来源建议使用 a来获取[1]threshold所需的二进制图像findContours(...)
ret, thresh = cv2.threshold(image, 1, 255, 0)
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
Run Code Online (Sandbox Code Playgroud)
这也无济于事,我收到同样的异常抱怨支持CV_8UC1。
该图像实际上是一个 numpy 数组,其形状
(128, 128)和元素的实际值介于 之间[0.0,1.0]。
错误cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)是由于您尝试将单通道图像从 BGR(3 通道)转换为灰度(1 通道)。您的图像已经是灰度的,所以这一步是不必要的。
错误cv2.findContours是由于数组中元素的数据类型错误造成的。该文档对输入图像进行了以下说明:
源,8 位单通道图像。非零像素被视为 1。零像素仍为 0,因此图像被视为二进制。您可以使用
compare、inRange、threshold、adaptiveThreshold、Canny等从灰度或彩色图像创建二值图像。如果 mode 等于RETR_CCOMP或RETR_FLOODFILL,则输入也可以是标签 ( ) 的 32 位整数图像CV_32SC1。
要解决此问题,您需要将图像中的值缩放到 range [0.0,255.0],然后将结果转换为np.uint8:
image_8bit = np.uint8(image * 255)
Run Code Online (Sandbox Code Playgroud)
您问题中的代码几乎没有其他问题或怪癖。
首先,在一个片段中cv2.findContours返回 2 个值 (OpenCV 2.x),在另一个片段中返回 3 个值 (OpenCV 3.x)。您使用哪个版本?
您的第一个代码示例包含以下内容:
contours, hierarchy = cv2.findContours(image, 1, 2)
Run Code Online (Sandbox Code Playgroud)
避免使用幻数。对应1于cv2.RETR_LIST, 对应2于cv2.CHAIN_APPROX_SIMPLE。由于该RETR_LIST模式不生成任何层次结构,因此您可以忽略该返回值:
contours, _ = cv2.findContours(binarized, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
Run Code Online (Sandbox Code Playgroud)
另一个问题很可能是最初您没有明确对图像进行二值化(例如使用cv2.threshold)。虽然这不会导致异常,但结果可能没有多大意义 -findContours将像素分为两组 - 零,然后所有非零。您很可能希望对它们进行不同的分区。
threshold_level = 127 # Set as you need...
_, binarized = cv2.threshold(image_8bit, threshold_level, 255, cv2.THRESH_BINARY)
Run Code Online (Sandbox Code Playgroud)
示例脚本(OpenCV 3.x):
import numpy as np
import cv2
# Generate random image matching your description:
# shape is (128,128), values are real numbers in range [0,1]
image = np.random.uniform(0, np.nextafter(1,2), (128,128))
# Scale and convert data type
image_8bit = np.uint8(image * 255)
threshold_level = 127 # Set as you need...
_, binarized = cv2.threshold(image_8bit, threshold_level, 255, cv2.THRESH_BINARY)
_, contours, hierarchy = cv2.findContours(binarized, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# ... processing the contours, etc.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8194 次 |
| 最近记录: |