main.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import cv2
  2. import mediapipe as mp
  3. from vidstab import VidStab
  4. from pyvirtualcam import PixelFormat
  5. import pyvirtualcam
  6. import platform
  7. # global variables
  8. gb_zoom = 1.4
  9. def zoom_at(image, coord=None, zoom_type=None):
  10. """
  11. Args:
  12. image: frame captured by camera
  13. coord: coordinates of face(nose)
  14. zoom_type:Is it a transition or normal zoom
  15. Returns:
  16. Image with cropped image
  17. """
  18. global gb_zoom
  19. # If zoom_type is transition check if Zoom is already done else zoom by 0.1 in current frame
  20. if zoom_type == 'transition' and gb_zoom < 3.0:
  21. gb_zoom = gb_zoom + 0.1
  22. # If zoom_type is normal zoom check if zoom more than 1.4 if soo zoom out by 0.1 in each frame
  23. if gb_zoom != 1.4 and zoom_type is None:
  24. gb_zoom = gb_zoom - 0.1
  25. zoom = gb_zoom
  26. # If coordinates to zoom around are not specified, default to center of the frame
  27. cy, cx = [i / 2 for i in image.shape[:-1]] if coord is None else coord[::-1]
  28. # Scaling the image using getRotationMatrix2D to appropriate zoom
  29. rot_mat = cv2.getRotationMatrix2D((cx, cy), 0, zoom)
  30. # Use warpAffine to make sure that lines remain parallel
  31. result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
  32. return result
  33. def frame_manipulate(img):
  34. """
  35. Args:
  36. image: frame captured by camera
  37. Returns:
  38. Image with manipulated output
  39. """
  40. # Mediapipe face set up
  41. mp_face_detection = mp.solutions.face_detection
  42. with mp_face_detection.FaceDetection(
  43. model_selection=1, min_detection_confidence=0.5) as face_detection:
  44. img.flags.writeable = False
  45. img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  46. results = face_detection.process(img)
  47. img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
  48. # Set the default values to None
  49. coordinates = None
  50. zoom_transition = None
  51. if results.detections:
  52. for detection in results.detections:
  53. height, width, channels = img.shape
  54. # Fetch coordinates of nose, right ear and left ear
  55. nose = detection.location_data.relative_keypoints[2]
  56. right_ear = detection.location_data.relative_keypoints[4]
  57. left_ear = detection.location_data.relative_keypoints[5]
  58. # get coordinates for right ear and left ear
  59. right_ear_x = int(right_ear.x * width)
  60. left_ear_x = int(left_ear.x * width)
  61. # Fetch coordinates for the nose and set as center
  62. center_x = int(nose.x * width)
  63. center_y = int(nose.y * height)
  64. coordinates = [center_x, center_y]
  65. # Check the distance between left ear and right ear if distance is less than 120 pixels zoom in
  66. if (left_ear_x - right_ear_x) < 120:
  67. zoom_transition = 'transition'
  68. # Perform zoom on the image
  69. img = zoom_at(img, coord=coordinates, zoom_type=zoom_transition)
  70. return img
  71. def main():
  72. # Video Stabilizer
  73. device_val = None
  74. stabilizer = VidStab()
  75. # For webcam input:
  76. cap = cv2.VideoCapture(0)
  77. cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) # set new dimensions to cam object (not cap)
  78. cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
  79. cap.set(cv2.CAP_PROP_FPS, 120)
  80. # Check OS
  81. os = platform.system()
  82. if os == "Linux":
  83. device_val = "/dev/video2"
  84. # Start virtual camera
  85. with pyvirtualcam.Camera(1280, 720, 120, device=device_val, fmt=PixelFormat.BGR) as cam:
  86. print('Virtual camera device: ' + cam.device)
  87. while True:
  88. success, img = cap.read()
  89. img = frame_manipulate(img)
  90. # Stabilize the image to make sure that the changes with Zoom are very smooth
  91. img = stabilizer.stabilize_frame(input_frame=img,
  92. smoothing_window=2, border_size=-20)
  93. # Resize the image to make sure it does not crash pyvirtualcam
  94. img = cv2.resize(img, (1280, 720),
  95. interpolation=cv2.INTER_CUBIC)
  96. cam.send(img)
  97. cam.sleep_until_next_frame()
  98. if __name__ == '__main__':
  99. main()