Python OpenCv2 place l'image sur le visage trouvé

Oct 02 2020

Je charge plusieurs images qui iront sur mon visage et j'ai du mal à faire passer l'image sur le carré du visage créé. J'ai examiné de nombreuses ressources, mais pour une raison quelconque, je reçois une erreur lorsque j'essaie de suivre leur méthode.

Chaque fois que je le fais, je reçois une erreur

ValueError: impossible de diffuser le tableau d'entrée de la forme (334,334,3) vers la forme (234,234,3)

Je pense que les images sont peut-être trop grandes, mais j'ai essayé de les redimensionner pour voir si elles conviendraient en vain.

voici mon 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()

Réponses

1 KarthikSanka Oct 03 2020 at 03:44
  • Dans la ligne suivante,
frame[y:y+s_img.shape[0]  , x:x+s_img.shape[1]] = s_img 

vous essayez d'assigner s_img au frame [y: y + s_img.shape [0], x: x + s_img.shape [1]] qui sont de formes différentes.

  • Vous pouvez vérifier les formes des deux en imprimant la forme (elle sera la même que les formes mentionnées dans l'erreur).
  • Essayez de remodeler s_img à la même forme, puis essayez de l'attribuer.
Reportez-vous à ce lien: https://www.geeksforgeeks.org/image-resizing-using-opencv-python/

J'ai utilisé cette fonction pour redimensionner l'image à l'échelle.

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

Puis plus tard appelé

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

Réponse tirée d'ici aussi: Redimensionner une image sans distorsion OpenCV