Skip to content

Commit d32c5b9

Browse files
author
arch
committed
always use ffmpeg to extract frames
1 parent e89f7b7 commit d32c5b9

File tree

3 files changed

+89
-28
lines changed

3 files changed

+89
-28
lines changed

funscript_editor/algorithms/funscriptgenerator.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,12 +254,17 @@ def scale_score(self, status: str, metric : str = 'y') -> None:
254254
min_frame = np.argmin(np.array(self.score[metric])) + self.params.start_frame
255255
max_frame = np.argmax(np.array(self.score[metric])) + self.params.start_frame
256256

257-
cap = cv2.VideoCapture(self.params.video_path)
258-
cap.set(cv2.CAP_PROP_POS_FRAMES, min_frame)
259-
success_min, imgMin = cap.read()
260-
cap.set(cv2.CAP_PROP_POS_FRAMES, max_frame)
261-
success_max, imgMax = cap.read()
262-
cap.release()
257+
if False:
258+
cap = cv2.VideoCapture(self.params.video_path)
259+
cap.set(cv2.CAP_PROP_POS_FRAMES, min_frame)
260+
success_min, imgMin = cap.read()
261+
cap.set(cv2.CAP_PROP_POS_FRAMES, max_frame)
262+
success_max, imgMax = cap.read()
263+
cap.release()
264+
else:
265+
success_min, success_max = True, True
266+
imgMin = FFmpegStream.get_frame(self.params.video_path, min_frame)
267+
imgMax = FFmpegStream.get_frame(self.params.video_path, max_frame)
263268

264269
if success_min and success_max:
265270
if self.is_vr_video():
@@ -534,6 +539,7 @@ def tracking(self) -> str:
534539
delete_last_predictions = 0
535540
bbox_woman = [None for _ in range(self.params.number_of_trackers)]
536541
bbox_men = [None for _ in range(self.params.number_of_trackers)]
542+
self.ui.clear_keypress_queue()
537543
try:
538544
while video.isOpen():
539545
cycle_start = time.time()

funscript_editor/algorithms/videotracker.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
""" Video Tracker """
22

3-
import os
43
import cv2
54
import time
5+
import copy
66
import funscript_editor.utils.logging as logging
77
import platform
88

@@ -65,6 +65,8 @@ def __init__(self,
6565
self.tracking_counter = 0
6666
self.cluster_center = [0, 0]
6767
self.plausibility_thresholds = [0, 0]
68+
self.current_detected_tracking_box = tracking_bbox
69+
self.lats_detected_tracking_box = tracking_bbox
6870
self.last_valid_tracking_box = tracking_bbox
6971
self.supervised_tracking_is_exit_condition = supervised_tracking_is_exit_condition
7072

@@ -190,6 +192,19 @@ def __is_plausible(self, box) -> bool:
190192
return True
191193

192194

195+
@staticmethod
196+
def get_center(box: tuple) -> tuple:
197+
""" Get the cencter point of an box
198+
199+
Args:
200+
box (tuple): the predicted bounding box
201+
202+
Returns:
203+
tuple (x,y) of the current point
204+
"""
205+
return ( round(box[0] + box[2]/2), round(box[1] + box[3]/2) )
206+
207+
193208
def run(self) -> None:
194209
""" The Video Tracker Thread Function """
195210
self.__setup_tracker()
@@ -226,6 +241,8 @@ def run(self) -> None:
226241
frame = self.queue_in.get()
227242
frame_roi = frame[y0:y1, x0:x1]
228243
success, bbox = self.tracker.update(frame_roi)
244+
self.last_detected_tracking_box = self.current_detected_tracking_box
245+
self.current_detected_tracking_box = copy.deepcopy(bbox)
229246
self.tracking_counter += 1
230247
status = StaticVideoTracker.Status.TRACKING_LOST
231248
if not success or bbox is None:

funscript_editor/data/ffmpegstream.py

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -111,27 +111,6 @@ def get_video_info(
111111
return video_info
112112

113113

114-
@staticmethod
115-
def get_frame(
116-
video_path :str,
117-
frame_number :int) -> np.ndarray:
118-
""" Get Video frame
119-
120-
Args:
121-
video_path (str): path to video
122-
frame_number (int): frame number to extract from video
123-
124-
Returns:
125-
np.ndarray: opencv image
126-
"""
127-
cap = cv2.VideoCapture(video_path)
128-
if frame_number > 0:
129-
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
130-
_, frame = cap.read()
131-
cap.release()
132-
return frame
133-
134-
135114
@staticmethod
136115
def get_ffmpeg_command() -> str:
137116
""" Get FFmpeg binary command string
@@ -314,6 +293,65 @@ def more(self) -> bool:
314293
return self.frame_buffer.qsize() > 0
315294

316295

296+
@staticmethod
297+
def get_frame(
298+
video_path :str,
299+
frame_number :int) -> np.ndarray:
300+
""" Get Video frame
301+
302+
Args:
303+
video_path (str): path to video
304+
frame_number (int): frame number to extract from video
305+
306+
Returns:
307+
np.ndarray: opencv image
308+
"""
309+
if False:
310+
cap = cv2.VideoCapture(video_path)
311+
if frame_number > 0:
312+
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
313+
_, frame = cap.read()
314+
cap.release()
315+
return frame
316+
else:
317+
video_info = FFmpegStream.get_video_info(video_path)
318+
seek = FFmpegStream.frame_to_timestamp(frame_number, video_info.fps)
319+
320+
command = [
321+
FFmpegStream.get_ffmpeg_command(),
322+
'-hide_banner',
323+
'-loglevel', 'warning',
324+
'-ss', str(seek),
325+
'-hwaccel', 'auto',
326+
'-i', video_path,
327+
'-f', 'image2pipe',
328+
'-pix_fmt', 'bgr24',
329+
'-vsync', '0',
330+
'-vcodec', 'rawvideo',
331+
'-an',
332+
'-sn',
333+
'-'
334+
]
335+
336+
pipe = sp.Popen(
337+
command,
338+
stdout = sp.PIPE,
339+
stderr = sp.PIPE,
340+
bufsize= 3 * video_info.height * video_info.width
341+
)
342+
343+
data = pipe.stdout.read(video_info.width * video_info.height * 3)
344+
pipe.terminate()
345+
try: pipe.stdout.close()
346+
except: pass
347+
try: pipe.stderr.close()
348+
except: pass
349+
350+
return np.frombuffer(data, dtype='uint8').reshape(
351+
(video_info.height, video_info.width, 3)
352+
)
353+
354+
317355
def run(self) -> None:
318356
""" Function to read transformed frames from ffmpeg video stream into a queue """
319357

0 commit comments

Comments
 (0)