A Simple HDR Implementation on OpenCV Python | by Felipe Cunha | Towards Data Science

HDR images encompass the information of multiple pictures with different exposures. In a scene which the source of light is uneven, a single shot may overexpose certain areas of the image and details will be lost due to elevated brightness. Conversely, this picture may also present underexposed areas which will also lead to information loss.
To create an HDR image you will need:
Take pictures with different exposures. Minimum of 2, generally 3, you can use more than 3 images but it will take a lot of CPU resources.Align the images. Even if you use a tripod you will need to perform this step (we are talking about pixel level alignment). Not properly aligning your image will lead to artifacts and ‘ghosts’ in your HDR image.Merge the aligned images into one.Perform tone mapping on the merged image. In nature the minimum possible brightness is zero but the maximum is not limited to 255, in fact there is no limit to it, it can be infinity. For this reason we need to map the image obtained in the third step to a (0, 255) range. This can be achieved with tone mapping.
Take pictures with different exposures. Minimum of 2, generally 3, you can use more than 3 images but it will take a lot of CPU resources.
Align the images. Even if you use a tripod you will need to perform this step (we are talking about pixel level alignment). Not properly aligning your image will lead to artifacts and ‘ghosts’ in your HDR image.
Merge the aligned images into one.
Perform tone mapping on the merged image. In nature the minimum possible brightness is zero but the maximum is not limited to 255, in fact there is no limit to it, it can be infinity. For this reason we need to map the image obtained in the third step to a (0, 255) range. This can be achieved with tone mapping.
import cv2 as cvimport numpy as np# Loading exposure images into a listimg_fn = [r"C:\Users\felipe.cunha\Documents\venv\HDRTest\100.jpg", r"C:\Users\felipe.cunha\Documents\venv\HDRTest\250.jpg", r"C:\Users\felipe.cunha\Documents\venv\HDRTest\500.jpg"]img_list = [cv.imread(fn) for fn in img_fn]exposure_times = np.array([100, 250, 500], dtype=np.float32)# Merge exposures to HDR imagemerge_debevec = cv.createMergeDebevec()hdr_debevec = merge_debevec.process(img_list, times=exposure_times.copy())merge_robertson = cv.createMergeRobertson()hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy())# Tonemap HDR imagetonemap1 = cv.createTonemap(gamma=2.2)res_debevec = tonemap1.process(hdr_debevec.copy())# Exposure fusion using Mertensmerge_mertens = cv.createMergeMertens()res_mertens = merge_mertens.process(img_list)# Convert datatype to 8-bit and saveres_debevec_8bit = np.clip(res_debevec*255, 0, 255).astype('uint8')res_mertens_8bit = np.clip(res_mertens*255, 0, 255).astype('uint8')cv.imwrite(r"C:\Users\felipe.cunha\Documents\venv\HDRTest\ldr_debevec.jpg", res_debevec_8bit)cv.imwrite(r"C:\Users\felipe.cunha\Documents\venv\HDRTest\fusion_mertens.jpg", res_mertens_8bit)
We’ve covered the very basics of HDR. This technique is specially helpful in situations that you need to located features in a large field of view that has under and overexposed areas.
I hope this can help you with your computer vision projects.
Let me know in the comments if you would like a more in depth article about this topic.