I'm trying to paste a picture on the face detected through a haarcascade.
While I was writing the code, I came across this error..
error: (-215:Assertion failed) (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1) in function 'cv::binary_op'
At first I thought the problem was the size of the mask and the roi wasn't same, so I refered to a same problem on stackoverflow and tried implementing the same on my code and then change it accordingly to my requirements. My aim to paste the desired picture on the roi (which is face in my case), but still the problem persists.
Here is the 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()
Please point out where did I go wrong? Thanks in advance..
I had to run it to find the problem. It is actually that roi is not the same size as the mask all the time... I think it goes "out of bounds" when setting the variable roi, numpy just gives up to the point it can.
It is hard to know for sure what is wrong, since the code (in my opinion) is a mess. For each face found you calculate several widths and heights which are not needed if you want to simply replace the face found with that of an image and to create a mask of the image.
Try something like this:
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()
I hope this helps, if not, just leave a comment