Python OpenCV人脸检测代码有时会引发'tuple'对象没有属性'shape'` [英] Python OpenCV face detection code sometimes raises `'tuple' object has no attribute 'shape'`
问题描述
我正在尝试使用opencv在python中构建人脸检测应用程序.
请参阅下面的代码段:
I am trying to build a face detection application in python using opencv.
Please see below for my code snippets:
# Loading the Haar Cascade Classifier
cascadePath = "/home/work/haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascadePath)
# Dictionary to store image name & number of face detected in it
num_faces_dict = {}
# Iterate over image directory.
# Read the image, convert it in grayscale, detect faces using HaarCascade Classifier
# Draw a rectangle on the image
for img_fname in os.listdir('/home/work/images/caltech_face_dataset/'):
img_path = '/home/work/images/caltech_face_dataset/' + img_fname
im = imread(img_path)
gray = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)
faces = faceCascade.detectMultiScale(im)
print "Number of faces found in-> ", img_fname, " are ", faces.shape[0]
num_faces_dict[img_fname] = faces.shape[0]
for (x,y,w,h) in faces:
cv2.rectangle(im, (x,y), (x+w,y+h), (255,255,255), 3)
rect_img_path = '/home/work/face_detected/rect_' + img_fname
cv2.imwrite(rect_img_path,im)
此代码对于大多数图像都适用,但是对于其中一些图像,则会引发错误-
This code works fine for most of the images but for some of them it throws an error -
AttributeError:元组"对象没有属性"shape"
AttributeError: 'tuple' object has no attribute 'shape'
在打印面数的行中出现错误.任何帮助将不胜感激.
I get error in the line where I print the number of faces. Any help would be appreciated.
推荐答案
问题的原因是,如果没有匹配项,则detectMultiScale
返回一个空元组()
,但是如果存在匹配项,则返回numpy.ndarray
. /p>
The cause of the problem is that detectMultiScale
returns an empty tuple ()
when there's no matches, but a numpy.ndarray
when there are matches.
>>> faces = classifier.detectMultiScale(cv2.imread('face.jpg'))
>>> print(type(faces), faces)
<class 'numpy.ndarray'> [[ 30 150 40 40]]
>>> faces = classifier.detectMultiScale(cv2.imread('wall.jpg'))
>>> print(type(faces), faces)
<class 'tuple'> ()
您可能期望负结果将是形状为(0,4)的ndarray,但事实并非如此.
You might expect that a negative result would be a ndarray of shape (0,4), but that's not the case.
此行为及其背后的原因是未在文档中进行解释,而是指示返回值应为对象".
This behaviour and the reasoning behind it is not explained in the documentation, which instead indicates that the return value should be "objects".
OpenCV有很多这样的疣,而隐秘的错误消息也无济于事.处理它的一种方法是在代码中添加日志记录语句或断言,以检查所有内容是否都是您期望的类型.
OpenCV has a lot of warts like this, and the cryptic error messages doesn't help. One way deal with it is to add logging statements or asserts into your code to check that everything is the type you expected.
探索库如何在诸如 ipython 之类的repl中工作是非常有用的.在 Rahul K P的答案中使用.
It's also very useful to explore how a library works in a repl such as ipython. This is used in Rahul K P's answer.
在这种情况下,您可以通过不使用shape
来解决问题. Python具有许多数据类型,这些数据类型是序列或集合,例如tuple
,list
和dict
.所有这些都实现了len()
内置函数,您也可以使用for x in y
对其进行循环.相反,shape
只是numpy.ndarray
的一个属性,在任何内置的python数据类型中都找不到.
In this case, you can solve your problem by not using shape
. Python has many data types that are sequences or collections, for example tuple
, list
and dict
. All of these implement the len()
built-in function and you can also loop over them using for x in y
. In contrast shape
is only a property of numpy.ndarray
, and not found in any of the built-in python data types.
如果您的代码重写为使用len(faces)
而不是faces.shape[0]
,则您的代码应该可以工作,因为前者可同时用于元组和ndarray.
Your code should work if you rewrite it to use len(faces)
instead of faces.shape[0]
, since the former works with both tuple and ndarray.
for img_fname in os.listdir('/home/work/images/caltech_face_dataset/'):
img_path = '/home/work/images/caltech_face_dataset/' + img_fname
im = imread(img_path)
gray = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)
faces = faceCascade.detectMultiScale(gray) # use the grayscale image
print "Number of faces found in-> {} are {}".format(
img_fname, len(faces)) # len() works with both tuple and ndarray
num_faces_dict[img_fname] = len(faces)
# when faces is (), the following loop will never run, so it's safe.
for (x,y,w,h) in faces:
cv2.rectangle(im, (x,y), (x+w,y+h), (255,255,255), 3)
rect_img_path = '/home/work/face_detected/rect_' + img_fname
cv2.imwrite(rect_img_path,im)
这篇关于Python OpenCV人脸检测代码有时会引发'tuple'对象没有属性'shape'`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!