0

I want to add/merge an RGBA gradient to a black and white (b/w) RGB image to be able to adjust the "brightness" of the b/w image along one axes.

The gradient image is supposed to be a white to transparent gradient along the horizontal axes. The "whiteness" is controlled by value, while value_min is supposed to be the minimal "whiteness" value reached. edge is the x-value the linear gradient should reach 0 or value_min (in which case value_min was reached earlier).

And here is an example input image, gradient and output image.

example_inputgradientexample_output

Executed as show_pre_pic(value=255, value_min=0, edge=100)

The problem with the version of the program which produced this output is, that it does not only increase the brightness along the gradient but also decreases the brightness once it reaches the "edge" of the gradient.

I've already worked out some code but it doesn't work and just crashes the PyQt application it is implemented in (and the Spyder Kernel). The PyQt app worked before the introduction of the alpha channel of the gradient and the conversion of image to RGBA. The image is converted to RGBA because cv.addWeighted() needs both images to be the same size and amount of channels (gradient would have 4 channels, image has 3).

For my first approach, I followed this answer as a guideline but it didn't work.

Here is the last working version of the code, without the introduction of an alpha channel & transparency:

import cv2 as cv
import numpy as np

def show_pre_pic(value, value_min, edge):
    #load image
    image = cv.imread("example.jpg")
    #create gradient
    gradient = create_gradient(image.shape[1], image.shape[0], value, value_min, edge)

    #merge image with gradient
    image = cv.addWeighted(image, 0.5, gradient, 0.5, 0)

    #save gradient and image
    cv.imwrite("example_output.png", image)
    cv.imwrite("gradient.png", gradient)

def create_gradient(width, height, value, value_min, edge):

    # Create blank image
    gradient = np.zeros((height, width, 3), np.uint8)

    #go through all lines of pixels horizontally
    for x in range(0, width):
        #if value is smaller than value_min make all pixels value_min
        if value <= value_min:
            gradient[0:height,x] = (value_min,value_min,value_min)
        #make all lines of pixels = value    
        else:
            gradient[0:height,x] = (value, value, value)
            #decrease value so that it reaches 0 by x = edge
            value = value - (255/edge)

    return gradient

if __name__ == "__main__":
    show_pre_pic(255, 0, 100)

In the application, the values: value, value_min, and edge can be adjusted with sliders with an immediate preview. The performance wasn't a problem (yet) because the actually used images are small (8KB) and all loaded into memory(not loaded directly with cv.imread() as shown here).

GittingGud
  • 315
  • 2
  • 16
  • 1
    I'm having a hard time envisaging how your gradient is supposed to look or work. Maybe you could just show the alpha channel itself and which variables set which aspects of it and how that should affect the underlying image... – Mark Setchell Apr 04 '20 at 10:54
  • 1
    Sorry, I still don't understand. You say you want to *"add an RGBA gradient to a greyscale image"*. So, in my mind, you want to add a 4-channel image to a single channel image - how does that work? Will the answer be 5-channel? Or are you going to add the greyscale values to each of the RGBA channels? And somehow adding something is going to make the image darker - how can that be - surely the values will get larger (brighter) when you add to them? – Mark Setchell Apr 04 '20 at 11:47
  • @MarkSetchell I have my self-generated gradient which is RGBA because I need transparency and I have an image which in general is rgb (but in my specific case the rgb image is b/w). I want to use `cv.addWeighted()` to add the gradient to the image to increase the brightness of the b/w with the gradient. You can see the gradient as a mask to increase brightness, only that the mask has fading transparency to it. I will create an image that shows the operation without transparency to visualize but this will take a few minutes. – GittingGud Apr 04 '20 at 13:59
  • Sorry, I still don't understand. You have a not very tall, rather wide PNG of 796x240 pixels and a tall, narrow JPEG of 183x275 that you want to blend somehow. You show a result but I don't know if that's the correct result you want or the incorrect one. Could you please clarify and ensure you provide the correctly sized, correctly oriented input images and the corresponding correct output image? Thank you. – Mark Setchell Apr 06 '20 at 11:36
  • @MarkSetchell The gradient was for another image sorry. I've updated the gradient. The shown result is the result without transparency of the gradient, causing darkening of the right half of the output image. I want to avoid this darkening with the introduction of transparency of the gradient but this is where I don't know how to proceed. I've also updated the code to show the last working version without the transparency to avoid confusion. – GittingGud Apr 06 '20 at 12:04

0 Answers0