0

I am trying to create a small program for personal use with the picamera and rpi3. I have been trying for a while to implement real-time face detection using opencv. It never works. The error code I get is "error: (-215) scn == 3 || scn == 4 in function cvtColor"

The code I am trying to use is:

import numpy as np
import cv2
cam = cv2.VideoCapture(0)
name = 'detect'
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cv2.namedWindow(name, cv2.WINDOW_AUTOSIZE)
while True:
    s, img = cam.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
    cv2.imshow(name, img)    
    k = cv2.waitKey(0)
    if k == 27:
        cv2.destroyWindow("Detect")
        break

Disclaimer, the code I have posted here is not mine. I intended to copy-paste-edit the code for PERSONAL use. I do not claim to have created it, I just need it to work

Many thanks in advance

  • You should identify the line which throws that error, i.e. provide the whole stack trace. – tehhowch Mar 09 '18 at 22:34
  • Have you checked the number of channels in `img`? – beaker Mar 09 '18 at 22:52
  • Traceback (most recent call last): File "/home/pi/Desktop/test.py", line 9, in gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.error: /home/piwheels/opencv-python/opencv/modules/imgproc/src/color.cpp:10638: error: (-215) scn == 3 || scn == 4 in function cvtColor –  Mar 10 '18 at 10:21
  • Also, what do you mean by the number of channels in img? (noob alert) –  Mar 10 '18 at 10:22
  • Alright, did you check `s` to make sure you read a valid image? You're telling `cvtColor` that you're taking a `BGR` (3-channel) image and converting it to gray (a 1-channel image). `img` is apparently not a 3-channel image. Checking the number of channels will confirm this (read the documentation to find out how). Alternatively, checking the return value from `read` will tell you if the image was successfully read from the camera at all. – beaker Mar 10 '18 at 15:17
  • The image I'm trying to read is the raw picamera output. Where might I find the documentation? –  Mar 10 '18 at 19:25
  • I was referring to the OpenCV documentation on how to determine the number of channels (depth) of a `Mat`. p.s. If you tag me like @beaker, I'll be notified when you respond. Otherwise, I won't. I can't guarantee I'll remember to check back for responses. – beaker Mar 10 '18 at 21:27
  • @beaker For some reason the channel checking is not working. It works with a normal image but just now the picamera video output. it would seem that opencv needs a numpy.ndarray and I don't know how to convert it. I tried >>> import cv2 >>> cam = cv2.VideoCapture() >>> ret, img = cam.read() >>> print(img.shape) Traceback (most recent call last): File "", line 1, in print(img.shape) AttributeError: 'NoneType' object has no attribute 'shape' –  Mar 11 '18 at 08:41
  • It would seem that your VideoCapture `read` is not returning a valid image. Which is why I suggested that you check the return value `s`. – beaker Mar 11 '18 at 15:23
  • @beaker I put a "print(s)" line in the code and it returns "False" –  Mar 11 '18 at 15:55

1 Answers1

0

I have found a solution. Instead of using the code I posted above, I have stolen some new code and edited it to my liking. For some reason, it can only work when triggered from the terminal but that is acceptable.

The command needed (on linux) is : cd (path_to_script) && python3 (script_name) --picamera 1

Thanks to @beaker for helping me

from imutils.video import VideoStream
from imutils import face_utils
import datetime
import argparse
import imutils
import time
import dlib
import cv2
ap = argparse.ArgumentParser()
ap.add_argument("-r", "--picamera", type=int, default=-1,
    help="whether or not the Raspberry Pi camera should be used")
args = vars(ap.parse_args())
print("[INFO] camera sensor warming up...")
vs = VideoStream(usePiCamera=args["picamera"] > 0).start()
time.sleep(2.0)
faceCascade = cv2.CascadeClassifier('/home/pi/Documents/Python Projects/Camera/haarcascade_frontalface_default.xml')
while True:
    frame = vs.read()
    frame = imutils.resize(frame, width=400)
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30),
        flags = cv2.CASCADE_SCALE_IMAGE)
    for (x, y, w, h) in faces:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 10)
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF
    if key == ord("q"):
        break
cv2.destroyAllWindows()
vs.stop()

Disclaimer, the code I have posted here is not mine. I intended to copy-paste-edit the code for PERSONAL use. I do not claim to have created it