首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >python opencv加水印 去水印

python opencv加水印 去水印

作者头像
py3study
发布于 2020-01-06 11:24:39
发布于 2020-01-06 11:24:39
4.5K00
代码可运行
举报
文章被收录于专栏:python3python3
运行总次数:0
代码可运行

收到的需求是在一个图上匹配到水印 然后将原来的水印换成一个新水印

先要安装一个库 库文件代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# coding=utf-8

import cv2
import numpy as np

# 膨胀算法 Kernel
_DILATE_KERNEL = np.array([[0, 0, 1, 0, 0],
                           [0, 0, 1, 0, 0],
                           [1, 1, 1, 1, 1],
                           [0, 0, 1, 0, 0],
                           [0, 0, 1, 0, 0]], dtype=np.uint8)

class WatermarkRemover(object):
    """"
    去除图片中的水印(Remove Watermark)
    """

    def __init__(self, verbose=True):
        self.verbose = verbose
        self.watermark_template_gray_img = None
        self.watermark_template_mask_img = None
        self.watermark_template_h = 0
        self.watermark_template_w = 0
        self.watermark_start_x = 0
        self.watermark_start_y = 0

    def load_watermark_template(self, watermark_template_filename):
        """
        加载水印模板,以便后面批量处理去除水印
        :param watermark_template_filename:
        :return:
        """
        self.generate_template_gray_and_mask(watermark_template_filename)

    def dilate(self, img):
        """
        对图片进行膨胀计算
        :param img:
        :return:
        """
        dilated = cv2.dilate(img, _DILATE_KERNEL)
        return dilated

    def generate_template_gray_and_mask(self, watermark_template_filename):
        """
        处理水印模板,生成对应的检索位图和掩码位图
        检索位图
            即处理后的灰度图,去除了非文字部分

        :param watermark_template_filename: 水印模板图片文件名称
        :return: x1, y1, x2, y2
        """

        # 水印模板原图
        img = cv2.imread(watermark_template_filename)

        # 灰度图、掩码图
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        _, mask = cv2.threshold(gray, 0, 255, cv2.THRESH_TOZERO + cv2.THRESH_OTSU)
        _, mask = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)

        mask = self.dilate(mask)  # 使得掩码膨胀一圈,以免留下边缘没有被修复
        #mask = self.dilate(mask)  # 使得掩码膨胀一圈,以免留下边缘没有被修复

        # 水印模板原图去除非文字部分
        img = cv2.bitwise_and(img, img, mask=mask)

        # 后面修图时需要用到三个通道
        mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)

        self.watermark_template_gray_img = gray
        self.watermark_template_mask_img = mask

        self.watermark_template_h = img.shape[0]
        self.watermark_template_w = img.shape[1]

        # cv2.imwrite('watermark-template-gray.jpg', gray)
        # cv2.imwrite('watermark-template-mask.jpg', mask)

        return gray, mask

    def find_watermark(self, filename):
        """
        从原图中寻找水印位置
        :param filename:
        :return: x1, y1, x2, y2
        """
        # Load the images in gray scale
        gray_img = cv2.imread(filename, 0)
        return self.find_watermark_from_gray(gray_img, self.watermark_template_gray_img)

    def find_watermark_from_gray(self, gray_img, watermark_template_gray_img):
        """
        从原图的灰度图中寻找水印位置
        :param gray_img: 原图的灰度图
        :param watermark_template_gray_img: 水印模板的灰度图
        :return: x1, y1, x2, y2
        """
        # Load the images in gray scale

        method = cv2.TM_CCOEFF
        # Apply template Matching
        res = cv2.matchTemplate(gray_img, watermark_template_gray_img, method)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

        # If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
        if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
            x, y = min_loc
        else:
            x, y = max_loc

        return x, y, x + self.watermark_template_w, y + self.watermark_template_h

    def remove_watermark_raw(self, img, watermark_template_gray_img, watermark_template_mask_img):
        """
        去除图片中的水印
        :param img: 待去除水印图片位图
        :param watermark_template_gray_img: 水印模板的灰度图片位图,用于确定水印位置
        :param watermark_template_mask_img: 水印模板的掩码图片位图,用于修复原始图片
        :return: 去除水印后的图片位图
        """
        # 寻找水印位置
        img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        x1, y1, x2, y2 = self.find_watermark_from_gray(img_gray, watermark_template_gray_img)
        self.watermark_start_x = x1
        self.watermark_start_y = y1
        # 制作原图的水印位置遮板
        mask = np.zeros(img.shape, np.uint8)
        # watermark_template_mask_img = cv2.cvtColor(watermark_template_gray_img, cv2.COLOR_GRAY2BGR)
        # mask[y1:y1 + self.watermark_template_h, x1:x1 + self.watermark_template_w] = watermark_template_mask_img
        mask[y1:y2, x1:x2] = watermark_template_mask_img
        mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)

        # 用遮板进行图片修复,使用 TELEA 算法
        dst = cv2.inpaint(img, mask, 4, cv2.INPAINT_TELEA)
        # cv2.imwrite('dst.jpg', dst)

        return dst

    def remove_watermark(self, filename, output_filename=None):
        """
        去除图片中的水印
        :param filename: 待去除水印图片文件名称
        :param output_filename: 去除水印图片后的输出文件名称
        :return: 去除水印后的图片位图
        """

        # 读取原图
        img = cv2.imread(filename)

        dst = self.remove_watermark_raw(img,
                                        self.watermark_template_gray_img,
                                        self.watermark_template_mask_img
                                        )

        if output_filename is not None:
            cv2.imwrite(output_filename, dst)

        return dst

注意 上面的代码要加上这两句 才能显示 原来水印的位置

去水印代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from nowatermark import WatermarkRemover

path = 'E:/sample/'

watermark_template_filename = path + 'watermark.png'
remover = WatermarkRemover()
remover.load_watermark_template(watermark_template_filename)

remover.remove_watermark(path + '20180516144931.png', path + '20180516144932.png')
print(remover.watermark_start_x)
print(remover.watermark_start_y)

这里输出的两个值 是指的水印在原图中的位置

加水印代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import cv2
import numpy as np
path = 'E:/sample/'
matimage = cv2.imread(path + '20180516144932.png')

#matimagenew = np.zeros((matimage.shape[0],matimage.shape[1],3))
matimagenew = matimage-matimage
watermark_template_filename = path + 'watermark.png'
matlogo = cv2.imread(watermark_template_filename)

matimagenew[359:359+matlogo.shape[0],453:453+matlogo.shape[1]] = matlogo
imagenew = cv2.addWeighted(matimage,1,matimagenew,1,1)
savepath = path + '20180516144933.png'
cv2.imwrite(savepath,imagenew)

其中的359为水印在原图中的位置的纵坐标 453为横坐标

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
完全依赖QML实现播放器
一直听闻QML无比强大好用,工作中需要扣一个同时播放视频的Demo,所以就趁这个机会研究了一下。
gongluck
2020/03/05
2.3K0
完全依赖QML实现播放器
qml入门教程_前端从入门到放弃
<9>:Property and number animation in mouse event:
全栈程序员站长
2022/09/19
2K0
qml入门教程_前端从入门到放弃
QML入门教程:一、QML和QtQuick简介以及QML实例
从 Qt 4.7 开始,Qt 引入了一种声明式脚本语言,称为 QML(Qt Meta Language 或者 Qt Modeling Language),作为 C++ 语言的一种替代。而 Qt Quick 就是使用 QML 构建的一套类库。 QML 是一种基于 JavaScript 的声明式语言。在 Qt 5 中, QML 有了长足进步,并且同 C++ 并列成为 Qt 的首选编程语言。也就是说,使用 Qt 5,我们不仅可以使用 C++ 开发 Qt 程序,而且可以使用 QML。虽然 QML 是解释型语言,性能要比 C++ 低一些,但是新版 QML 使用 V8,Qt 5.2 又引入了专为 QML 优化的 V4 引擎,使得其性能不再有明显降低。在 Nokia 发布 Qt 4.7 的时候,QML 被用于开发手机应用程序,全面支持触摸操作、流畅的动画效果等。但是在 Qt 5 中,QML 已经不仅限于开发手机应用,也可以用户开发传统的桌面程序。 QML 文档描述了一个对象树。QML 元素包含了其构造块、图形元素(矩形、图片等)和行为(例如动画、切换等)。这些 QML 元素按照一定的嵌套关系构成复杂的组件,供用户交互。 ——摘自《Qt学习之路2》
全栈程序员站长
2022/11/01
5.3K0
QML入门教程:一、QML和QtQuick简介以及QML实例
【C++】Qt:QML介绍与入门示例
Qt Quick是一个用于构建现代、高效、可扩展用户界面的框架。它是Qt开发框架的一部分,旨在通过声明性语法和JavaScript绑定来简化用户界面的设计和实现。
DevFrank
2024/07/24
1.2K0
【C++】Qt:QML介绍与入门示例
Qt开发-QT Quick
Row 则是一个单独的 Item ,专门用来管理其它 Item 的,后面介绍的几种布局,也是类似的。
码客说
2021/11/10
2.7K0
Qt官方示例-QML标签页
❝TabWidget示例演示了如何使用属性别名和QML Object默认属性创建标签页。❞ TabWidget.qml Item { id: tabWidget // 核心实现 // 将默认属性设置为stack.children意味着TabWidget的所有子项实际上都已添加到"stack"项的子项中。 // 有关默认属性的详细信息,请参见"Property Binding"文档。 default property alias content: stack.c
Qt君
2023/03/17
1.4K0
Qt官方示例-QML标签页
【专业技术】还有人在用Qt开发app嘛?
编者按: 这个世界不缺工程师,但是缺大师。如果在Qt里写个app,传统做法,需要熟悉API,熟悉C++,熟悉Qt本身的实现,同时还要熟悉编程环境。 现在出现了一种类似于脚本Javascript的语言,利用它,我们可以少编写一些程序逻辑。可不,最近我就利用它开发出了个浏览器。大家都没有。 欢迎来到声明式UI语言QML的世界.在本入门教程中,我们使用QML创建一个简单的文本编辑器.阅读这个教程后,就可以使用QML和Qt C++开发应用程序了. 安装 首先需要安装包含Qt Quick的Qt最新版本,现在是Qt4.
程序员互动联盟
2018/03/14
5.1K0
【专业技术】还有人在用Qt开发app嘛?
【QML】基础语法
QtQuick是一种高级界面技术,可轻松创建供移动、嵌入式设备使用的触摸式界面、轻量级应用程序。QtQuick主要由3部分组成:QtQuick设计器,QML语言、quick模块。
半生瓜的blog
2023/05/13
8690
【QML】基础语法
Qt官方示例-Qml鼠标点击与拖拽
  当您在红色方块内单击鼠标时,界面下方区域文本将显示出单击鼠标的一些属性,这些属性可用于QML中。按下鼠标时,红色方块的不透明度将降低,并保留在MouseArea内。当其中发生单击或双击等其他操作时,MouseArea会发出对应的信号。
Qt君
2020/04/01
2.8K0
Qt官方示例-Qml翻转动画
❝示例演示翻转动画(沿着x轴或y轴翻转动画)。❞ 主要代码: import QtQuick 2.0 Flipable { id: container property alias source: frontImage.source property bool flipped: true property int xAxis: 0 property int yAxis: 0 property int angle: 0 width: front.
Qt君
2023/03/17
8510
Qt官方示例-Qml翻转动画
Qml数字键盘
双十一购物节为了避免剁手,给自己一个小目标,写个Qml数字键盘分享给大家。 1. Qml键盘代码 Rectangle { id: rootKeyboard property color backgroundColor: "#202120" //default property color pressedButtonColor: "#00a0fc" // default property color normalButtonColor: "#303751" // d
Qt君
2023/03/17
8970
Qml数字键盘
兼容Qt4/Qt5版本Qml控件Slider
通过滑动滑块选择一个值 导入方法: 文件导入 兼容性: QtQuick1.x与 QtQuick2.x 继承: Item 属性 background: Item from: real handle: Item orientation: enumeration position: real pressed: bool stepSize: real to: real value: real 方法 function decrease() function increase() 描述 通过滑动滑块选择一个值 Slid
Qt君
2019/07/15
7030
兼容Qt4/Qt5版本Qml控件Slider
Qt Quick实践系列-函数绑定
  由于display函数内部使用了string1和string2变量,当其中任意一个变量变更都会更新text: display()表达式。这种动态绑定在界面编程中会变得更易用方便。
Qt君
2020/05/08
5150
Qt界面UI之QML初见(学习笔记四)
一 概述 QML是一种专门用于构建用户界面的编程语言,它允许用户构建高性能,具有流畅特效的可视化应用程序,QML是可读的,声明式的文档,具有类似JSON的语法,支持使用JavaScrip表达式,具有动态属性绑定等特性。 二 QML语法基础 QMl的代码一般长如下: import QtQuick 2.2 Rectangle { width: 360 height: 360 MouseArea { anchors.fill: parent onClic
用户1198337
2018/01/19
2.6K0
Qt界面UI之QML初见(学习笔记四)
Qt5实战第十一篇:QML与Qt Quick详解
QML(Qt Meta-Object Language 或 Qt Modelling Language)和Qt Quick是Qt框架的重要组成部分,主要用于构建高性能、交互性强的用户界面。QML是一种基于JavaScript的声明性语言,而Qt Quick则是QML类型和功能的标准库。下面将详细讲解QML与Qt Quick的基本概念、特点、应用场景以及示例。
china马斯克
2025/01/04
9100
Qml失焦问题
Qml常见诡异失焦情况一般为明明设置了某一控件的焦点, 实际却是不生效。这到底时什么情况呢?用例子来分析这种情况。 1.常见失焦情况 被其他控件抢夺; 误以为设置成功。 2.关于控件被抢夺的情况 2.1 先看下列例子 Dialog { id: dialog width: 100; height: 100 onHidden: { dialog.forceReset() // restore focus to 'yes' button } } Rectangle
Qt君
2019/07/15
2.5K0
一个好的Qml文件(翻译文)
  什么样的Qml文件(通常称为组件)是一个高质量的文件?   让我们看看示例1:
Qt君
2019/07/15
1.2K0
pyqt5与QML开发小结
qt 5.11 与 qt 5.12 中Qquick的差异还是蛮大的,由开发环境:Pyqt5.11 + Qt5.12 部署到 Pyqt5.11 + Qt5.11时遇到以下问题:
py3study
2020/01/17
1.6K0
兼容Qt4/Qt5版本Qml控件CheckBox
复选框显示一个可切换(选中)或关闭(未选中)的选项按钮.复选框通常用于从一组选项中选择一个或多个选项.
Qt君
2019/07/15
1.1K0
兼容Qt4/Qt5版本Qml控件CheckBox
Qt官方示例-Qml之ListView
  在应用程序的根Rectangle中定义的第一项是委托组件。这是用于构造ListView中每个项目的模板。
Qt君
2023/03/17
1K0
Qt官方示例-Qml之ListView
相关推荐
完全依赖QML实现播放器
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档