-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcv2utils.py
139 lines (115 loc) · 5.4 KB
/
cv2utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""
# a: zak-45
# d: 23/08/2024
# v: 1.0.0
#
# CV2Utils
#
# CAST utilities
#
# Image utilities
# cv2 thumb
#
"""
import cv2
import os
import numpy as np
from configmanager import ConfigManager
cfg_mgr = ConfigManager(logger_name='WLEDLogger.cv2utils')
class VideoThumbnailExtractor:
"""
Extract thumbnails from a video or image file.
thumbnail_width: 160 by default
get_thumbnails: return a list of numpy arrays (RGB)
# Usage
video_path = "path/to/your/video.mp4"
extractor = VideoThumbnailExtractor(video_path)
extractor.extract_thumbnails(times_in_seconds=[10, 20, 30]) # Extract thumbnails at specified times
thumbnail_frames = extractor.get_thumbnails()
for i, thumbnail_frame in enumerate(thumbnail_frames):
if thumbnail_frame is not None:
# Display the thumbnail using OpenCV
cv2.imshow(f'Thumbnail {i+1}', thumbnail_frame)
cv2.waitKey(0)
cv2.destroyAllWindows()
else:
print(f"No thumbnail extracted at time {i}.")
"""
def __init__(self, media_path, thumbnail_width=160):
self.media_path = media_path
self.thumbnail_width = thumbnail_width
self.thumbnail_frames = []
def is_image_file(self):
# Check if the file extension is an image format
image_extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff']
_, ext = os.path.splitext(self.media_path)
return ext.lower() in image_extensions
def is_video_file(self):
# Check if the file can be opened as a video
cap = cv2.VideoCapture(self.media_path)
if not cap.isOpened():
return False
ret, _ = cap.read()
cap.release()
return ret
async def extract_thumbnails(self, times_in_seconds=None):
if times_in_seconds is None:
times_in_seconds = [5]
if self.is_image_file():
self.extract_thumbnails_from_image()
elif self.is_video_file():
await self.extract_thumbnails_from_video(times_in_seconds)
else:
# Provide blank frames if the file is not a valid media file
self.thumbnail_frames = [self.create_blank_frame() for _ in times_in_seconds]
cfg_mgr.logger.warning(f"{self.media_path} is not a valid media file. Generated blank frames.")
def extract_thumbnails_from_image(self):
image = cv2.imread(self.media_path)
if image is not None:
# Resize the image to the specified thumbnail width while maintaining aspect ratio
height, width, _ = image.shape
aspect_ratio = height / width
new_height = int(self.thumbnail_width * aspect_ratio)
resized_image = cv2.resize(image, (self.thumbnail_width, new_height))
self.thumbnail_frames = [resized_image] # Single thumbnail for images
cfg_mgr.logger.debug(f"Thumbnail extracted from image: {self.media_path}")
else:
self.thumbnail_frames = [self.create_blank_frame()]
cfg_mgr.logger.error("Failed to read image. Generated a blank frame.")
async def extract_thumbnails_from_video(self, times_in_seconds):
cap = cv2.VideoCapture(self.media_path)
if not cap.isOpened():
cfg_mgr.logger.error(f"Failed to open video file: {self.media_path}")
self.thumbnail_frames = [self.create_blank_frame() for _ in times_in_seconds]
return
fps = cap.get(cv2.CAP_PROP_FPS)
video_length = cap.get(cv2.CAP_PROP_FRAME_COUNT) / fps
for time_in_seconds in times_in_seconds:
if time_in_seconds > video_length:
cfg_mgr.logger.warning(f"Specified time {time_in_seconds}s is greater than video length {video_length}s. "
f"Setting time to {video_length}s.")
time_in_seconds = video_length
frame_number = int(time_in_seconds * fps)
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
success, frame = cap.read()
if success:
# Resize the frame to the specified thumbnail width while maintaining aspect ratio
height, width, _ = frame.shape
aspect_ratio = height / width
new_height = int(self.thumbnail_width * aspect_ratio)
resized_frame = cv2.resize(frame, (self.thumbnail_width, new_height))
self.thumbnail_frames.append(resized_frame)
cfg_mgr.logger.debug(f"Thumbnail extracted at {time_in_seconds}s.")
else:
cfg_mgr.logger.error("Failed to extract frame.")
self.thumbnail_frames.append(self.create_blank_frame())
cap.release()
def create_blank_frame(self):
# Create a blank frame with the specified thumbnail width and a default height
height = int(self.thumbnail_width * 9 / 16) # Assuming a 16:9 aspect ratio for the blank frame
blank_frame = np.random.randint(0, 256, (height, self.thumbnail_width, 3), dtype=np.uint8)
# blank_frame = np.zeros((height, self.thumbnail_width, 3), np.uint8)
# blank_frame[:] = (255, 255, 255) # White blank frame
return blank_frame
def get_thumbnails(self):
return [cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) for frame in self.thumbnail_frames]