Python OpenCV人脸检测代码有时会引发'tuple'对象没有属性'shape'` [英] Python OpenCV face detection code sometimes raises `'tuple' object has no attribute 'shape'`

查看:923
本文介绍了Python OpenCV人脸检测代码有时会引发'tuple'对象没有属性'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具有许多数据类型,这些数据类型是序列或集合,例如tuplelistdict.所有这些都实现了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆