'How to obtain path from ZipFile objects that could be passed into OpenCV?

I would like to pass the image file into OpenCV to create a NumPy array without unzipping it.

My code looks like this:

zip_file = r'D:\Folder\small_img.zip'

with zipfile.ZipFile(zip_file) as zip:
    for info in zip.infolist():
        path_to_image = os.path.abspath(info.filename)
        zip_img = zip.open(info.filename)
        pil_img = Image.open(zip_img).convert('RGB')
        # cv_img = cv.imread(*)

The place where I put a * is what I'm not sure what to pass in. I have created a few variables of class Pillow Image (pil_img), and ZipFileExt (zip_img). I understand that cv2.imread only accepts a path. So, I have tried to pass in a path name, however I have not de-zipped the zip file, hence I also tried to create a absolute path (path_to_image) that looks like ('D:\Folder\File1.jpg'), and a file name (info.filename) that looks like (File1.jpg).

However, most of them render an error message:

TypeError: Can't convert object of type 'Image' to 'str' for 'filename'

or

TypeError: Can't convert object of type 'ZipExtFile' to 'str' for 'filename'

Or, in the case where I pass in path_to_image or info.filename, it returns None.

Anyone knows what I could pass into cv2.imread to get the NumPy array?



Solution 1:[1]

There's cv2.imdecode for that purpose:

import cv2
import numpy as np
import zipfile

with zipfile.ZipFile('images.zip') as zf:
    for info in zf.infolist():
        zip_img = zf.open(info.filename)
        cv_img = cv2.imdecode(np.frombuffer(zip_img.read(), dtype=np.uint8),
                              cv2.IMREAD_UNCHANGED)

On the ZipExtFile object obtained from zipfile.ZipFile.open, you can call read to get the raw bytes. You then need np.frombuffer to get a proper input for cv2.imdecode.

If you (also) need the Pillow Image object, you could also simply cast that one to some NumPy array, but have to keep in mind to correct the ordering from RGB (Pillow) to BGR (OpenCV):

import cv2
import numpy as np
from PIL import Image
import zipfile

with zipfile.ZipFile('images.zip') as zf:
    for info in zf.infolist():
        zip_img = zf.open(info.filename)
        pil_img = Image.open(zip_img)
        cv_img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.19041-SP0
Python:        3.9.1
PyCharm:       2021.1.1
NumPy:         1.20.2
OpenCV:        4.5.1
Pillow:        8.2.0
----------------------------------------

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 HansHirse