import cv2 from SpaceXtract.general_extract import BaseExtract, RelativeExtract import random class Util(): def __init__(self, extractor: BaseExtract): self.extractor = extractor def search_switch(self, cap, key, thresh=0.5): left = 0 right = cap.get(cv2.CAP_PROP_FRAME_COUNT) - 1 cap.set(cv2.CAP_PROP_POS_FRAMES, int((right + left) / 2)) while right > left + 1: _, frame = cap.read() image = self.extractor.prepare_frame(frame, self.extractor.image_dict[key][0]) if not self.extractor.exists(image, self.extractor.image_dict[key][1][0], thresh): left = int((right + left) / 2) else: right = int((right + left) / 2) cap.set(cv2.CAP_PROP_POS_FRAMES, int((right + left) / 2)) cap.set(cv2.CAP_PROP_POS_FRAMES, left) return left def skip_from_launch(self, cap, key, time, thresh=None): """ Move the capture to T+time (time can be negative) and returns the frame index. :param cap: OpenCV capture :param time: delta time from launch to skip to :return: index of requested frame """ if thresh is None: thresh = self.extractor.image_dict[key][2] number_of_frames = int(cap.get(cv2.CAP_PROP_FPS) * time) + self.search_switch(cap, key, thresh) number_of_frames = max(number_of_frames, 0) number_of_frames = min(number_of_frames, cap.get(cv2.CAP_PROP_FRAME_COUNT)) cap.set(cv2.CAP_PROP_POS_FRAMES, number_of_frames) return number_of_frames def find_anchor(self, cap, start=0, end=1, maxiter=10): if not isinstance(self.extractor, RelativeExtract): return False original_location = cap.get(cv2.CAP_PROP_POS_FRAMES) for i in range(maxiter): pos = random.uniform(start, end) cap.set(cv2.CAP_PROP_POS_FRAMES, pos*cap.get(cv2.CAP_PROP_FRAME_COUNT)) _, frame = cap.read() if self.extractor.prepare_image_dict(frame): return True cap.set(cv2.CAP_PROP_POS_FRAMES, original_location) return False def get_template_distance(self, pos_list): return [pos_list[i+1] - pos_list[i] for i in range(len(pos_list)-1)] def decimal_point_conversion(self, digit_pos_list): """ Change the altitude value according to the position of the decimal point. :param digit_pos_list: a list of the digits with their position. :param altitude: Value of altitude :return: The altitude after decimal digit conversion. """ distances = self.get_template_distance(digit_pos_list) return distances[-2] > distances[-1] * 1.3 def play_until_anchor_found(self, cap, session, interval=5): _, frame = cap.read() while not session.prepare_image_dict(frame): for i in range(interval*30): _, frame = cap.read() if cv2.waitKey(1) & 0xff == ord('q'): return cv2.imshow('frame', frame) def rtnd(number, n): """ Round number to a max of n digits after the decimal point :param number: Given number :param n: Requested number of digits after the decimal points :return: number with a max of n digits after the decimal point """ return int(number * 10 ** n) / 10 ** n def time_to_seconds(time): """ Convert the time to seconds :param time: A number that represent the time. ex. 011731 --> 1 hour, 17 minutes and 31 seconds :return: The number in seconds. """ seconds = time % 100 minutes = int(time / 100) % 100 hours = int(time / 10000) return seconds + 60*minutes + 60*60*hours def to_float(num): try: return float(num) except ValueError: return 0