I am building a game with openCV and pygame. When I test code, it sometimes works and sometimes returns an error saying
line 76, in "face_recognition.py"
self.dets = self.detector(self.frame, 0)
TypeError: __call__(): incompatible function arguments. The following argument types are supported:
1. (self: dlib.fhog_object_detector, image: array, upsample_num_times: int=0) -> dlib.rectangles
I think it means the self.frame is empty but why does it sometimes work and some times not? How should I fix this problem?
This is the class of the face recognition.
class face():
def __init__(self,game,screen):
super().__init__()
self.game=game
self.screen=screen
self.cap = cv2.VideoCapture(0)
self.fourcc = cv2.VideoWriter_fourcc(*'XVID')
self.predictor_path = 'shape_predictor_81_face_landmarks.dat'
self.detector = dlib.get_frontal_face_detector() #INITIALIZE FACE PROTECTOR
self.predictor = dlib.shape_predictor(self.predictor_path) #LANDMARK PREDICTO
self.cap.set(3,160) #self.
self.cap.set(4,120)
self.color=False#True#False
(self.mStart,self.mEnd)=(48,54) #mouth
self.MOUTH_AR_THRESH = 0.1
self.direction = 0 #direction of eyebrows
# grab the indexes of the facial landmarks for the left and
# right eyebrows, respectively
(self.lbStart, self.lbEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eyebrow"]
(self.rbStart, self.rbEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eyebrow"]
#Get the indexes of the nose line
(self.nStart, self.nEnd) = face_utils.FACIAL_LANDMARKS_IDXS["nose"]
#Get the mid indexes of the facial landmarks
self.lbMid = int((self.lbStart + self.lbEnd)/2)
self.rbMid = int((self.rbStart +self.rbEnd)/2)
self.nMid = int((self.nStart + self.nEnd)/2)
# Define variables that will contain the euclidean distances
self.rightEyebrowToNose = 0
self.leftEyebrowToNose = 0
def __call__(self):
print (" ")
def getDirection(self):
return self.direction
def defineDirection(self,direction):
self.direction = direction
def face_recognition(self,screen):
self.ret,self.frame = self.cap.read()
self.frame = cv2.flip(self.frame, 1)
self.dets = self.detector(self.frame, 0) #rects
self.cvToPygame=cv2.cvtColor(self.frame,cv2.COLOR_BGR2RGB)
if not self.color:
self.cvToPygame=cv2.cvtColor(self.cvToPygame,cv2.COLOR_BGR2GRAY)
self.cvToPygame=cv2.cvtColor(self.cvToPygame,cv2.COLOR_GRAY2RGB)
self.cvToPygame=np.rot90(self.cvToPygame)
self.cvToPygame=pygame.surfarray.make_surface(self.cvToPygame)
self.screen.blit(self.cvToPygame,(0,0))
for k, d in enumerate(self.dets):
shape = self.predictor(self.frame, d)
landmarks = np.matrix([[p.x, p.y] for p in shape.parts()])
for num in range(shape.num_parts):
cv2.circle(self.frame, (shape.parts()[num].x, shape.parts()[num].y), 3, (0,255,0), -1)
A=dist.euclidean((shape.parts()[61].x,shape.parts()[61].y),(shape.parts()[67].x,shape.parts()[67].y))
B=dist.euclidean((shape.parts()[63].x,shape.parts()[63].y),(shape.parts()[65].x,shape.parts()[65].y))
C=dist.euclidean((shape.parts()[48].x,shape.parts()[48].y),(shape.parts()[54].x,shape.parts()[54].y))
mar=(A+B)/(2.0*C)
mar=round(mar,5)
if mar>self.MOUTH_AR_THRESH:
#cv2.putText(self.frame,"MOUTH IS OPEN!",(30,60),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)
print("mouth is open")
return True
else:
print("closed")
return False
self.cap.release()
cv2.destroyAllWindows()
def distance(A, B):
(ax,ay) = A
(bx,by) = B
return math.sqrt((ax-bx)**2 + (ay-by)**2)
def eyebrowDetection(self,screen):
for k, d in enumerate(self.dets):
shape = self.predictor(self.frame, d)
shape = face_utils.shape_to_np(shape)
# Get the positions of the
leftEyebrowCoordinates = shape[self.lbMid]
rightEyebrowCoordinates = shape[self.rbMid]
currentNosePosition = midPointNoseCoordinates = shape[self.nMid]
midPointNoseCoordinates = shape[self.nMid]
currentRightEyebrowDistance = dist.euclidean(rightEyebrowCoordinates,midPointNoseCoordinates)
currentLeftEyebrowDistance =dist.euclidean(leftEyebrowCoordinates,midPointNoseCoordinates)
if (self.rightEyebrowToNose == 0) or (self.leftEyebrowToNose == 0):
self.rightEyebrowToNose =dist.euclidean(rightEyebrowCoordinates,midPointNoseCoordinates)
self.leftEyebrowToNose = dist.euclidean(leftEyebrowCoordinates,midPointNoseCoordinates)
elif (currentRightEyebrowDistance > self.rightEyebrowToNose) or (currentLeftEyebrowDistance > self.leftEyebrowToNose):
self.defineDirection(1)
print ("[RESULT] UP")
return True
else:
self.defineDirection(-1)
print ("[RESULT] DOWN")
return False
The below is how I call the functions in main.
def main(self):
face=face_recog.face(self,self.screen)
....
while True:
mouthOpen=face.face_recognition(self.screen)
eyebrow=face.eyebrowDetection(self.screen)
while buttonPressed==2:
buttonPressed=gameover_.pausePressed()
if buttonPressed==1:
self.gameover=True
break
self.player.update(self,self.up,self.down,self.left, self.right)
self.camera.update()
pygame.display.flip()
Please help me solve the problem.