-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added ability to correct upload video with a rotation record in the metadata #2218
Changes from all commits
315409d
0134e56
0fd7af3
9ea48f5
c9768a7
a31d621
cb530df
5720a6e
60046f3
347621a
188df45
fb9207b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
from collections import OrderedDict | ||
import hashlib | ||
import os | ||
from cvat.apps.engine.utils import rotate_image | ||
|
||
class WorkWithVideo: | ||
def __init__(self, **kwargs): | ||
|
@@ -24,7 +25,6 @@ def _get_video_stream(self, container): | |
video_stream.thread_type = 'AUTO' | ||
return video_stream | ||
|
||
|
||
class AnalyzeVideo(WorkWithVideo): | ||
def check_type_first_frame(self): | ||
container = self._open_video_container(self.source_path, mode='r') | ||
|
@@ -76,7 +76,17 @@ def get_task_size(self): | |
|
||
@property | ||
def frame_sizes(self): | ||
container = self._open_video_container(self.source_path, 'r') | ||
frame = next(iter(self.key_frames.values())) | ||
if container.streams.video[0].metadata.get('rotate'): | ||
frame = av.VideoFrame().from_ndarray( | ||
rotate_image( | ||
frame.to_ndarray(format='bgr24'), | ||
360 - int(container.streams.video[0].metadata.get('rotate')) | ||
), | ||
format ='bgr24' | ||
) | ||
self._close_video_container(container) | ||
return (frame.width, frame.height) | ||
|
||
def check_key_frame(self, container, video_stream, key_frame): | ||
|
@@ -150,6 +160,14 @@ def decode_needed_frames(self, chunk_number, db_data): | |
if frame_number < start_chunk_frame_number: | ||
continue | ||
elif frame_number < end_chunk_frame_number and not ((frame_number - start_chunk_frame_number) % step): | ||
if video_stream.metadata.get('rotate'): | ||
frame = av.VideoFrame().from_ndarray( | ||
rotate_image( | ||
frame.to_ndarray(format='bgr24'), | ||
360 - int(container.streams.video[0].metadata.get('rotate')) | ||
), | ||
format ='bgr24' | ||
) | ||
yield frame | ||
elif (frame_number - start_chunk_frame_number) % step: | ||
continue | ||
|
@@ -177,6 +195,14 @@ def frame_sizes(self): | |
container.seek(offset=next(iter(self.key_frames.values())), stream=video_stream) | ||
for packet in container.demux(video_stream): | ||
for frame in packet.decode(): | ||
if video_stream.metadata.get('rotate'): | ||
frame = av.VideoFrame().from_ndarray( | ||
rotate_image( | ||
frame.to_ndarray(format='bgr24'), | ||
360 - int(container.streams.video[0].metadata.get('rotate')) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a couple of questions here:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
string of rotation angle
this is analogue
I checked for some values like 60, 90, 180, 270.. and in such cases - yes |
||
), | ||
format ='bgr24' | ||
) | ||
self._close_video_container(container) | ||
return (frame.width, frame.height) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
# SPDX-License-Identifier: MIT | ||
|
||
import ast | ||
import cv2 as cv | ||
from collections import namedtuple | ||
import importlib | ||
import sys | ||
|
@@ -74,3 +75,16 @@ def av_scan_paths(*paths): | |
res = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
if res.returncode: | ||
raise ValidationError(res.stdout) | ||
|
||
def rotate_image(image, angle): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we support rotation which isn't multiply pi/2 by an integer? Is it a real case to rotate a frame by 30 degrees? Is it possible at all? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Artificially (write the desired value in the metadata) you can create such a video. |
||
height, width = image.shape[:2] | ||
image_center = (width/2, height/2) | ||
matrix = cv.getRotationMatrix2D(image_center, angle, 1.) | ||
abs_cos = abs(matrix[0,0]) | ||
abs_sin = abs(matrix[0,1]) | ||
bound_w = int(height * abs_sin + width * abs_cos) | ||
bound_h = int(height * abs_cos + width * abs_sin) | ||
matrix[0, 2] += bound_w/2 - image_center[0] | ||
matrix[1, 2] += bound_h/2 - image_center[1] | ||
matrix = cv.warpAffine(image, matrix, (bound_w, bound_h)) | ||
return matrix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code duplication?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No