4

For a python project making heavy use of opencv/numpy/scipy, I would like to ingest a .HEIC/.HEIF image without first converting to any other format, e.g. JPEG etc.

Is there a way to do this?

This link implies not:

https://docs.opencv.org/3.0-beta/modules/imgcodecs/doc/reading_and_writing_images.html?highlight=imread#Mat%20imread(const%20String&%20filename,%20int%20flags)

but hints that enabling the build flag OPENCV_BUILD_3RDPARTY_LIBS might help. Searching for that flag turns up little.

NB: Please no PIL/Pillow unless it is the only way.

Thanks!

jtlz2
  • 7,700
  • 9
  • 64
  • 114

3 Answers3

2

You can do that with pyvips like this:

#!/usr/bin/env python3

import pyvips
import numpy as np

# map vips formats to np dtypes
format_to_dtype = {
   'uchar': np.uint8,
   'char': np.int8,
   'ushort': np.uint16,
   'short': np.int16,
   'uint': np.uint32,
   'int': np.int32,
   'float': np.float32,
   'double': np.float64,
   'complex': np.complex64,
   'dpcomplex': np.complex128,
}

# vips image to numpy array
def vips2numpy(vi):
    return np.ndarray(buffer=vi.write_to_memory(),
                  dtype=format_to_dtype[vi.format],
                  shape=[vi.height, vi.width, vi.bands])

# Open HEIC image from iPhone
vipsim = pyvips.Image.new_from_file("iPhone.heic", access='sequential')
print(f'Dimensions: {vipsim.width}x{vipsim.height}')

# Do conversion from vips image to Numpy array
na = vips2numpy(vipsim)
print(f'Numpy array dimensions: {na.shape}, dtype:{na.dtype}')

Sample Output

Dimensions: 3024x4032
Numpy array dimensions: (4032, 3024, 3), dtype:uint8
jcupitt
  • 10,213
  • 2
  • 23
  • 39
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
0

You can do that with Python Wand, which uses ImageMagick with the libheif delegate installed. Or you can simply call ImageMagick from Python using the subprocess call.

import subprocess

cmd = ['/usr/local/bin/convert','image.suffix','image.heic']

subprocess.call(cmd, shell=False)
fmw42
  • 46,825
  • 10
  • 62
  • 80
0

HEIC to PNG using OpenCV

    import numpy as np
    import cv2
    import pillow_heif
    
    heif_file = pillow_heif.open_heif("image.heic", convert_hdr_to_8bit=False, bgr_mode=True)
    np_array = np.asarray(heif_file)
    cv2.imwrite("rgb16.png", np_array)

If you do not need high bit formats, then remove convert_hdr_to_8bit parameter.

This is a simplified example to work with only a first image in a file.

P.S.: pillow_heif min supported version for this is 0.10.0