OpenCV 断言失败:(-215:断言失败)npoints >= 0 &&(深度 == CV_32F || 深度 == CV_32S)
Posted
技术标签:
【中文标题】OpenCV 断言失败:(-215:断言失败)npoints >= 0 &&(深度 == CV_32F || 深度 == CV_32S)【英文标题】:OpenCV Assertion failed: (-215:Assertion failed) npoints >= 0 && (depth == CV_32F || depth == CV_32S) 【发布时间】:2019-07-11 02:02:32 【问题描述】:我在this website找到了以下代码:
import os
import os.path
import cv2
import glob
import imutils
CAPTCHA_IMAGE_FOLDER = "generated_captcha_images"
OUTPUT_FOLDER = "extracted_letter_images"
# Get a list of all the captcha images we need to process
captcha_image_files = glob.glob(os.path.join(CAPTCHA_IMAGE_FOLDER, "*"))
counts =
# loop over the image paths
for (i, captcha_image_file) in enumerate(captcha_image_files):
print("[INFO] processing image /".format(i + 1, len(captcha_image_files)))
# Since the filename contains the captcha text (i.e. "2A2X.png" has the text "2A2X"),
# grab the base filename as the text
filename = os.path.basename(captcha_image_file)
captcha_correct_text = os.path.splitext(filename)[0]
# Load the image and convert it to grayscale
image = cv2.imread(captcha_image_file)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Add some extra padding around the image
gray = cv2.copyMakeBorder(gray, 8, 8, 8, 8, cv2.BORDER_REPLICATE)
# threshold the image (convert it to pure black and white)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
# find the contours (continuous blobs of pixels) the image
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Hack for compatibility with different OpenCV versions
contours = contours[0] if imutils.is_cv2() else contours[1]
letter_image_regions = []
# Now we can loop through each of the four contours and extract the letter
# inside of each one
for contour in contours:
# Get the rectangle that contains the contour
(x, y, w, h) = cv2.boundingRect(contour)
# Compare the width and height of the contour to detect letters that
# are conjoined into one chunk
if w / h > 1.25:
# This contour is too wide to be a single letter!
# Split it in half into two letter regions!
half_width = int(w / 2)
letter_image_regions.append((x, y, half_width, h))
letter_image_regions.append((x + half_width, y, half_width, h))
else:
# This is a normal letter by itself
letter_image_regions.append((x, y, w, h))
# If we found more or less than 4 letters in the captcha, our letter extraction
# didn't work correcly. Skip the image instead of saving bad training data!
if len(letter_image_regions) != 4:
continue
# Sort the detected letter images based on the x coordinate to make sure
# we are processing them from left-to-right so we match the right image
# with the right letter
letter_image_regions = sorted(letter_image_regions, key=lambda x: x[0])
# Save out each letter as a single image
for letter_bounding_box, letter_text in zip(letter_image_regions, captcha_correct_text):
# Grab the coordinates of the letter in the image
x, y, w, h = letter_bounding_box
# Extract the letter from the original image with a 2-pixel margin around the edge
letter_image = gray[y - 2:y + h + 2, x - 2:x + w + 2]
# Get the folder to save the image in
save_path = os.path.join(OUTPUT_FOLDER, letter_text)
# if the output directory does not exist, create it
if not os.path.exists(save_path):
os.makedirs(save_path)
# write the letter image to a file
count = counts.get(letter_text, 1)
p = os.path.join(save_path, ".png".format(str(count).zfill(6)))
cv2.imwrite(p, letter_image)
# increment the count for the current key
counts[letter_text] = count + 1
当我尝试运行代码时,出现以下错误:
[INFO] processing image 1/9955
Traceback (most recent call last):
File "extract_single_letters_from_captchas.py", line 47, in <module>
(x, y, w, h) = cv2.boundingRect(contour)
cv2.error: OpenCV(4.0.0) /Users/travis/build/skvark/opencv-python/opencv/modules/imgproc/src/shapedescr.cpp:741: error: (-215:Assertion failed) npoints >= 0 && (depth == CV_32F || depth == CV_32S) in function 'pointSetBoundingRect'
我尝试在 *** 上搜索解决方案,但没有找到任何类似的解决方案。
编辑(见 cmets):
type(contour[0])
= <class 'numpy.ndarray'>
len(contour)
= 4
【问题讨论】:
请添加len(contour)
和type(contour[0])
。
非常感谢您的快速回复,我刚刚更新了我的问题。
评论此行contours = contours[0] if imutils.is_cv2() else contours[1]
@BahramdunAdil 感谢您的快速回复,现在它给了我以下错误:Traceback (most recent call last): File "extract_single_letters_from_captchas.py", line 49, in <module> (x, y, w, h) = cv2.boundingRect(contour) TypeError: Expected cv::UMat for argument 'array'
@Fozoro 我更新了我的答案,提供了一些关于为什么会发生这种情况的信息,以防你好奇:)
【参考方案1】:
这是做错事了:
contours = contours[0] if imutils.is_cv2() else contours[1]
imutils.is_cv2()
正在返回 False
,即使它应该返回 True
。如果您不介意删除此依赖项,请更改为:
contours = contours[0]
我找到了原因。您所关注的教程可能是在 OpenCV 4 发布之前发布的。 OpenCV 3 将cv2.findContours(...)
更改为返回image, contours, hierarchy
,而OpenCV 2's cv2.findContours(...)
和OpenCV 4's cv2.findContours(...)
返回contours, hierarchy
。因此,在 OpenCV 4 之前,正确的说法是,如果您使用 OpenCV 2,则应为 contours[0]
,否则为 contours[1]
。如果还想拥有这个“兼容性”,可以改成:
contours = contours[1] if imutils.is_cv3() else contours[0]
【讨论】:
@Fozoro 很高兴能提供帮助,但现在我很好奇他们为什么在 OpenCV 3 上更改了这个输出 :) 如果我找到相关信息,我会告诉你 @Fozoro 我想不通 :( 更改发生在 5 个月前(这里是 commit),但没有与之相关的拉取请求或问题。有时事情只是改变了,我猜测:) 或者,您可以更改为imutils.is_cv2(or_better=True)
。如果您使用的是opencv4,您将获得True
@NikO'Lai 但这并不能解决只有 OpenCV 3 具有不同返回格式的问题【参考方案2】:
在 OpenCV4 中,cv2.findContours 只有 2 个返回值。 轮廓是第一个值
contours, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
请注意,我添加了下划线以放弃 hierarchy
的另一个返回值【讨论】:
【参考方案3】: (x, y, w, h) = cv2.boundingRect(contour.astype(np.int))
【讨论】:
虽然只有代码的答案可能会回答这个问题,但您可以通过为您的代码提供上下文、此代码工作的原因以及一些文档参考以供进一步阅读,从而显着提高您的答案质量.来自How to Answer:“简洁是可以接受的,但更全面的解释更好。”【参考方案4】:这是因为 opencv-python 版本 4.0.0。如果您想在不更改代码的情况下解决此问题,请将 opencv-python 降级到版本 3.4.9.31
卸载opencv-python
pip 卸载 opencv-python
安装opencv-python==3.4.9.31
pip install opencv-python==3.4.9.31
如果遇到函数“pointSetBoundingRect”的问题,您需要安装“opencv-python-headless”
pip install opencv-python-headless==3.4.9.31
【讨论】:
【参考方案5】:我用以下方式编写了相同的代码:
_, contours, hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
并且我的代码有效。我认为以前它返回 2 个变量,现在我们必须解压缩成三个变量。如果这不起作用,请尝试以下操作:
_, contours, _ = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
这应该可以。
更多信息可以访问OpenCV文档页面:https://docs.opencv.org/3.1.0/d4/d73/tutorial_py_contours_begin.html
希望对你有帮助。
【讨论】:
【参考方案6】:原因在于 findContours()。
在 OpenCV 版本 3 中,我们写道:
_, contours, _ = cv.findContours()
在 OpenCV 版本 4 中,我们改为:
contours, _ = cv.findContours()
使用任何一个来解决问题。
或者,我们可以使用这些命令来稳定我们的 OpenCV 版本,假设您安装了 anaconda
。
conda install -c conda-forge opencv=4.1.0
pip install opencv-contrib-python
【讨论】:
【参考方案7】:【OpenCV 3 更改 cv2.findContours(...) 以返回图像、轮廓、层次结构】 这个内容对我很有帮助。我在前面添加了一个新变量并修复了所有错误..
【讨论】:
虽然这可能是解决问题的宝贵提示,但一个好的答案也可以证明解决方案。请EDIT 提供示例代码来说明您的意思。或者,考虑将其写为评论以上是关于OpenCV 断言失败:(-215:断言失败)npoints >= 0 &&(深度 == CV_32F || 深度 == CV_32S)的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV VideoCapture 和错误:(-215:断言失败)!_src.empty() in function 'cv::cvtColor'
OpenCV(4.5.2)/tmp/pip-req-build-sl2aelck/opencv/modules/imgproc/src/color.cpp:182:错误:(-215:断言失败)!_sr
错误:(-215:断言失败)!函数'cv :: CascadeClassifier :: detectMultiScale'中的empty()