| |
| import cv2 |
| import numpy |
| import threading |
| import os |
| import struct |
| import concurrent.futures |
| from concurrent.futures import ThreadPoolExecutor, wait |
|
|
| _imread_executor_pool = ThreadPoolExecutor(max_workers=16) |
|
|
| class UnknownImageFormat(Exception): |
| pass |
|
|
|
|
| def quick_imsize(file_path): |
| """Return (width, height) for a given img file content - no external |
| dependencies except the os and struct modules from core |
| |
| Parameters |
| ---------- |
| file_path |
| |
| Returns |
| ------- |
| |
| """ |
| size = os.path.getsize(file_path) |
| with open(file_path, 'rb') as input: |
| height = -1 |
| width = -1 |
| data = input.read(25) |
|
|
| if (size >= 10) and data[:6] in ('GIF87a', 'GIF89a'): |
| |
| w, h = struct.unpack("<HH", data[6:10]) |
| width = int(w) |
| height = int(h) |
| elif ((size >= 24) and data.startswith('\211PNG\r\n\032\n') |
| and (data[12:16] == 'IHDR')): |
| |
| w, h = struct.unpack(">LL", data[16:24]) |
| width = int(w) |
| height = int(h) |
| elif (size >= 16) and data.startswith('\211PNG\r\n\032\n'): |
| |
| w, h = struct.unpack(">LL", data[8:16]) |
| width = int(w) |
| height = int(h) |
| elif (size >= 2) and data.startswith('\377\330'): |
| |
| msg = " raised while trying to decode as JPEG." |
| input.seek(0) |
| input.read(2) |
| b = input.read(1) |
| try: |
| while (b and ord(b) != 0xDA): |
| while (ord(b) != 0xFF): b = input.read(1) |
| while (ord(b) == 0xFF): b = input.read(1) |
| if (ord(b) >= 0xC0 and ord(b) <= 0xC3): |
| input.read(3) |
| h, w = struct.unpack(">HH", input.read(4)) |
| break |
| else: |
| input.read(int(struct.unpack(">H", input.read(2))[0]) - 2) |
| b = input.read(1) |
| width = int(w) |
| height = int(h) |
| except struct.error: |
| raise UnknownImageFormat("StructError" + msg) |
| except ValueError: |
| raise UnknownImageFormat("ValueError" + msg) |
| except Exception as e: |
| raise UnknownImageFormat(e.__class__.__name__ + msg) |
| else: |
| raise UnknownImageFormat( |
| "Sorry, don't know how to get information from this file." |
| ) |
|
|
| return width, height |
|
|
|
|
| def cv2_read_img_resize(path, read_storage, resize_storage, frame_size, grayscale): |
| if grayscale: |
| read_storage[:] = cv2.imread(path, 0) |
| else: |
| read_storage[:] = cv2.imread(path) |
| resize_storage[:] = cv2.resize(read_storage, frame_size, interpolation=cv2.INTER_LINEAR) |
|
|
|
|
| def cv2_read_img(path, read_storage, grayscale): |
| if grayscale: |
| read_storage[:] = cv2.imread(path, 0) |
| else: |
| read_storage[:] = cv2.imread(path) |
|
|
|
|
| def quick_read_frames(path_list, im_w=None, im_h=None, resize=False, frame_size=None, grayscale=True): |
| """Multi-thread Frame Loader |
| |
| Parameters |
| ---------- |
| path_list : list |
| resize : bool, optional |
| frame_size : None or tuple |
| |
| Returns |
| ------- |
| |
| """ |
| img_num = len(path_list) |
| for i in range(img_num): |
| if not os.path.exists(path_list[i]): |
| print(path_list[i]) |
| raise IOError |
| if im_w is None or im_h is None: |
| im_w, im_h = quick_imsize(path_list[0]) |
| if grayscale: |
| read_storage = numpy.empty((img_num, im_h, im_w), dtype=numpy.uint8) |
| else: |
| read_storage = numpy.empty((img_num, im_h, im_w, 3), dtype=numpy.uint8) |
| if resize: |
| if grayscale: |
| resize_storage = numpy.empty((img_num, frame_size[0], frame_size[1]), dtype=numpy.uint8) |
| else: |
| resize_storage = numpy.empty((img_num, frame_size[0], frame_size[1], 3), dtype=numpy.uint8) |
| if img_num == 1: |
| cv2_read_img_resize(path=path_list[0], read_storage=read_storage[0], |
| resize_storage=resize_storage[0], |
| frame_size=frame_size, grayscale=grayscale) |
| else: |
| future_objs = [] |
| for i in range(img_num): |
| obj = _imread_executor_pool.submit(cv2_read_img_resize, |
| path_list[i], |
| read_storage[i], |
| resize_storage[i], frame_size, grayscale) |
| future_objs.append(obj) |
| wait(future_objs) |
| if grayscale: |
| resize_storage = resize_storage.reshape((img_num, 1, frame_size[0], frame_size[1])) |
| else: |
| resize_storage = resize_storage.transpose((0, 3, 1, 2)) |
| return resize_storage[:, ::-1, ...] |
| else: |
| if img_num == 1: |
| cv2_read_img(path=path_list[0], read_storage=read_storage[0], grayscale=grayscale) |
| else: |
| future_objs = [] |
| for i in range(img_num): |
| obj = _imread_executor_pool.submit(cv2_read_img, path_list[i], read_storage[i], grayscale) |
| future_objs.append(obj) |
| wait(future_objs) |
| if grayscale: |
| read_storage = read_storage.reshape((img_num, 1, im_h, im_w)) |
| else: |
| read_storage = read_storage.transpose((0, 3, 1, 2)) |
| return read_storage[:, ::-1, ...] |