使用Python,OpenCV制作全透明的logo水印,对图像添加水印

这篇博客将介绍如何使用OpenCV,Python自己动手做一个全透明的logo,并将其作为水印添加到图片数据集上。对图像或视频加水印称为数字水印,是将独特的识别图案嵌入到图像本身的过程。

例如:专业摄影师倾向于给发送给客户的数字打样加水印(包括相关信息,例如其姓名和/或设计工作室),直到客户同意购买照片为止,并在此发布原始的,未更改的图像。这使摄影师能够分发演示和作品样本,而无需实际“放弃”原始作品。

我们还会在受版权保护的视频中看到数字水印-在这种情况下,视频的每一帧都嵌入了水印,从而保证作品的原始制作者的版权。

在这两种情况下,加水印的目的是在图像上创建一个独特且可识别的图案,将其归属于原始创作者,但又不破坏图像本身的内容。有关盲水印的更多内容可查看

1. 效果图

源数据集:
在这里插入图片描述加了水印后的数据集:在这里插入图片描述

2. OpenCV自己制作一个logo(完全不透明的)

  1. 打开windows上mspaint画一张图并保存(白底黑字);在这里插入图片描述
  2. 利用cv.threhold 阈值化方法转为黑底白字的图;
    在这里插入图片描述
  3. 添加一个透明度为255(完全不透明)的通道alpha,转为四通道图;
    在这里插入图片描述

3. 制作水印图源码

# logo读取与制作
# 三通道图转为4通道 制作透明图

import numpy as np
import cv2

image = cv2.imread('D:\\deepLearning\\test\\watermark.png')
cv2.imshow("Image", image)
cv2.waitKey(0)

# 转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 像素翻转
thresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)[1]
cv2.imshow("Thresh", thresh)
cv2.imwrite("D:\\deepLearning\\test\\wm_thresh.png", thresh)
cv2.waitKey(0)

image = cv2.imread('D:\\deepLearning\\test\\wm_thresh.png')
print(image.shape)
(h, w) = image.shape[:2]
image = np.dstack([image, np.ones((h, w), dtype="uint8") * 255])
print(image.shape)
cv2.imwrite('D:\\deepLearning\\test\\wm_thresh_255.png', image)
cv2.imshow("alpha", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

4. 添加水印源码

# python watermark_dataset.py --watermark wm_thresh_255.png --input input --output output

# 导入必须的包
from imutils import paths
import numpy as np
import argparse
import cv2
import os

# 构建命令行参数
ap = argparse.ArgumentParser()
# --watermark     :我们希望用作水印的图像的路径。我们假设(1)此图像是具有alpha透明度的PNG图像,并且(2)我们的水印较小(就宽度和高度而言),然后我们将对其应用水印的数据集中的所有图像都较小。
# --input         :要加水印的图像输入目录的路径。
# --output        :用来存储带水印图像的输出目录。
# --alpha         :可选的--alpha 值控制水印的透明度。值为1.0表示水印应为100%不透明(即不透明)。值0.0表示水印应为100%透明。25%的值在大多数情况下效果很好。
# --correct       :最后,此开关用于控制我们是否应保留OpenCV处理alpha透明度的“错误”。我加入此开关的唯一原因是有关OpenCV库的问题。除非您想亲自调查此错误,否则可能会忽略此参数。
ap.add_argument("-w", "--watermark", required=True,
                help="path to watermark image (assumed to be transparent PNG)")
ap.add_argument("-i", "--input", required=True,
                help="path to the input directory of images")
ap.add_argument("-o", "--output", required=True,
                help="path to the output directory")
ap.add_argument("-a", "--alpha", type=float, default=0.25,
                help="alpha transparency of the overlay (smaller is more transparent)")
ap.add_argument("-c", "--correct", type=int, default=1,
                help="flag used to handle if bug is displayed or not")
args = vars(ap.parse_args())

# 加载水印图像,确保其有4通道,包含透明度alpha值
# cv2.IMREAD_UNCHANGED允许我们可以读取PNG图像的Alpha透明度通道(以及标准的Red,Green和Blue通道)。
watermark = cv2.imread(args["watermark"], cv2.IMREAD_UNCHANGED)
(wH, wW) = watermark.shape[:2]

# 解决在使用Alpha透明度和OpenCV时遇到的一些奇怪的问题
# 将水印拆分为各自的蓝色,绿色,红色和Alpha通道;然后在所有通道和Alpha通道之间进行按位与运算以构造实际的水印。注意:我不确定为什么必须这样做,但是如果不这样做,则会有问题
# 在研究Alpha通道本身时,我注意到直接使用Alpha通道没有问题-Alpha通道已加载并完美表示。
# 因此,为了确保每个红色,绿色和蓝色通道都遵守alpha通道,我采用了按位AND 在各个颜色通道和alpha通道之间,将alpha通道视为遮罩,这解决了奇怪的问题
# 我包含了--correct   标记此处,以便您调查不应用此类校正时会发生什么(有关更多信息,请参见“加水印结果”部分)。
# 【在OpenCV图像处理管道中使用alpha透明度,请确保格外小心,分别使用alpha蒙版分别对每个Red,Green和Blue通道进行蒙版,这块可能出错。会把整个水印图像半透明而不是其内容;】
if args["correct"] > 0:
    (B, G, R, A) = cv2.split(watermark)
    B = cv2.bitwise_and(B, B, mask=A)
    G = cv2.bitwise_and(G, G, mask=A)
    R = cv2.bitwise_and(R, R, mask=A)
    watermark = cv2.merge([B, G, R, A])

# 遍历输入的图像
for imagePath in paths.list_images(args["input"]):
    # 加载输入图像 并添加一个维度(alpha透明度值)【h * w * 3 --- h * w * 4】
    # 构建一个和输入图像完全一致的叠加层,此Alpha通道具有与原始图像相同的空间尺寸,并且Alpha通道中的所有值均设置为255,指示像素完全不透明。
    image = cv2.imread(imagePath)
    (h, w) = image.shape[:2]
    image = np.dstack([image, np.ones((h, w), dtype="uint8") * 255])

    # 构建水印图片的叠加层(使得其具有与输入图像完全相同的宽度和高度)
    overlay = np.zeros((h, w, 4), dtype="uint8")
    overlay[h - wH - 10:h - 10, w - wW - 10:w - 10] = watermark

    # 应用cv2.addWeighted构造水印的图像
    output = image.copy()
    cv2.addWeighted(overlay, args["alpha"], output, 1.0, 0, output)

    # 把加了水印的图片写入磁盘
    filename = imagePath[imagePath.rfind(os.path.sep) + 1:]
    p = os.path.sep.join((args["output"], filename))
    cv2.imwrite(p, output)

5. 思考:

水印是否可以换个位置?
是否可添加多个?
都是可以的呦,自己尝试啦~~

加水印容易,怎么去除水印呢? 下一节继续奇妙的旅程;
可以用cv2.inpaint【图像修复】

参考

猜你喜欢

转载自blog.csdn.net/qq_40985985/article/details/106213908
今日推荐