demo_video.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # video file processing setup
  2. # from: https://stackoverflow.com/a/61927951
  3. import argparse
  4. import copy
  5. import json
  6. import os
  7. import subprocess
  8. from typing import NamedTuple
  9. import cv2
  10. import numpy as np
  11. class FFProbeResult(NamedTuple):
  12. return_code: int
  13. json: str
  14. error: str
  15. def ffprobe(file_path) -> FFProbeResult:
  16. command_array = ["ffprobe",
  17. "-v", "quiet",
  18. "-print_format", "json",
  19. "-show_format",
  20. "-show_streams",
  21. file_path]
  22. result = subprocess.run(command_array, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
  23. return FFProbeResult(return_code=result.returncode,
  24. json=result.stdout,
  25. error=result.stderr)
  26. # openpose setup
  27. from src import util
  28. from src.body import Body
  29. from src.hand import Hand
  30. body_estimation = Body('model/body_pose_model.pth')
  31. hand_estimation = Hand('model/hand_pose_model.pth')
  32. def process_frame(frame, body=True, hands=True):
  33. canvas = copy.deepcopy(frame)
  34. if body:
  35. candidate, subset = body_estimation(frame)
  36. canvas = util.draw_bodypose(canvas, candidate, subset)
  37. if hands:
  38. hands_list = util.handDetect(candidate, subset, frame)
  39. all_hand_peaks = []
  40. for x, y, w, is_left in hands_list:
  41. peaks = hand_estimation(frame[y:y + w, x:x + w, :])
  42. peaks[:, 0] = np.where(peaks[:, 0] == 0, peaks[:, 0], peaks[:, 0] + x)
  43. peaks[:, 1] = np.where(peaks[:, 1] == 0, peaks[:, 1], peaks[:, 1] + y)
  44. all_hand_peaks.append(peaks)
  45. canvas = util.draw_handpose(canvas, all_hand_peaks)
  46. return canvas
  47. # writing video with ffmpeg because cv2 writer failed
  48. # https://stackoverflow.com/questions/61036822/opencv-videowriter-produces-cant-find-starting-number-error
  49. import ffmpeg
  50. # open specified video
  51. parser = argparse.ArgumentParser(
  52. description="Process a video annotating poses detected.")
  53. parser.add_argument('file', type=str, help='Video file location to process.')
  54. parser.add_argument('--no_hands', action='store_true', help='No hand pose')
  55. parser.add_argument('--no_body', action='store_true', help='No body pose')
  56. args = parser.parse_args()
  57. video_file = args.file
  58. cap = cv2.VideoCapture(video_file)
  59. # get video file info
  60. ffprobe_result = ffprobe(args.file)
  61. info = json.loads(ffprobe_result.json)
  62. videoinfo = [i for i in info["streams"] if i["codec_type"] == "video"][0]
  63. input_fps = videoinfo["avg_frame_rate"]
  64. # input_fps = float(input_fps[0])/float(input_fps[1])
  65. input_pix_fmt = videoinfo["pix_fmt"]
  66. input_vcodec = videoinfo["codec_name"]
  67. # define a writer object to write to a movidified file
  68. postfix = info["format"]["format_name"].split(",")[0]
  69. output_file = ".".join(video_file.split(".")[:-1]) + ".processed." + postfix
  70. class Writer():
  71. def __init__(self, output_file, input_fps, input_framesize, input_pix_fmt,
  72. input_vcodec):
  73. if os.path.exists(output_file):
  74. os.remove(output_file)
  75. self.ff_proc = (
  76. ffmpeg
  77. .input('pipe:',
  78. format='rawvideo',
  79. pix_fmt="bgr24",
  80. s='%sx%s' % (input_framesize[1], input_framesize[0]),
  81. r=input_fps)
  82. .output(output_file, pix_fmt=input_pix_fmt, vcodec=input_vcodec)
  83. .overwrite_output()
  84. .run_async(pipe_stdin=True)
  85. )
  86. def __call__(self, frame):
  87. self.ff_proc.stdin.write(frame.tobytes())
  88. def close(self):
  89. self.ff_proc.stdin.close()
  90. self.ff_proc.wait()
  91. writer = None
  92. while (cap.isOpened()):
  93. ret, frame = cap.read()
  94. if frame is None:
  95. break
  96. posed_frame = process_frame(frame, body=not args.no_body,
  97. hands=not args.no_hands)
  98. if writer is None:
  99. input_framesize = posed_frame.shape[:2]
  100. writer = Writer(output_file, input_fps, input_framesize, input_pix_fmt,
  101. input_vcodec)
  102. cv2.imshow('frame', posed_frame)
  103. # write the frame
  104. writer(posed_frame)
  105. if cv2.waitKey(1) & 0xFF == ord('q'):
  106. break
  107. cap.release()
  108. writer.close()
  109. cv2.destroyAllWindows()