7

I have created a JPEG using Python OpenCV, EXIF data being lost in the process and apparently not being able to be re-added when calling imwrite (reference: Can't keep image exif data when editing it with opencv in python).

Two questions:

  1. In general, how can I write the original EXIF data/new custom metadata into a JPEG that exists in memory rather than a file?

  2. Would pillow/PIL be able to maintain the EXIF data and allow supplementary metadata to be added? As of 2013 (reference: how maintain exif data of images resizes using PIL) this did not seem possible except via a tmp file (which is not an option for me).

Thanks as ever

Konrad Rudolph
  • 506,650
  • 124
  • 909
  • 1,183
jtlz2
  • 6,105
  • 7
  • 54
  • 98

1 Answers1

12

I'm not certain I understand what you are trying to do, but I think you are trying to process an image with OpenCV and then re-insert the EXIF data you lost when OpenCV opened it...

So, hopefully you can do what you are already doing, but also open the image with PIL/Pillow and extract the EXIF data and then write it into the image processed by OpenCV.

from PIL import Image
import io

# Read your image with EXIF data using PIL/Pillow
imWithEXIF = Image.open('image.jpg')

You will now have a dict with the EXIF info in:

imWIthEXIF.info['exif']

You now want to write that EXIF data into your image you processed with OpenCV, so:

# Make memory buffer for JPEG-encoded image
buffer = io.BytesIO()

# Convert OpenCV image onto PIL Image
OpenCVImageAsPIL = Image.fromarray(OpenCVImage)

# Encode newly-created image into memory as JPEG along with EXIF from other image
OpenCVImageAsPIL.save(buffer, format='JPEG', exif=imWIthEXIF.info['exif']) 

Beware... I am assuming in the code above, that OpenCVImage is a Numpy array and that you have called cvtColor(cv2.COLOR_BGR2RGB) to go to the conventional RGB channel ordering that PIL uses rather than OpenCV's BGR channel ordering.

Keywords: Python, OpenCV, PIL, Pillow, EXIF, preserve, insert, copy, transfer, image, image processing, image-processing, dict, BytesIO, memory, in-memory, buffer.

Mark Setchell
  • 169,892
  • 24
  • 238
  • 370
  • Ah, easy as that, thank you so much! Use case is spot on - just also need the ability to add arbitrary EXIF tags if the standard supports it. – jtlz2 Jun 21 '19 at 09:31
  • clarification: `imWithExif.info` is a dictionary, and imWithExif.info["exif"] is bytes. – Jason Harrison Apr 14 '22 at 19:15