0

I'm looking for an efficient way to efficiently gamma-blend images.

While regular (additive) blend of pixels A and B with a factor r is expressed as this:

C = (1-r) A + r B

Gamma (multiplicative) blend is done as follows:

C = A^(1-r) B^r

This would require a way to raise a pixel channels to a non-integer power, a bit like a gamma correction.

Since I have a large batch of 4K images to process, I need this be done efficiently (without looping through all pixels and performing the computation individually).

Thanks!

Kevin Workman
  • 41,537
  • 9
  • 68
  • 107
  • Welcome to SO. Unfortunately this isn't a discussion forum or tutorial. Please take the time to read [ask] and the other links on that page. – wwii Feb 11 '18 at 17:59
  • Possible duplicate of [Iterating a function over the RGB values of individual pixels](https://stackoverflow.com/questions/22800049/iterating-a-function-over-the-rgb-values-of-individual-pixels) – wwii Feb 11 '18 at 18:02
  • 1
    To do the computation efficiently, I think you'll need some other image processing or number crunching tool like NumPy -- not just PIL. – unutbu Feb 11 '18 at 18:09
  • For example, [this does additive blending](https://stackoverflow.com/a/3375291/190597), but it would not be hard to modify it to do multiplicative blending. – unutbu Feb 11 '18 at 18:20
  • OK, I got the solution as follows: Convert the image as a numpy array, and perform whole-array mathematical operations, whatever needed... – Pascal Mount Feb 11 '18 at 21:19
  • 2
    @PascalMount Post this as the answer and accept it, it sounds like a good solution. – Michiel Overtoom Feb 12 '18 at 08:03

1 Answers1

0

Posting an implementation of the solution @Pascal Mount mentioned in the comments he used as he has yet to post his:

import numpy as np

def blend_gamma_mul(img_A, img_B, r):
    arr_A = np.array(img_A)
    arr_B = np.array(img_B)
    arr_C = arr_A**(1-r) * arr_B**r
    return Image.fromarray(np.array(arr_C, dtype=np.uint8))

Use the function like so:

from PIL import Image

img_A = Image.open("A.jpg")
img_B = Image.open("B.jpg")
img_C = blend_gamma_mul(img_A, img_B, 0.7)
img_C.save("C.jpg")

Took 3.47s on my computer to blend two 4k images.

freshpasta
  • 556
  • 2
  • 11