Skip to content

Commit 3961a18

Browse files
author
arch
committed
reimplement scaling part 2
1 parent d7baf58 commit 3961a18

File tree

10 files changed

+126
-602
lines changed

10 files changed

+126
-602
lines changed

funscript_editor/algorithms/funscriptgenerator.py

Lines changed: 73 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
from funscript_editor.algorithms.videotracker import StaticVideoTracker
1616
from PyQt5 import QtGui, QtCore, QtWidgets
1717
from matplotlib.figure import Figure
18-
from funscript_editor.utils.config import HYPERPARAMETER, SETTINGS
18+
from funscript_editor.utils.config import HYPERPARAMETER, SETTINGS, PROJECTION
1919
from datetime import datetime
20-
from funscript_editor.data.ffmpegstream import FFmpegStream, FFmpegStreamParameter, VideoInfo
20+
from funscript_editor.data.ffmpegstream import FFmpegStream, VideoInfo
2121

2222
import funscript_editor.algorithms.signalprocessing as sp
2323
import numpy as np
@@ -42,7 +42,8 @@ class FunscriptGeneratorParameter:
4242
zoom_factor :float = max((1.0, float(SETTINGS['zoom_factor'])))
4343
top_threshold :float = float(HYPERPARAMETER['top_threshold'])
4444
bottom_threshold :float = float(HYPERPARAMETER['bottom_threshold'])
45-
preview_scaling :float = 1.0
45+
preview_scaling :float = float(SETTINGS['preview_scaling'])
46+
projection :str = str(SETTINGS['projection']).lower()
4647

4748

4849
class FunscriptGenerator(QtCore.QThread):
@@ -89,6 +90,24 @@ def __init__(self,
8990
logger = logging.getLogger(__name__)
9091

9192

93+
def determine_monitor_scaling(self):
94+
frame_width = PROJECTION[self.params.projection]['parameter']['width']
95+
frame_height = PROJECTION[self.params.projection]['parameter']['height']
96+
97+
scale = []
98+
try:
99+
for monitor in get_monitors():
100+
scale.append( min((monitor.width / float(frame_width), monitor.height / float(frame_height) )) )
101+
except: pass
102+
103+
if len(scale) == 0:
104+
self.logger.error("Monitor resolution info not found")
105+
self.monitor_scale = 1.0
106+
else:
107+
# asume we use the largest monitor for scipting
108+
self.mointor_scale = max(scale)
109+
110+
92111
def drawBox(self, img: np.ndarray, bbox: tuple) -> np.ndarray:
93112
""" Draw an tracking box on the image/frame
94113
@@ -291,9 +310,20 @@ def scale_score(self, status: str, direction : str = 'y') -> None:
291310
cap.release()
292311

293312
if successMin and successMax:
294-
# TODO: Assume we have VR 3D Side by Side
295-
imgMin = imgMin[:, :int(imgMin.shape[1]/2)]
296-
imgMax = imgMax[:, :int(imgMax.shape[1]/2)]
313+
if 'vr' in self.params.projection.split('_'):
314+
if 'sbs' in self.params.projection.split('_'):
315+
imgMin = imgMin[:, :int(imgMin.shape[1]/2)]
316+
imgMax = imgMax[:, :int(imgMax.shape[1]/2)]
317+
elif 'ou' in self.params.projection.split('_'):
318+
imgMin = imgMin[:int(imgMin.shape[0]/2), :]
319+
imgMax = imgMax[:int(imgMax.shape[0]/2), :]
320+
321+
if PROJECTION[self.params.projection]['parameter']['width'] > 0:
322+
scale = PROJECTION[self.params.projection]['parameter']['width'] / float(2*imgMax.shape[1])
323+
else:
324+
scale = PROJECTION[self.params.projection]['parameter']['height'] / float(2*imgMax.shape[1])
325+
imgMin = cv2.resize(imgMin, None, fx=scale, fy=scale)
326+
imgMax = cv2.resize(imgMax, None, fx=scale, fy=scale)
297327

298328
(desired_min, desired_max) = self.min_max_selector(
299329
image_min = imgMin,
@@ -381,31 +411,16 @@ def preview_scaling(self, preview_image :np.ndarray) -> np.ndarray:
381411
Returns:
382412
np.ndarray: scaled opencv image
383413
"""
384-
"""
385-
frame_height, frame_width = preview_image.shape[:2]
386-
scale = []
387-
try:
388-
for monitor in get_monitors():
389-
scale.append( min((monitor.width / (frame_width*1.1), monitor.height / (frame_height*1.1) )) )
390-
except: pass
391-
392-
if len(scale) == 0:
393-
self.logger.error("Monitor resolution info not found")
394-
scale = 1.0
395-
else:
396-
# asume we use the largest monitor for scipting
397-
scale = max(scale)
398-
"""
399414
return cv2.resize(preview_image, None, fx=self.params.preview_scaling, fy=self.params.preview_scaling)
400415

401416

402-
def get_projection_parameter(self, image :np.ndarray) -> None:
403-
""" Get the projection ROI parameters form user input
417+
def get_vr_projection_config(self, image :np.ndarray) -> None:
418+
""" Get the projection ROI config form user input
404419
405420
Args:
406421
image (np.ndarray): opencv vr 180 or 360 image
407422
"""
408-
parameter = FFmpegStreamParameter()
423+
config = PROJECTION[self.params.projection]
409424

410425
# NOTE: improve processing speed to make this menu more responsive
411426
if image.shape[0] > 6000 or image.shape[1] > 6000:
@@ -418,7 +433,7 @@ def get_projection_parameter(self, image :np.ndarray) -> None:
418433
while not selected:
419434
if parameter_changed:
420435
parameter_changed = False
421-
preview = FFmpegStream.get_projection(image, parameter)
436+
preview = FFmpegStream.get_projection(image, config)
422437

423438
preview = self.drawText(preview, "Press 'q' to use current selected region of interest)",
424439
y = 50, color = (255, 0, 0))
@@ -433,10 +448,10 @@ def get_projection_parameter(self, image :np.ndarray) -> None:
433448
selected = True
434449
break
435450
elif pressed_key == "'w'":
436-
parameter.phi = min((80, parameter.phi + 5))
451+
config['parameter']['phi'] = min((80, config['parameter']['phi'] + 5))
437452
parameter_changed = True
438453
elif pressed_key == "'s'":
439-
parameter.phi = max((-80, parameter.phi - 5))
454+
config['parameter']['phi'] = max((-80, config['parameter']['phi'] - 5))
440455
parameter_changed = True
441456

442457
if cv2.waitKey(1) in [ord('q')]: break
@@ -448,7 +463,7 @@ def get_projection_parameter(self, image :np.ndarray) -> None:
448463
cv2.waitKey(1)
449464
except: pass
450465

451-
return parameter
466+
return config
452467

453468

454469
def get_bbox(self, image: np.ndarray, txt: str) -> tuple:
@@ -514,18 +529,45 @@ def get_first_frame(self) -> np.ndarray:
514529
return first_frame
515530

516531

532+
def get_flat_projection_config(self,
533+
first_frame :np.ndarray) -> dict:
534+
""" Get the flat config parameter
535+
536+
Args:
537+
first_frame (np.ndarray): opencv image
538+
539+
Returns:
540+
dict: config
541+
"""
542+
h, w = first_frame.shape[:2]
543+
config = PROJECTION[self.params.projection]
544+
545+
if config['parameter']['height'] == -1:
546+
scaling = config['parameter']['width'] / float(w)
547+
config['parameter']['height'] = round(h * scaling)
548+
elif config['parameter']['width'] == -1:
549+
scaling = config['parameter']['height'] / float(h)
550+
config['parameter']['width'] = round(w * scaling)
551+
552+
return config
553+
554+
517555
def tracking(self) -> str:
518556
""" Tracking function to track the features in the video
519557
520558
Returns:
521559
str: a process status message e.g. 'end of video reached'
522560
"""
523561
first_frame = FFmpegStream.get_frame(self.params.video_path, self.params.start_frame)
524-
projection_parameter = self.get_projection_parameter(first_frame)
562+
563+
if 'vr' in self.params.projection.split('_'):
564+
projection_config = self.get_vr_projection_config(first_frame)
565+
else:
566+
projection_config = self.get_flat_projection_config(first_frame)
525567

526568
video = FFmpegStream(
527569
video_path = self.params.video_path,
528-
parameter = projection_parameter,
570+
config = projection_config,
529571
start_frame = self.params.start_frame
530572
)
531573

@@ -553,7 +595,7 @@ def tracking(self) -> str:
553595
frame_num += 1
554596

555597
if frame is None:
556-
status = 'Reach a corrupt video frame'
598+
status = 'Reach a corrupt video frame' if video.isOpen() else 'End of video reached'
557599
break
558600

559601
# NOTE: Use != 1 to ensure that the first difference is equal to the folowing (reqired for the interpolation)
@@ -607,7 +649,6 @@ def tracking(self) -> str:
607649
wait = cycle_time_in_ms - (time.time() - cycle_start)*float(1000)
608650
if wait > 0: time.sleep(wait/float(1000))
609651

610-
611652
video.stop()
612653
self.logger.info(status)
613654
self.calculate_score()

funscript_editor/algorithms/videotracker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def run(self) -> None:
7272
frame_heigt, frame_width = self.first_frame.shape[:2]
7373

7474
if self.limit_searchspace:
75-
# Determine the tracking ROI, assume we have 3d Side by Side static VR video
75+
# TODO Determine the tracking ROI, assume we have 3d Side by Side static VR video
7676
# The movement is mostly up-down, so we can restrict left and right more than up and down
7777
dh, dw = int(frame_heigt/12), int(frame_width/38)
7878
else:
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
# 3D Side-By-Side VR Video
3+
vr_he_sbs:
4+
video_filter: 'v360=input=he:in_stereo=sbs:pitch=${phi}:output=flat:d_fov=${fov}:w=${width}:h=${height}'
5+
parameter:
6+
height: 720
7+
width: 1240
8+
fov: 100
9+
phi: -45
10+
11+
flat:
12+
video_filter: 'scale=${width}:${height}'
13+
parameter:
14+
height: 720
15+
width: -1

funscript_editor/config/settings.yaml

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,15 @@ use_zoom: False
77
# Set the desired zoom value which will be used when the zoom function is activated.
88
zoom_factor: 4.0
99

10-
# Convert video in normal perspective view before apply tracking. This should improve the
11-
# tracking at the border of videos, because there is the distortion very high.
12-
use_equirectangular: True
13-
14-
# Scaling for the equirectangular preview window
15-
equirectangular_scaling: 1.0
16-
1710
# Specify the tracking direction. Allowed values are `'x'` and `'y'`.
1811
tracking_direction: 'y'
1912

20-
# Specify the scaling method for the video before apply tracking and the preview window size. Allowed
21-
# values are 'auto' and 'config'. 'auto': try to calculate the scaling depending on your screen
22-
# resolution. If you have a very high screen resolution e.g. 8K Monitor this option will strongly slow
23-
# down the tracking speed, because all videos are scaled up/down to 8K before tracking. If you set 'config'
24-
# the scaling form `video_scaling.json` will be used. You can adjust this config to your like as
25-
# described in the documentation on github.
26-
scaling_method: 'config'
27-
2813
# Limit the max player speed in the tracking preview window (0 = disable limit)
2914
max_playback_fps: 0
15+
16+
# TODO
17+
preview_scaling: 1.0
18+
19+
# TODO
20+
# projection: 'vr_he_sbs'
21+
projection: 'flat'

funscript_editor/config/video_scaling.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)