当前位置 博文首页 > 文章内容

    使用OpenCV为图像加水印的教程

    作者:21344 栏目:未分类 时间:2021-09-01 14:43:58

    在本文中,我们将学习如何使用 OpenCV 为多个图像添加水印。

    1. 什么是水印?

    水印是有意叠加在不同图像上的标志、签名、文本或图案,用于保护图像的版权。

    其主要目的是宣传品牌,并使未经所有者许可复制或使用原始图像变得更加困难。

    组织和专业人士经常使用水印来防止在在线托管内容后被其他人使用他们的内容。

    那么,你有没有想过为图像添加水印?

    例如,我们写博客会说明外部图像的来源。但是你自己创建的图像呢?在自己创建的图像上留下你的记号不是很好吗?

    好极了!让我们开始这项激动人心的任务。

    2. 在 OpenCV 中调整图像大小

    调整大小只不过是缩放图像,这意味着更改原始图像的大小。我们可以根据业务需求增加或减少图像的大小。

    可以通过多种方式调整大小。

    1.保持纵横比。图像的纵横比是其宽度与高度的比率。

    .缩小或放大图像的大小

    1.不保留纵横比

    .仅缩小/放大宽度,仅缩小/放大高度

    1.将宽度和高度都更改为特定值

    到目前为止听起来不错,但我们如何实际操作呢?答案是 OpenCV 及其 resize() 函数。从本文档中阅读有关 OpenCV 调整大小功能的更多信息:https://docs.opencv.org/3.4/da/d54/group__imgproc__transform.html#ga47a974309e9102f5f08231edc7e7529d

    **cv2.resize() 函数的语法:**cv2.resize(src, dsize,interpolation)

    src – 源图像

    dsize – 输出图像的所需大小

    interpolation -  插值,维基百科定义:它是一种基于一组离散的已知数据点的范围构建(查找)新数据点的方法。

    请参阅此文档以了解有关插值标志的更多信息:https://docs.opencv.org/3.4/da/d54/group__imgproc__transform.html#ga5bb5a1fea74ea38e1a5445ca803ff121

    现在,让我们拍摄一个示例图像并调整其大小。下面是我们的示例图像。

    现在,尝试使用 OpenCV 显示它。

    import cv2
    img = cv2.imread('images/deer.JPG')
    cv2.imshow("Original Image", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    下面是我们的图像在使用 OpenCV 显示时的外观。

    由于我们的图像是高分辨率的,因此只有一部分是可见的。

    所以,肯定有必要调整它的大小。我们需要减小它的大小。

    在 OpenCV 中调整图像大小的步骤:

    • 使用 cv2.imread() 读取图像
    • 设置新的宽度和高度。
    • 为新维度创建一个元组
    • 使用 cv2.resize() 调整图像大小
    • 如果需要,使用 cv2.imwrite() 将调整后的图像保存到计算机
    • 使用 cv2.imshow() 显示原始的、调整大小的图像

    1. 保持纵横比——将图像缩小到原始尺寸的 20%。

    我们将原始图像的大小减小到其原始大小的 20%。因此,通过计算原始宽度的 20%,原始高度的 20%,为新尺寸创建一个元组。

    import cv2
    img = cv2.imread('images/deer.JPG')
    percent_of_scaling = 20
    new_width = int(img.shape[1] * percent_of_scaling/100)
    new_height = int(img.shape[0] * percent_of_scaling/100)
    new_dim = (new_width, new_height)
    resized_img = cv2.resize(img, new_dim, interpolation=cv2.INTER_AREA)
    filename = 'resized_img_aspect ratio.jpg'
    cv2.imwrite(filename, resized_img)
    cv2.imshow("Original Image", img)
    cv2.imshow("Resized Image", resized_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    上面的代码保存调整大小的图像并显示原始的、调整大小的图像。

    做得好。通过牢记纵横比,我们成功地调整了图像大小。

    2. 不保留纵横比 – 仅缩小/放大宽度,仅缩小/放大高度

    调整大小的步骤与上述相同。唯一的区别是我们保持两个维度中的任何一个不变。

    import cv2
    img = cv2.imread('images/deer.JPG')
    new_dim = (img.shape[1], 500) # changes height
    resized_img = cv2.resize(img, new_dim, interpolation=cv2.INTER_AREA)
    cv2.imshow("Original Image", img)
    cv2.imshow("Resized Image", resized_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    下面是从上面的代码显示的图像。

    调整大小的图像失真并且不是所需的输出。

    3.将宽度和高度都更改为特定值

    import cv2
    img = cv2.imread(‘images/deer.JPG')
    new_dim = (450, 450)
    resized_img = cv2.resize(img, new_dim, interpolation=cv2.INTER_AREA)
    cv2.imshow(“Original Image”, img)
    cv2.imshow(“Resized Image”, resized_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    下面是从上面的代码显示的图像。

    这看起来还可以,但不如保留纵横比的输出图像。所以我更喜欢通过保留纵横比来调整大小。

    下一步是查看如何创建水印。

    3.使用图像创建水印

    我选择使用我名字的图像添加水印。制作一张你的名字的图像,然后和我一起尝试。

    在图像中心添加水印的步骤

    如果需要,读取并调整图像(水印图像、输入图像)的大小。

    import cv2
    img = cv2.imread('images/deer.JPG')
    watermark = cv2.imread("watermark.PNG")
     
    percent_of_scaling = 20
    new_width = int(img.shape[1] * percent_of_scaling/100)
    new_height = int(img.shape[0] * percent_of_scaling/100)
    new_dim = (new_width, new_height)
    resized_img = cv2.resize(img, new_dim, interpolation=cv2.INTER_AREA)
     
    wm_scale = 40
    wm_width = int(watermark.shape[1] * wm_scale/100)
    wm_height = int(watermark.shape[0] * wm_scale/100)
    wm_dim = (wm_width, wm_height)
    resized_wm = cv2.resize(watermark, wm_dim, interpolation=cv2.INTER_AREA)

    根据调整大小的输入图像的新尺寸定义水印的位置。

    h_img, w_img, _ = resized_img.shape
    center_y = int(h_img/2)
    center_x = int(w_img/2)
    h_wm, w_wm, _ = resized_wm.shape
    top_y = center_y - int(h_wm/2)
    left_x = center_x - int(w_wm/2)
    bottom_y = top_y + h_wm
    right_x = left_x + w_wm

    获取感兴趣的**矩形区域 (ROI)**并将其存储到名为“roi”的变量中。

    roi = resized_img[top_y:bottom_y, left_x:right_x]

    使用**cv2.addWeighted()**将调整大小的水印叠加到 ROI 上,并将其存储到名为“result”的变量中。

    result = cv2.addWeighted(roi, 1, resized_wm, 0.3, 0)

    现在,将此结果添加到调整大小的输入图像

    resized_img[top_y:bottom_y, left_x:right_x] = result

    将生成的水印图像保存到计算机

    filename = 'watermarked_deer.jpg'
    cv2.imwrite(filename, resized_img)

    显示生成的水印图像

    cv2.imshow("Resized Input Image", resized_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    下面是生成的水印图像。

    到现在为止,我们已经学会了给单个图像加水印。由于我们的目标是为多个图像加水印,因此我们需要创建所有这些输入图像的列表并循环遍历它。

    下面是将使用的图像。

    创建输入图像列表

    import os
    folderPath = "images"
    imgList = os.listdir(folderPath)
    imgList

    给多个图像加水印的代码

    import cv2
    watermark = cv2.imread("watermark.PNG")
    wm_scale = 40
    wm_width = int(watermark.shape[1] * wm_scale/100)
    wm_height = int(watermark.shape[0] * wm_scale/100)
    wm_dim = (wm_width, wm_height)
    resized_wm = cv2.resize(watermark, wm_dim, interpolation=cv2.INTER_AREA)
    h_wm, w_wm, _ = resized_wm.shape
     
    for image in  imgList:
        img = cv2.imread(f'{folderPath}/{image}')
        percent_of_scaling = 20
        new_width = int(img.shape[1] * percent_of_scaling/100)
        new_height = int(img.shape[0] * percent_of_scaling/100)
        new_dim = (new_width, new_height)
        resized_img = cv2.resize(img, new_dim, interpolation=cv2.INTER_AREA)
        h_img, w_img, _ = resized_img.shape
        center_y = int(h_img/2)
        center_x = int(w_img/2)
        top_y = center_y - int(h_wm/2)
        left_x = center_x - int(w_wm/2)
        bottom_y = top_y + h_wm
        right_x = left_x + w_wm
        roi = resized_img[top_y:bottom_y, left_x:right_x]
        result = cv2.addWeighted(roi, 1, resized_wm, 0.3, 0)
        resized_img[top_y:bottom_y, left_x:right_x] = result
        filename = os.path.basename(image)
        cv2.imwrite("watermarked images/watermarked_"+filename, resized_img)
        cv2.imshow("Watermarked Image", resized_img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

    最后,我们完成了为所有输入图像加水印的任务。

    参考

    OpenCV 文档:https://docs.opencv.org/3.4/d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56

    GitHub 存储库链接:https://github.com/harika-bonthu/Watermark-OpenCV