cropping for videos
This commit is contained in:
@@ -20,6 +20,8 @@ class Marker:
|
||||
self.frame_visu = []
|
||||
self.max_res = (1280, 720)
|
||||
self.min_res = (512, None)
|
||||
self.crop = [(None, None), (None, None), None]
|
||||
self.crop_click = 0
|
||||
self.forced_fps = opts.fps
|
||||
|
||||
try:
|
||||
@@ -49,6 +51,10 @@ class Marker:
|
||||
int(self.video_reader.get(cv2.CAP_PROP_FRAME_WIDTH)),
|
||||
int(self.video_reader.get(cv2.CAP_PROP_FRAME_HEIGHT)),
|
||||
]
|
||||
self.video_res_original = [
|
||||
int(self.video_reader.get(cv2.CAP_PROP_FRAME_WIDTH)),
|
||||
int(self.video_reader.get(cv2.CAP_PROP_FRAME_HEIGHT)),
|
||||
]
|
||||
video_aspect = self.video_res[0] / self.video_res[1]
|
||||
if self.video_res[0] > self.max_res[0]:
|
||||
self.video_res[0] = int(self.max_res[0])
|
||||
@@ -63,6 +69,20 @@ class Marker:
|
||||
self.video_res[1] = int(self.video_res[0] / video_aspect)
|
||||
|
||||
self.video_res = tuple(self.video_res)
|
||||
self.crop = [(0, 0), tuple(self.video_res), None]
|
||||
if self.opts.crop:
|
||||
w, h, x, y = [int(c) for c in self.opts.crop.split(":")]
|
||||
self.crop = [
|
||||
(
|
||||
int(self.video_res[0] * x / self.video_res_original[0]),
|
||||
int(self.video_res[1] * y / self.video_res_original[1]),
|
||||
),
|
||||
(
|
||||
int(self.video_res[0] * w / self.video_res_original[0]),
|
||||
int(self.video_res[1] * h / self.video_res_original[1]),
|
||||
),
|
||||
True,
|
||||
]
|
||||
self.bar_start = int(self.video_res[0] * 0.05)
|
||||
self.bar_end = int(self.video_res[0] * 0.95)
|
||||
self.bar_top = int(self.video_res[1] * 0.90)
|
||||
@@ -147,6 +167,49 @@ class Marker:
|
||||
(255, 255, 255),
|
||||
)
|
||||
|
||||
def draw_crop(self, frame):
|
||||
|
||||
if self.crop[2] is None:
|
||||
return
|
||||
p2 = (self.crop[0][0] + self.crop[1][0], self.crop[0][1] + self.crop[1][1])
|
||||
cv2.rectangle(
|
||||
frame,
|
||||
self.crop[0],
|
||||
p2,
|
||||
(0, 192, 192),
|
||||
1,
|
||||
)
|
||||
if self.crop_click == 1:
|
||||
x, y = [
|
||||
int(self.video_res_original[0] * self.crop[0][0] / self.video_res[0]),
|
||||
int(self.video_res_original[1] * self.crop[0][1] / self.video_res[1]),
|
||||
]
|
||||
self.shadow_text(
|
||||
frame,
|
||||
f"{x},{y}",
|
||||
self.crop[0],
|
||||
0.5,
|
||||
1,
|
||||
(0, 192, 192),
|
||||
)
|
||||
if self.crop_click == 2:
|
||||
x, y = [
|
||||
int(self.video_res_original[0] * self.crop[0][0] / self.video_res[0]),
|
||||
int(self.video_res_original[1] * self.crop[0][1] / self.video_res[1]),
|
||||
]
|
||||
w, h = [
|
||||
abs(int(self.video_res_original[0] * self.crop[1][0] / self.video_res[0])),
|
||||
abs(int(self.video_res_original[1] * self.crop[1][1] / self.video_res[1])),
|
||||
]
|
||||
self.shadow_text(
|
||||
frame,
|
||||
f"{w}x{h}",
|
||||
self.crop[0],
|
||||
0.5,
|
||||
1,
|
||||
(0, 192, 192),
|
||||
)
|
||||
|
||||
def draw_help(self, frame):
|
||||
|
||||
bottom = 80
|
||||
@@ -195,6 +258,7 @@ class Marker:
|
||||
mark frame
|
||||
space or click video
|
||||
pause
|
||||
a and s modify crop offset or size
|
||||
f toggle 0.5x 1x or 2x FPS
|
||||
v toggle HUD
|
||||
h toggle help
|
||||
@@ -211,6 +275,17 @@ class Marker:
|
||||
y > self.bar_top,
|
||||
)
|
||||
)
|
||||
if self.crop_click == 1:
|
||||
self.crop[0] = (x, y)
|
||||
if event == cv2.EVENT_LBUTTONDOWN:
|
||||
self.crop_click = 0
|
||||
return
|
||||
if self.crop_click == 2:
|
||||
self.crop[1] = (x - self.crop[0][0], y - self.crop[0][1])
|
||||
if event == cv2.EVENT_LBUTTONDOWN:
|
||||
self.crop_click = 0
|
||||
return
|
||||
|
||||
if event == cv2.EVENT_LBUTTONDOWN:
|
||||
if in_bar:
|
||||
click_relative = (x - self.bar_start) / (self.bar_end - self.bar_start)
|
||||
@@ -271,17 +346,48 @@ class Marker:
|
||||
print(self.get_help())
|
||||
|
||||
def print_timestamps(self):
|
||||
|
||||
if self.crop[2] is None:
|
||||
cropstr = ""
|
||||
else:
|
||||
x, y = [
|
||||
int(self.video_res_original[0] * self.crop[0][0] / self.video_res[0]),
|
||||
int(self.video_res_original[1] * self.crop[0][1] / self.video_res[1]),
|
||||
]
|
||||
w, h = [
|
||||
int(self.video_res_original[0] * self.crop[1][0] / self.video_res[0]),
|
||||
int(self.video_res_original[1] * self.crop[1][1] / self.video_res[1]),
|
||||
]
|
||||
if w < 0:
|
||||
x = x + w
|
||||
w = -w
|
||||
if h < 0:
|
||||
y = y + h
|
||||
h = -h
|
||||
cropstr = f"-filter:v crop={w}:{h}:{x}:{y} "
|
||||
self.stamps.sort()
|
||||
print("# Timestamps:")
|
||||
for i, ts in enumerate(self.stamps):
|
||||
print("# {}: {} / {}".format(i + 1, self.format_time(ts), ts))
|
||||
if len(self.stamps) == 0:
|
||||
self.stamps.append(0)
|
||||
self.stamps.append(self.frames)
|
||||
if len(self.stamps) > 0:
|
||||
print(
|
||||
'ffmpeg -ss {} -to {} -i "{}" -c copy "{}.trimmed.mp4"'.format(
|
||||
'ffmpeg -i "{}" {}-c:v mpeg2video -q:v 3 -g 1 -a copy -ss {} -to {} "{}.trimmed.mp4"'.format(
|
||||
self.opts.video.replace('"', '\\"'),
|
||||
cropstr,
|
||||
self.format_time(self.stamps[0]),
|
||||
self.format_time(self.stamps[-1]),
|
||||
os.path.splitext(self.opts.video)[0].replace('"', '\\"'),
|
||||
)
|
||||
)
|
||||
elif self.crop[0][0] is not None:
|
||||
print(
|
||||
'ffmpeg -i "{}" {}-c:v mpeg2video -q:v 3 -g 1 "{}.trimmed.mp4"'.format(
|
||||
self.opts.video.replace('"', '\\"'),
|
||||
self.opts.video.replace('"', '\\"'),
|
||||
cropstr,
|
||||
os.path.splitext(self.opts.video)[0].replace('"', '\\"'),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -350,6 +456,7 @@ class Marker:
|
||||
if (not self.paused) or self.read_next:
|
||||
self.read_next = False
|
||||
frame_visu = cv2.resize(frame.copy(), self.video_res)
|
||||
self.draw_crop(frame_visu)
|
||||
nr_time = self.nr / self.fps
|
||||
if self.show_info:
|
||||
self.draw_time(frame_visu)
|
||||
@@ -436,7 +543,12 @@ class Marker:
|
||||
|
||||
elif k & 0xFF == ord("f"): # modify FPS
|
||||
FPS_modifier = (FPS_modifier + 1) % len(FPS_modifiers)
|
||||
|
||||
elif k & 0xFF == ord("a"): # toggle crop offset
|
||||
self.crop_click = 0 if self.crop_click == 1 else 1
|
||||
self.crop[2] = True
|
||||
elif k & 0xFF == ord("s"): # toggle crop size
|
||||
self.crop_click = 0 if self.crop_click == 2 else 2
|
||||
self.crop[2] = True
|
||||
elif k & 0xFF == ord("x"): # toggle ts
|
||||
self.toggle_stamp()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user