Image Processing #4 - WaterMark without alpha channel
A few days ago, I wrote a blog post on pasting overlays with OpenCV. A little tweaking the code in that article can create a watermark feature.
Many Python samples that implement watermarks use the alpha channel of png files. However, I would like to implement the function of generating a watermark using an image of an RGB channel without an alpha channel.
Masking code in my previous blog
def process_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: mask = cv2.cvtColor(mask, cv2.COLOR_BGRA2BGR) #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] if (int(B) + int(G) + int(R)): bg[i][j][0] = B bg[i][j][1] = G bg[i][j][2] = R 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 code replaces the pixel values of the original image area with mask value if the RGB value of the mask exist. If you do not replace the pixel values of the original image with the mask values, mix original image pixel values with mask image pixel values.
New watermark function
This function is very similar to the above function. But it mixes the original pixel and the mask pixel by the mixing ratio as a parameter(rate). The sum of the reflectance ratios of the original image pixels and the watermark image pixels is always one.def watermark(img, mask, pos, rate): h, w, c = mask.shape x = pos[0] y = pos[1] height, width, channels = img.shape if (x + w) > width : print('Error : The worker mark is out of the image area.') return None if c == 4: mask = cv2.cvtColor(mask, cv2.COLOR_BGRA2BGR)
#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] if (int(B) + int(G) + int(R)): bg[i][j][0] = float(B) * rate + float(bg[i][j][0]) * (1 - rate) bg[i][j][1] = float(G) * rate + float(bg[i][j][1]) * (1 - rate) bg[i][j][2] = float(R) * rate + float(bg[i][j][2]) * (1 - rate) bg.astype('uint8') img[y:y+h, x:x+w] = bg except IndexError: print(' index Error') return None return img
The values in the bg array changed to floating point numbers during the operation. Therefore, you must convert to uint8 type again after all operations using astype function. Every coloe image has at least three channels(R, G, B). PNG files can have an alpha channel, which in this case is 4. All values in the image array are between 0 and 255. The variable type is uint8.
Full Code
import argparse import cv2 import numpy as np ''' This function remains background rate should be : 0 < rate < 1.0 ''' def watermark(img, mask, pos, rate): h, w, c = mask.shape x = pos[0] y = pos[1] height, width, channels = img.shape if (x + w) > width : print('Error : The worker mark is out of the image area.') return None if c == 4: mask = cv2.cvtColor(mask, cv2.COLOR_BGRA2BGR)
#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] if (int(B) + int(G) + int(R)): bg[i][j][0] = float(B) * rate + float(bg[i][j][0]) * (1 - rate) bg[i][j][1] = float(G) * rate + float(bg[i][j][1]) * (1 - rate) bg[i][j][2] = float(R) * rate + float(bg[i][j][2]) * (1 - rate) bg.astype('uint8') img[y:y+h, x:x+w] = bg except IndexError: 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") parser.add_argument("--rate", type=float, default=0.5, help="mixing rate") 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 = watermark(img, mark, (x, y), args.rate) if new_img is not None : cv2.imshow('masked', new_img) cv2.waitKey(0)
Run the code.
python watermark.py --file=biden.jpg --mask=watermark.png image H:727 W:320, Channel:3 mask H:32 W:100, Channel:4
You can adjust --rate value to adjust the clearness of the watermark.
python watermark.py --file=biden.jpg --mask=watermark.png --rate=0.8 image H:727 W:320, Channel:3 mask H:32 W:100, Channel:4
Default rate value is 0.5, if you increase this value to 0.8, the watermark image is more clear and the background image is hard to see.
Wrapping up
This article is an example of inserting a watermark using a jpg image without an alpha channel. If it is a png file with an alpha channel, the alpha channel is removed and a watermark is inserted. Therefore, there is a rate variable that controls the concentration in the parameter of the watermark function. However, if an alpha channel exists, the density can be adjusted according to the size of the alpha channel value. See the next article for an example of a watermark using the alpha channel.You can download the source codes here(https://github.com/raspberry-pi-maker/OpenCV)
댓글
댓글 쓰기