Erreur Opencv: (-215: Échec de l'assertion) (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize (* psrc1) dans la fonction 'cv :: binary_op'


Prithvi Raj Kanaujia

J'essaye de coller une image sur le visage détecté lors d'une haarcascade.

Pendant que j'écrivais le code, je suis tombé sur cette erreur.

error: (-215:Assertion failed) (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1) in function 'cv::binary_op'

Au début, je pensais que le problème était la taille du masque et que le retour sur investissement n'était pas le même, alors j'ai fait référence au même problème sur stackoverflow et j'ai essayé de l'implémenter sur mon code, puis de le modifier en fonction de mes besoins. Mon objectif est de coller l'image souhaitée sur le ROI (qui est le visage dans mon cas), mais le problème persiste.

Voici le code.

import cv2
import numpy as np
import imutils

cap=cv2.VideoCapture(0)
classifier= cv2.CascadeClassifier('D:\\Downloads\\Computer-Vision-Tutorial-master\\Computer-Vision-Tutorial-master\\Haarcascades\\haarcascade_frontalface_default.xml')

img=cv2.imread("D:\\Downloads\\anonymous_face_mask.jpg")
rows,cols,channels=img.shape
while(cap.isOpened()):
    img=cv2.imread("D:\\Downloads\\anonymous_face_mask.jpg")
    _,frame=cap.read()

    gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    
    img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    ret,original_mask=cv2.threshold(img_gray,100,255,cv2.THRESH_BINARY_INV)
    original_mask_inv=cv2.bitwise_not(original_mask)
    #cv2.imshow("mask_inv",mask_inv)
    face=classifier.detectMultiScale(gray,1.4,5)

    
    for x,y,w,h in face:
        
        face_w = w
        face_h = h
        face_x1 = x
        face_x2 = face_x1 + face_h
        face_y1 = y
        face_y2 = face_y1 + face_h
        img_width=3*face_w
        img_height=int(img_width*rows/cols)

        img_x1=face_x2-int(face_w/2)-int(img_width/2)
        img_x2=face_x1+img_width
        img_y1=face_y2+5
        img_y2=img_y1+img_height

        if img_x1<0:
            img_x1=0
        if img_y1<0:
            img_y1=0
        if img_x2<cols:
            img_x2=cols
        if img_y2<rows:
            img_y2=rows

        imgwidth=img_x2-img_x1
        imgheight=img_y2-img_y1
        if imgwidth<0 or imgheight<0:
            continue

        image=cv2.resize(img,(imgwidth,imgheight),cv2.INTER_AREA)
        mask=cv2.resize(original_mask,(imgwidth,imgheight),cv2.INTER_AREA)
        mask_inv=cv2.resize(original_mask_inv,(imgwidth,imgheight),cv2.INTER_AREA)
        roi=frame[img_y1:img_y2,img_x1:img_x2]
        frame_bg=cv2.bitwise_and(roi,roi,mask=mask)
        img_fg=cv2.bitwise_and(image,image,mask=mask_inv)
        dst=cv2.add(frame_bg,img_fg)
        frame[img_y1:img_y2,img_x1:img_x2]=dst
        cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,255),2)
        cv2.imshow("framee",frame)
    
    k = cv2.waitKey(1) & 0xff
    if k == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Veuillez indiquer où je me suis trompé? Merci d'avance..

api55

J'ai dû l'exécuter pour trouver le problème. C'est en fait que le ROI n'est pas tout le temps de la même taille que le masque ... Je pense que ça va "hors des limites" lors de la définition de la variable ROI, numpy cède juste au maximum.

Il est difficile de savoir avec certitude ce qui ne va pas, car le code (à mon avis) est un gâchis. Pour chaque visage trouvé, vous calculez plusieurs largeurs et hauteurs qui ne sont pas nécessaires si vous voulez simplement remplacer le visage trouvé par celui d'une image et créer un masque de l'image.

Essayez quelque chose comme ceci:

import cv2
import numpy as np

# initialize camera, classifier and load the new image
cap=cv2.VideoCapture(0)
img=cv2.imread("image.png")
classifier= cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# create masks to be used later
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,original_mask=cv2.threshold(img_gray,100,255,cv2.THRESH_BINARY_INV)
original_mask_inv=cv2.bitwise_not(original_mask)

while(cap.isOpened()):
    # get image and find the face(s)
    _,frame=cap.read()
    gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    face = classifier.detectMultiScale(gray,1.4,5)
    
    for x,y,w,h in face:
        # resize images and mask to size of the face
        newFace = cv2.resize(img,(w,h),cv2.INTER_AREA)
        mask = cv2.resize(original_mask,(w,h),cv2.INTER_AREA)
        mask_inv = cv2.resize(original_mask_inv,(w,h),cv2.INTER_AREA)

        # obtain the foreground of the image and the background of the camera frame
        roi=frame[y:y+h,x:x+w]
        frame_bg=cv2.bitwise_and(roi,roi,mask=mask)
        img_fg=cv2.bitwise_and(newFace,newFace,mask=mask_inv)

        # replace the face with the image data and draw a rectangle
        frame[y:y+h,x:x+w]= frame_bg + img_fg
        cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,255),2)
    
    # show image and wait parse key    
    cv2.imshow("framee",frame)
    k = cv2.waitKey(1) & 0xff
    if k == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

J'espère que cela aide, sinon, laissez un commentaire

Articles connexes