Python OpenCv2 place image over face found

308 views Asked by At

I am loading several images will go over my face and I am having difficulty getting the image to go over the square for face created. I have looked at a many resources , but for some reason I am receiving an error when attempting to follow their method.

Every time I do so , I receive an error

ValueError: could not broadcast input array from shape (334,334,3) into shape (234,234,3)

I think the images might be too large, however I tried to resize them to see if they will fit to no avail.

here is my code:

import cv2
import sys
import logging as log
import datetime as dt
from time import sleep
import os
import random 
from timeit import default_timer as timer


cascPath = "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascPath)
#log.basicConfig(filename='webcam.log',level=log.INFO)

video_capture = cv2.VideoCapture(0)
anterior = 0

#s_img = cv2.imread("my.jpg")

increment = 0

for filename in os.listdir("Faces/"):
    if filename.endswith(".png"): 
         FullFile = (os.path.join("Faces/", filename))
         #ret, frame = video_capture.read()
         frame = cv2.imread(FullFile, cv2.IMREAD_UNCHANGED)

         gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
         faces = faceCascade.detectMultiScale( gray,scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)  )
         edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9) 
         
         for (x, y, w, h) in faces:            
            roi_color = frame[y:( y ) + ( h ), x:x + w]
            status = cv2.imwrite('export/faces_detected'+ str( increment ) +'.png', roi_color)
            increment = increment + 1 

        
    else:
        continue

masks = []


for filename in os.listdir("export/"):
    if filename.endswith(".png"): 
         FullFile = (os.path.join("export/", filename))
         s_img = cv2.imread(FullFile)
         masks.append(s_img)


Start = timer()
End = timer()
MasksSize = len(masks)
nrand = random.randint(0, MasksSize -1 )

increment =  0

while True:
    if not video_capture.isOpened():
        print('Unable to load camera.')
        sleep(5)
        pass

    # Capture frame-by-frame
    ret, frame = video_capture.read()

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30)
    )



    edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9) 


    # Draw a rectangle around the faces
    for (x, y, w, h) in faces:
        if (End - Start) > 3:
            Start = timer()
            End = timer()
            nrand = random.randint(0, MasksSize -1 )


        # -75 and +20 added to fit my face
        cv2.rectangle(frame, (x, y - 75), (x+w, y+h+20), (0, 255, 0), 2)
        s_img = masks[nrand]  
        increment = increment + 1 
        #maskresize = cv2.resize(s_img, (150, 150))


        #frame[y:y+s_img.shape[0]  , x:x+s_img.shape[1]] = s_img # problem occurs here with 


        # ValueError: could not broadcast input array from shape (334,334,3) into shape (234,234,3)
        # I assume I am inserting somethign too big? 
        End = timer()
        


        


    if anterior != len(faces):
        anterior = len(faces)
        #log.info("faces: "+str(len(faces))+" at "+str(dt.datetime.now()))


    # Display the resulting frame
    cv2.imshow('Video', frame)
    #cv2.imshow('Video', cartoon)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

    # Display the resulting frame
    cv2.imshow('Video', frame)

# When everything is done, release the capture
video_capture.release()
cv2.destroyAllWindows()
1

There are 1 answers

0
Karthik Sanka On BEST ANSWER
  • In the following line,
frame[y:y+s_img.shape[0]  , x:x+s_img.shape[1]] = s_img 

you are trying to attempt to assign s_img to frame[y:y+s_img.shape[0] , x:x+s_img.shape[1]] which are of different shapes.

  • You can check the shapes of the two by printing the shape (it will be the same as the shapes mentioned in the error).
  • Try reshaping s_img to the same shape and then try to assign.
Refer to this link:https://www.geeksforgeeks.org/image-resizing-using-opencv-python/

I used this function to resize the image to scale.

def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
    # initialize the dimensions of the image to be resized and
    # grab the image size
    dim = None
    (h, w) = image.shape[:2]

    # if both the width and height are None, then return the
    # original image
    if width is None and height is None:
        return image

    # check to see if the width is None
    if width is None:
        # calculate the ratio of the height and construct the
        # dimensions
        r = height / float(h)
        dim = (int(w * r), height)

    # otherwise, the height is None
    else:
        # calculate the ratio of the width and construct the
        # dimensions
        r = width / float(w)
        dim = (width, int(h * r))

    # resize the image
    resized = cv2.resize(image, dim, interpolation = inter)

    # return the resized image
    return resized

Then later on called

 r= image_resize(s_img, height = h, width=w)
 frame[y:y+r.shape[0]  , x:x+r.shape[1]] = r 

Answer taken from here too: Resize an image without distortion OpenCV