0

I want to get the coordinates of a moving landmark point where an object is moving. I tried to detect select a point first. I am a beginner at OpenCV and python. Don't know any function exist or not.

import cvzone
import numpy as np
from cvzone.FaceMeshModule import FaceMeshDetector
from cvzone.PlotModule import LivePlot



idList = [8]
 
cap = cv2.VideoCapture(0)
detector = FaceMeshDetector(maxFaces=1)


while True:
 
    if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):
        cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
 
    success, img = cap.read()
    img, faces = detector.findFaceMesh(img, draw = False)
    
    if faces:
        face = faces[0]
        leftUp = face[8]
        
        for id in idList:
            cv2.circle(img, face[id], 3,(80,200,120), cv2.FILLED)

    
    img = cv2.resize(img,(640,360))
    cv2.imshow("image", img)
    cv2.waitKey(25)
         
cap.release()
cv2.destroyAllWindows()
Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. – Community Jan 24 '22 at 04:44

1 Answers1

0

If I am understanding the question right, You would like to detect whether a specific point is moving in the landmark.

To do this I would recommend to first identify the index of the landmark, I couldn't find specific documentation for that, but you can use the following piece of code to identify it:

import cv2
from cvzone.FaceMeshModule import FaceMeshDetector

cap = cv2.VideoCapture(0)
detector = FaceMeshDetector(maxFaces=1)

def click_event(event, x, y, faces, detector):
        if event == cv2.EVENT_LBUTTONDOWN and faces[0]:
            lstOfPoints = [detector.findDistance(faces[0][i], (x, y))[0] for i in range(0, 468)]
            print(lstOfPoints.index(min(lstOfPoints)))

while True:
        _, img = cap.read()
        img, faces = detector.findFaceMesh(img, draw=False)
        if faces:
            face = faces[0]
            for i in range(0, 468):
                    cv2.circle(img, (face[i][0], face[i][1]), 1, (0, 255, 0), cv2.FILLED)
            cv2.imshow("Image", img)
            cv2.setMouseCallback('Image', lambda event, x , y, flags, params :click_event(event, x, y, faces, detector))
            cv2.waitKey(1)
        else:
            cv2.imshow("Image", img)
            cv2.waitKey(1)

You can click on the point which you want to identify for its index to be printed.

Once You got the point you're looking for, you can change the code like such:

import cv2
from cvzone.FaceMeshModule import FaceMeshDetector
import math
cap = cv2.VideoCapture(0)
detector = FaceMeshDetector(maxFaces=1)
idxOfPoint = 50
i = 10
while True:
        _, img = cap.read()
        img, faces = detector.findFaceMesh(img, draw=False)
        if faces:
            if i != 10 and i % 30 == 0:
                distanceChange = math.sqrt((faces[0][idxOfPoint][0] - pastCoord[0])**2 + (faces[0][idxOfPoint][1] - pastCoord[1])**2)
                print("point moved" if distanceChange > 20 else "point didn't move")
                pastCoord  = faces[0][idxOfPoint]
            if i == 10:
                pastCoord  = faces[0][idxOfPoint]
            cv2.circle(img, (faces[0][idxOfPoint][0], faces[0][idxOfPoint][1]), 1, (0, 255, 0), cv2.FILLED) 
            cv2.imshow("Image", img)
            cv2.waitKey(1)
            i += 1
        else:
            cv2.imshow("Image", img)
            cv2.waitKey(1)

Where 30 (in i % 30) represent the frequency of verification per frame and 20 (in distanceChange > 20) represent the minimum distance change that triggers the print.