Source code for colordetect.video_color_detect

"""
.. _module_VideoColor:
Module VideoColor
==================
Defines VideoColor class

Usage:

>>> from colordetect import VideoColor
>>> user_video = VideoColor("<path_to_video>")
# where frame_color_count is the target most dominant colors to be found. Default set to 5
>>> colors =  user_video.get_video_frames(frame_color_count=7)
>>> colors
# alternatively shorten the dictionary to get a specific number of sorted colors from the whole lot
>>> from colordetect import col_share
>>> top_colors = col_share.sort_order(object_description=colors, key_count=8)
"""

import datetime
import sys

import cv2

from . import col_share
from .color_detect import ColorDetect


[docs]class VideoColor: """ Detect and recognize the number of colors in a video """ def __init__(self, video): # super().__init__(video) self.video_file = cv2.VideoCapture(video) self.color_description = {}
[docs] def get_video_frames( self, frame_color_count: int = 5, color_format: str = "rgb", progress: bool = False, ) -> dict: """ .. _get_video_frames: get_video_frames ---------------- Get image frames and their colors from the video Parameters ---------- frame_color_count: int The number of most dominant colors to be obtained from a single frame color_format:str The format to return the color in. Options * hsv - (60°,100%,100%) * rgb - rgb(255, 255, 0) for yellow * hex - #FFFF00 for yellow :return: color_description dictionary """ if type(frame_color_count) != int: raise TypeError( f"frame_color_count has to be an integer. Provided {type(frame_color_count)} " ) color_format_options = ["rgb", "hex", "hsv"] if color_format not in color_format_options: raise ValueError(f"Invalid color format: {color_format}") if type(progress) != bool: raise TypeError(f"Progress should be a boolean. Provided {type(progress)}") count = 0 total_frame_count = self.video_file.get(cv2.CAP_PROP_FRAME_COUNT) while self.video_file.isOpened(): # how often to extract colors from video frames. Defaults to every 1 second (success, image) = self._get_frame(time=count * 1000) if not success: break # Video is complete image_object = ColorDetect(image) colors = image_object.get_color_count( color_count=frame_color_count, color_format=color_format ) # merge dictionaries as they are created self.color_description = {**self.color_description, **colors} count += 1 current_frame_num = self.video_file.get(cv2.CAP_PROP_POS_FRAMES) if progress: col_share.progress_bar( position=current_frame_num, total_length=total_frame_count ) if progress: col_share.progress_bar( position=total_frame_count, total_length=total_frame_count ) # Cater for video with extra millis at the end that don't sum upto a full sec, and are thus skipped self.video_file.release() print("\n") return self.color_description
def _get_frame(self, time: int = 1000) -> tuple: """ .. _get_frame_color: get_frame_color ---------------- Get image frame at specific time in a video Parameters ---------- time: int Time to get color from in parsed image :return: () """ # read file every x time in milliseconds self.video_file.set(cv2.CAP_PROP_POS_MSEC, time) success, image = self.video_file.read() return (success, image)
[docs] def get_time_frame_color( self, color_count: int = 5, color_format: str = "rgb", time: int = 1000 ) -> tuple: """ .. _get_time_frame_color: get_time_frame_color ---------------- Get color from a specific time in the video Parameters ---------- time: int Time to get color from in video in milliseconds color_count: int Number of colors to return at the given time frame color_format:str The format to return the color in. Options * hsv - (60°,100%,100%) * rgb - rgb(255, 255, 0) for yellow * hex - #FFFF00 for yellow :return: (image, color_description) """ color_format_options = ["rgb", "hex", "hsv"] if color_format not in color_format_options: raise ValueError(f"Invalid color format: {color_format}") if type(color_count) != int: raise TypeError( f"color_count to extract has to be an integer. Provided {type(color_count)} " ) if time < 1: raise ValueError("Cannot give negative time to extract color from") if self._get_video_length() < time: raise ValueError( f"The time given is longer than the video parsed. Provided {time} while length of video: {self._get_video_length()}" ) (success, image) = self._get_frame(time) if success: image_object = ColorDetect(image) colors = image_object.get_color_count( color_count=color_count, color_format=color_format ) self.color_description = colors self.video_file.release() return (image_object, self.color_description)
def _get_video_length(self) -> int: """ .. _get_video_length: _get_video_length ---------------- get the length of a video return: the length of a video """ frames = self.video_file.get(cv2.CAP_PROP_FRAME_COUNT) fps = self.video_file.get(cv2.CAP_PROP_FPS) return round(frames / fps) * 1000