1

I'm making a drawing program where you can later save and export your changes as an image. The non-transparent image option works perfectly, but the transparent option does not. The code I have right now is based on this post.

Whenever I draw a line in the transparent option, nothing on the image shows up. It's completely transparent.

print("Transparent:", str(transparent))
    if not transparent:
        image = np.zeros((height, width, 3), np.uint8) # initialize image for saving preferences
        image[:] = backgroundColorBGR # change background color

        for drawing in drawings: # loop through each drawing
            cv2.line(image, drawing[0], drawing[1], drawing[2], thickness = drawing[3]) # create line that user drew
        cv2.imwrite("yourimage.png", image)
    else:
        
        image = np.zeros((height, width, 4), dtype = np.uint8) # 4 channels instead of 3, for transparent images

        for drawing in drawings: # loop through each drawing
            cv2.line(image, drawing[0], drawing[1], drawing[2], thickness = drawing[3])
        cv2.imwrite("yourimage.png", image)
MmBaguette
  • 340
  • 3
  • 13
  • Try adding `color=(b,g,r,a)` to your parameters for `cv2.line()`. I mean specifically 4 values so you include transparency/alpha. Make `a` equal to 255. Or try splitting the channels and drawing on the first 3 as BGR and the last one as greyscale then recombining with `np.dstack()`. – Mark Setchell Feb 07 '21 at 23:42
  • Thank you so much for your help! Please make this an answer as I know this would help others. – MmBaguette Feb 08 '21 at 00:01
  • I haven't tested this and so I am not comfortable putting it as an answer. If you have got it working, be my guest and add your code as an answer, accept your own answer and grab the points. Good luck! – Mark Setchell Feb 08 '21 at 00:06

2 Answers2

4

Thanks to Mark Setchell, I found a working solution to this. In the color parameter in cv2.line(), pass a tuple where the first three values are the BGR color. The fourth value is for transparency/alpha. So your code should look like cv2.line(color=(0, 0, 200, 255)) # etc if you want to draw on a transparent image.

MmBaguette
  • 340
  • 3
  • 13
  • Off-topic, but in case you are working with np.zeros(), a one channel image and trying to draw a color other than white (e.g. red, three channels), check this: https://stackoverflow.com/a/61244250/13590096 – Legendary Emoji Aug 07 '23 at 18:25
0

The OpenCV drawing functions are very limited and only intended for simple markings in images.

They do not support the concept of transparency in images. For example, the line method understands two modes: three channels (colored line) or non-three channels (grayscale line). That's it.

The result is that in your case, the same value is written to all four channels. A black line should stay invisible, while a white or blue line should end up as a white line.

Reference: Source code of the method

ypnos
  • 50,202
  • 14
  • 95
  • 141
  • Thanks for your help, but I found this post which uses OpenCV in C++ which does exactly what I want: https://stackoverflow.com/a/23131198/14270319. I just don't know how to translate this to Python. – MmBaguette Feb 07 '21 at 22:56
  • Thank you for your feedback. I looked at the code again and the source I looked up was for non-antialiased lines. The aliased version does indeed support four channels (see https://github.com/opencv/opencv/blob/c073e09956e28053d0259a1bb4355bae73b59c8a/modules/imgproc/src/drawing.cpp#L315). – ypnos Feb 08 '21 at 10:25