1
votes

I am working on taking a picture with a webcam connected to Raspberry Pi 2 model B. Then, I detect the face in the picture and crop the face and save it as a separate image. The below code worked perfectly in Windows.

import numpy as np
import cv2
import math
from random import random

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0)
ret,frame = cap.read()

#naming the image and save path

img_name = str(int(math.ceil(100000*random())))
img_path = 'images/'+img_name+'.png'
crop_img_path = 'images/'+'crop_'+img_name+'.png'

# directly saving the image
cv2.imwrite(img_path,frame)

cap.release()

img = cv2.imread(img_path)  #read image to numeric array

#printing image information
print str(img.shape) + " "
print str(img.size) + " "
print str(img.dtype)

#detecting face
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
face_cascade.load('haarcascade_frontalface_default.xml')
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
    img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) # drawing rectangle (Blue, thickness 2)
    print str(x)+" "+str(y)+" "+str(x+w)+" "+str(y+h) #printing region coordinates of rectangle
    crop_img = img[y:y+h,x:x+w]
    cv2.imwrite(crop_img_path,crop_img)

But it is giving following error in Raspbian:

Traceback (most recent call last):
File "xyz.py", line 35, in <module>
crop_img = img[y:y+h,x:x+w]
TypeError: 'NoneType' object has no attribute '__getitem__'

Note 1: The original captured image is saved in the images folder.

Note 2: I installed OpenCV for Python using follow command:

sudo apt-get install python-opencv
1

1 Answers

2
votes

Your issue is at this line: img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) and here you are re-assigning img to None so you lose it's original object.

Referring to OpenCV2 documentation, cv2.rectangle returns None.

Thus,

crop_img = img[y:y+h,x:x+w] gives you error message

rectangle

Draws a simple, thick, or filled up-right rectangle.

C++: void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)

C++: void rectangle(Mat& img, Rect rec, const Scalar& color, int thickness=1, int lineType=8, int shift=0 )

Python: cv2.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) → None

C: void cvRectangle(CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color, int thickness=1, int line_type=8, int shift=0 )

Python: cv.Rectangle(img, pt1, pt2, color, thickness=1, lineType=8, shift=0) → None

So as a fix to your code, you should not re-assign img, but instead do:

for (x,y,w,h) in faces:
    cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) # drawing rectangle (Blue, thickness 2)
    print str(x)+" "+str(y)+" "+str(x+w)+" "+str(y+h) #printing region coordinates of rectangle
    crop_img = img[y:y+h,x:x+w]
    cv2.imwrite(crop_img_path,crop_img)