Image Processing #5 - WaterMark using alpha channel

In the previous article, we saw how to implement a watermark without an alpha channel. This method uses a method of overlaying the part where the color exists except for the black color (0,0,0) part of the mask image. However, in the case of a png file having an alpha channel, this can be simplified because the density can be adjusted by the size of the alpha channel value. The source you implement is almost the same as the existing one. However, if the existing code finds black, this time, read the alpha channel value and divide it by 255 to reflect this ratio.

New watermark function using alpha channel



def process_alpha_masking(base, mask, pos):
    h, w, c = mask.shape
    hb, wb, _ = base.shape
    x = pos[0]
    y = pos[1]

    #check mask position
    if(x > wb or y > hb):
        print(' invalid overlay position(%d,%d)'%(x, y))
        return None
    
    #alpha channel check    
    if c != 4:
        print('mask image file does not have alpha channel')
        return None
    
    #adjust mask
    if(x + w > wb):
        mask = mask[:, 0:wb - x]
        print(' mask X size adjust[W:%d] -> [W:%d]'%(w, wb - x))
    if(y + h > hb):
        mask = mask[0:hb - y, :]
        print(' mask Y size adjust[H:%d] -> [H:%d]'%(h, hb - y))

    h, w, c = mask.shape
    
    img = base.copy()
    bg = img[y:y+h, x:x+w]      #overlay area
    try:
        for i in range(0, h):
            for j in range(0, w):
                B = mask[i][j][0]
                G = mask[i][j][1]
                R = mask[i][j][2]
                alpha = mask[i][j][3] * 1.0 / 255.0
                if (alpha > 0.0):
                    bg[i][j][0] = int(B * alpha + bg[i][j][0] * (1 - alpha))
                    bg[i][j][1] = int(G * alpha + bg[i][j][1] * (1 - alpha))
                    bg[i][j][2] = int(R * alpha + bg[i][j][2] * (1 - alpha))
        img[y:y+h, x:x+w] = bg
    except IndexError:  #index (i, j) is out of the screen resolution.  
        print(' index Error')
        return None
    return img


This is the full code.


import argparse
import cv2
import numpy as np
'''
This function remains background
rate should be : 0 < rate < 1.0
'''
def process_alpha_masking(base, mask, pos):
    h, w, c = mask.shape
    hb, wb, _ = base.shape
    x = pos[0]
    y = pos[1]

    #check mask position
    if(x > wb or y > hb):
        print(' invalid overlay position(%d,%d)'%(x, y))
        return None
    
    #remove alpha channel    
    if c != 4:
        print('mask image file does not have alpha channel')
        return None
    
    #adjust mask
    if(x + w > wb):
        mask = mask[:, 0:wb - x]
        print(' mask X size adjust[W:%d] -> [W:%d]'%(w, wb - x))
    if(y + h > hb):
        mask = mask[0:hb - y, :]
        print(' mask Y size adjust[H:%d] -> [H:%d]'%(h, hb - y))

    h, w, c = mask.shape
    
    img = base.copy()
    bg = img[y:y+h, x:x+w]      #overlay area
    try:
        for i in range(0, h):
            for j in range(0, w):
                B = mask[i][j][0]
                G = mask[i][j][1]
                R = mask[i][j][2]
                alpha = mask[i][j][3] * 1.0 / 255.0
                if (alpha > 0.0):
                    bg[i][j][0] = int(B * alpha + bg[i][j][0] * (1 - alpha))
                    bg[i][j][1] = int(G * alpha + bg[i][j][1] * (1 - alpha))
                    bg[i][j][2] = int(R * alpha + bg[i][j][2] * (1 - alpha))
        img[y:y+h, x:x+w] = bg
    except IndexError:  #index (i, j) is out of the screen resolution.  (화면 범위를 벗어남.)
        print(' index Error')
        return None
    return img


parser = argparse.ArgumentParser(description="OpenCV Example")
parser.add_argument("--file", type=str, required=True, help="filename of the input image to process")
parser.add_argument("--mask", type=str, required=True, help="mask image to overlay")
args = parser.parse_args()

img = cv2.imread(args.file, cv2.IMREAD_COLOR)
height, width, channels = img.shape
print("image   H:%d W:%d, Channel:%d"%(height, width, channels))
cv2.imshow('original', img)

mark = cv2.imread(args.mask, cv2.IMREAD_UNCHANGED)
mheight, mwidth, mchannels = mark.shape
print("mask   H:%d W:%d, Channel:%d"%(mheight, mwidth, mchannels))

x = np.amin( [mwidth, width])
y = np.amin( [mheight, height])
new_img = process_alpha_masking(img, mark, (x, y))
if new_img is not None :
    cv2.imshow('masked', new_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Run the code.



python watermark_alpha.py --file=biden.jpg --mask=watermark.png
image   H:727 W:320, Channel:3
mask   H:32 W:100, Channel:4

<watermarking using alpha channel>



<watermarking result in the previous post>

Can you find the difference from the previous example? Since the alpha channel value of the png file is 255 or 0, watermarking using the alpha channel appears more clearly. By adjusting the alpha channel value of the png file so that it has a value between 0 and 255, you can create a watermark with transparency adjusted as in the previous example. Alternatively, the rate value used in the previous watermark function may be used again.



댓글

이 블로그의 인기 게시물

Image Processing #7 - OpenCV Text

Playing YouTube videos using OpenCV

OpenCV Installation - Rasbian Buster, Jessie, DietPi Buster