demo_video.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import copy
  2. import numpy as np
  3. import cv2
  4. import os
  5. import json
  6. # video file processing setup
  7. # from: https://stackoverflow.com/a/61927951
  8. import argparse
  9. import subprocess
  10. from typing import NamedTuple
  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()