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