如何添加水印?
添加水印其实可以理解为将一张图片中的某个物体或者图案提取出来,然后叠加到另一张图片上。具体的操作思想是通过将原始图片转换成灰度图,并进行二值化处理,去除背景部分,得到一个类似掩膜的图像。然后将这个二值化图像与另一张图片中要添加水印的区域进行“与”运算,使得目标物体的形状出现在要添加水印的区域。最后,将得到的目标物体图像与要添加水印的区域进行相加,就完成了添加水印的操作。这样可以实现将一个图像中的某个物体或图案叠加到另一个图像上,从而实现添加水印的效果。
何为掩膜?
掩膜(Mask)是一种在图像处理中常见的操作,它用于选择性地遮挡图像的某些部分,以实现特定任务的目标。掩膜通常是一个二值化图像,并且与原图像的大小相同,其中目标区域被设置为1(或白色),而其他区域被设置为0(或黑色),并且目标区域可以根据HSV的颜色范围进行修改
没听懂没关系,下面开始详细介绍
示例演示
将准备好的logo图作为水印模板,本篇以下图作为水印模板与目标模板
注: 本示例以白底的水印模板演示,所以我们需要准备一张黑底的掩膜(目标区域位为白色)
黑底的水印模板则不需要多准备一张黑底的掩膜,直接从下面第二步开始即可
如果你是在分不清要准备什么底的掩膜,那就都准备吧,两个掩膜都试一试
第一步
首先我们需要先将颜色空间转换成HSV,再制造一个掩膜(目标区域为黑色,后面要进行与运算)用来确定logo的范围。
方法一:水印模板上出现了两种颜色,所以要制作两个掩膜,再将两个掩膜合为一个掩膜(或运算),这样就可以筛选水印模板中的所有logo信息,掩膜如下:
但直接调用接口制作的掩膜(如上图)中,目标区域是白色的,如果你需要的是目标区域为黑色的掩膜,建议用下面的第二种方法,直接得到目标区域为黑色的掩膜
方法二:掩膜本身也就是一个二值化的二维数组,我们也可以对原图灰度化后在进行二值化,得到的结果如下,二值化后的图(右侧)也可以用做掩膜使用。
第二步
在目标模板上利用ROI切割出自己想要的区域(你想将水印添加的区域),ROI切割可以参照我之前的文章
06篇--图片目标区域的 ROI切割-CSDN博客
第三步
将掩膜与目标模板进行与运算,之后:
- 掩膜(白色部分)会被目标模板(相应的部分)替代
- 掩膜(黑色部分)会将目标模板(相应的部分)替代
得到的结果与切割部分进行对比:
将切割出来的部分img_roi与掩膜进行与运算,之后:
- 掩膜(白色部分)会被目标模板(相应的部分)替代
- 掩膜(黑色部分)会将目标模板(相应的部分)替代
得到的结果与切割部分进行对比:
第四步
就是将图像对应的数组中的对应元素进行相加(一定要注意这里的两个数组是规格相同的,也就是说要么都是灰度图,要么都是彩图),其过程如下图所示
cv2.add()函数,用于执行上面的过程,可得到如下结果
第五步
将已经融合好的部分替换掉目标模板中的相应部分(被切割的那一部分),利用切片进行。
如果还是对上述步骤有疑问,欢迎在评论区提问。
代码演示
import cv2
import numpy as np#读取图像
logo = cv2.imread('image/logo_1.png')
img = cv2.imread('image/logo_demo.png')#第一种方法获取掩膜
#先转换颜色空间
logo_hsv = cv2.cvtColor(logo,cv2.COLOR_BGR2HSV)#制作红色掩膜
red_min= np.array([0,43,46])
red_max = np.array([10,255,255])
logo_mask_1_1 = cv2.inRange(logo_hsv,red_min,red_max)#制作黑色掩膜
black_min = np.array([0,0,0])
black_max = np.array([180,255,220])
logo_mask_1_2 = cv2.inRange(logo_hsv,black_min,black_max)#将两个掩膜合并
logo_mask_1 = cv2.bitwise_or(logo_mask_1_1,logo_mask_1_2)#第二种方法获取掩膜
#灰度化
logo_gray = cv2.cvtColor(logo,cv2.COLOR_BGR2GRAY)
#二值化结果充当掩膜
_,logo_mask_2 = cv2.threshold(logo_gray,127,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)
#获取掩膜大小
rows,cols = logo.shape[:2]#ROI切割
#要切割的矩形的top_left的坐标点
x1,y1 = 750,425
def ImgRoi(img,x1,y1):# 提取该图片的宽高h,w = img.shape[0], img.shape[1]#获取掩膜坐标,x2,y2x2 = x1 + colsy2 = y1 + rowsif x1<0 or x2>w or y1<0 or y2>h:print("要切割的区域是不合适的")else:# 给要切割的内容画个框# cv2.rectangle(img, (x1-2, y1-2), (x2+2, y2+2), (0, 0, 255), 2)# 保存要切割的内容img_roi = img[y1:y2, x1:x2]return img_roiimg_roi = ImgRoi(img,x1,y1)# 进行与运算
logo_mask = cv2.bitwise_and(logo,logo,mask=logo_mask_1)
img_roi_mask = cv2.bitwise_and(img_roi,img_roi,mask=logo_mask_2)#进行相加,得到融合的图像img_roi_mask,并合并到img中
img_roi_logo = cv2.add(img_roi_mask,logo_mask)
img[y1:(y1+rows), x1:(x1+cols)] = img_roi_logocv2.imshow('logo_mask',img)cv2.waitKey(0)