【数据安全-02】AI打假利器数字水印,及java+opencv实现


AIGC 的火爆引燃了数字水印,说实话数字水印并不是一项新的技术,但是这时候某些公司拿出来宣传一下特别应景,相应股票蹭蹭地涨。数字水印是什么呢,顾名思义,和我们在pdf中打的水印作用差不多,起到明确版权、防伪验真的作用。但是不同于传统肉眼可见的水印,数字水印也叫隐藏式水印,能够在人眼几乎无法察觉的情况下将水印信息秘密嵌入到音频、图像或视频中去,除了减少对画质的影响外,有个重要的功能就是保护著作权,使得盗版者无法感知水印存在,让版权的鉴定的溯源变得更轻松。

提到数字水印,有个经典案例经常被提到,阿里巴巴的一名员工擅网页截图外传,造成很大的恶劣影响,结果利用数字水印,很快就定位到这名员工,这名员工还奇怪,发的时候我还特意留意图片上没有水印,怎么就能定位到我呢,可见数字水印的强大,数字水印于无形中发挥着强大作用。

背后的科学奥秘

那么数字水印到底是如何实现的呢,那就不得不提到傅里叶变换,任何函数都可以写成正弦函数之和,用直白的话说就是任何二维空间的波形,都可以用简单的正弦和余弦波叠加而成,傅里叶变换交互式入门这篇文章详细的可视化地介绍了这一原理,并且我们可以随意画一条线看看,是不是可以由多条正弦波叠加而成。

在这里插入图片描述
我们拓展到三维空间,同样的道理,任何凹凸不平的面都可以用正弦平面波叠加而成,如下图所示,看一下大脑的图片,是一张灰度图,每个像素都有灰度值,我们加个坐标,Z轴为灰度值的大小,这样整张图就成为凹凸不平的曲面,那么这张凹凸不平的曲面就可以用多个正弦平面波叠加而成,所以在我们也可以用这些个正弦平面波来存储这张图,简而言之,我们能将图像用频域表示,接下来我们聊聊二维频率域K-SPACE,或者叫傅里叶空间
在这里插入图片描述

对于正弦平面波,可以这样理解,在一个方向上存在一个正弦函数,在法线方向上将其拉伸。前面说过三个参数可以确定一个一维的正弦波。哪几个参数可以确定一个二维的正弦平面波呢?答案是四个,其中三个和一维的情况一样,即频率ω,幅度A,相位φ,但是具有相同这些参数的平面波却可以有不同的方向 n ⃗ \vec{n} n ,如下图所示,频率ω,幅度A,相位φ,都有一样,方向 n ⃗ \vec{n} n ,两个平面波叠加出来的效果。

在这里插入图片描述

类比一维中,幅度和相位可以用一个复数表示,它可以作为我们存储的内容。但是还有两个:一个频率一个方向。这时想到向量是有方向的,也是有长度的。所以我们用一个二维的矩阵的来保存分解之后得到的信息。这个矩阵就是K空间。就是说一个二维矩阵点 (μ ,ν) 代表这个平面波的法向量 n ⃗ \vec{n} n ,这个向量的模 μ 2 + ν 2 \sqrt{\mu^2+\nu^2} μ2+ν2 代表这个平面波的频率ω ,这个点里面保存的内容复数就是此平面波的幅度和相位。

复数(complex number):形如a+bi(a、b均为实数)的数为复数,其中,a被称为实部,b被称为虚部,i为虚数单位。

K空间(K Space):也称傅里叶空间,k空间是寻常空间在傅利叶转换下的对偶空间。“K”代表什么,字母“k”在光学、声学、力学和电磁学领域已经使用了一个多世纪,k=1/ λ \lambda λ,其中 λ \lambda λ表示波长,因此,k是每单位距离的波数或周期数。

在这里插入图片描述

好了讲到这里,我们回归正题,数字水印到底怎么实现,以下就是基本流程,简单步骤如下:

  • 原始图像A经过傅里叶变换得到K空间图像B。
  • 将水印内容写到K空间图像B,得到叠加图像C。
  • 对图像C进行傅里叶逆变换等到添加了数字水印的图像D,该图像D在视觉上和A没什么区别。
    在这里插入图片描述

那么解密流程就很简单了,对D进行一次傅里叶变换就能得到图像C,视觉上就能看到水印了。

java+OpenCV实现

可以参考这篇文章opencv的java-maven-idea开发环境配置进行配置OpenCV的开发环境。我用的opencv的4.6.0版本,下面是数据盲水印的java代码实现,仅供学习参考:

package tools;import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import java.util.ArrayList;
import java.util.List;public class ImgWatermarkUtil {private static List<Mat> planes = new ArrayList<Mat>();private static List<Mat> allPlanes = new ArrayList<Mat>();public static Mat addImageWatermarkWithText(Mat image, String watermarkText){Mat complexImage = new Mat();Mat padded = splitSrc(image);padded.convertTo(padded, CvType.CV_32F);planes.add(padded);planes.add(Mat.zeros(padded.size(), CvType.CV_32F));Core.merge(planes, complexImage);Core.dft(complexImage, complexImage);Scalar scalar = new Scalar(0, 0, 0);Point point = new Point(40, 40);Imgproc.putText(complexImage, watermarkText, point, Imgproc.FONT_HERSHEY_DUPLEX, 1D, scalar);Core.flip(complexImage, complexImage, -1);Imgproc.putText(complexImage, watermarkText, point, Imgproc.FONT_HERSHEY_DUPLEX, 1D, scalar);Core.flip(complexImage, complexImage, -1);return antitransformImage(complexImage, allPlanes);}public static Mat getImageKSpace(Mat image){Mat complexImage = new Mat();Mat padded = splitSrc(image);padded.convertTo(padded, CvType.CV_32F);planes.add(padded);planes.add(Mat.zeros(padded.size(), CvType.CV_32F));Core.merge(planes, complexImage);Core.dft(complexImage, complexImage);Scalar scalar = new Scalar(0, 0, 0);Point point = new Point(40, 40);Mat magnitude = createOptimizedMagnitude(complexImage);planes.clear();return magnitude;}public static Mat getImageWatermarkWithText(Mat image){List<Mat> planes = new ArrayList<Mat>();Mat complexImage = new Mat();Mat padded = splitSrc(image);padded.convertTo(padded, CvType.CV_32F);planes.add(padded);planes.add(Mat.zeros(padded.size(), CvType.CV_32F));Core.merge(planes, complexImage);Core.dft(complexImage, complexImage);Mat magnitude = createOptimizedMagnitude(complexImage);planes.clear();return magnitude;}private static Mat splitSrc(Mat mat) {mat = optimizeImageDim(mat);Core.split(mat, allPlanes);Mat padded = new Mat();if (allPlanes.size() > 1) {for (int i = 0; i < allPlanes.size(); i++) {if (i == 0) {padded = allPlanes.get(i);break;}}} else {padded = mat;}return padded;}private static Mat antitransformImage(Mat complexImage, List<Mat> allPlanes) {Mat invDFT = new Mat();Core.idft(complexImage, invDFT, Core.DFT_SCALE | Core.DFT_REAL_OUTPUT, 0);Mat restoredImage = new Mat();invDFT.convertTo(restoredImage, CvType.CV_8U);if (allPlanes.size() == 0) {allPlanes.add(restoredImage);} else {allPlanes.set(0, restoredImage);}Mat lastImage = new Mat();Core.merge(allPlanes, lastImage);return lastImage;}private static Mat optimizeImageDim(Mat image) {Mat padded = new Mat();int addPixelRows = Core.getOptimalDFTSize(image.rows());int addPixelCols = Core.getOptimalDFTSize(image.cols());Core.copyMakeBorder(image, padded, 0, addPixelRows - image.rows(), 0, addPixelCols - image.cols(),Core.BORDER_CONSTANT, Scalar.all(0));return padded;}private static Mat createOptimizedMagnitude(Mat complexImage) {List<Mat> newPlanes = new ArrayList<Mat>();Mat mag = new Mat();Core.split(complexImage, newPlanes);Core.magnitude(newPlanes.get(0), newPlanes.get(1), mag);Core.add(Mat.ones(mag.size(), CvType.CV_32F), mag, mag);Core.log(mag, mag);shiftDFT(mag);mag.convertTo(mag, CvType.CV_8UC1);Core.normalize(mag, mag, 0, 255, Core.NORM_MINMAX, CvType.CV_8UC1);return mag;}private static void shiftDFT(Mat image) {image = image.submat(new Rect(0, 0, image.cols() & -2, image.rows() & -2));int cx = image.cols() / 2;int cy = image.rows() / 2;Mat q0 = new Mat(image, new Rect(0, 0, cx, cy));Mat q1 = new Mat(image, new Rect(cx, 0, cx, cy));Mat q2 = new Mat(image, new Rect(0, cy, cx, cy));Mat q3 = new Mat(image, new Rect(cx, cy, cx, cy));Mat tmp = new Mat();q0.copyTo(tmp);q3.copyTo(q0);tmp.copyTo(q3);q1.copyTo(tmp);q2.copyTo(q1);tmp.copyTo(q2);}
}
import org.opencv.imgcodecs.Imgcodecs;import java.net.URL;import static org.opencv.imgcodecs.Imgcodecs.imread;
import static org.opencv.imgcodecs.Imgcodecs.imwrite;public class Main {static{loadDll();}public static void main(String[] args){Mat img = imread("E:/software/opencv/Img.jpg");Mat kSpaceImg = ImgWatermarkUtil.getImageKSpace(img);Mat outImg = ImgWatermarkUtil.addImageWatermarkWithText(img,"zhulangfly");imwrite("E:/software/opencv/Img-kSpaceImg.jpg",kSpaceImg);imwrite("E:/software/opencv/Img-out.jpg",outImg);Mat watermarkImg = ImgWatermarkUtil.getImageWatermarkWithText(outImg);imwrite("E:/software/opencv/Img-watermark.jpg",watermarkImg);}public static void loadDll() {System.setProperty("java.awt.headless", "false");System.out.println(System.getProperty("java.library.path"));URL url = ClassLoader.getSystemResource("dlls/opencv_java460.dll");System.load(url.getPath());}
}
    <dependency><groupId>org.openpnp</groupId><artifactId>opencv</artifactId><version>4.6.0-0</version></dependency>

参考文献

  • 数字水印技术在前端落地的思考
  • 阿里巴巴公司根据截图查到泄露信息的具体员工的技术是什么?
  • 通俗讲解:图像傅里叶变换
  • 形象理解二维傅里叶变换
  • 傅里叶变换交互式入门
  • opencv的java-maven-idea开发环境配置
  • Java使用OpenCV:基于DCT变换 实现 图片 数字 的盲水印添加和提取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/143004.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

python自动打开网页_python 自动批量打开网页的示例

python 自动批量打开网页的示例 如下所示&#xff1a; import webbrowser import codecs import time with open("test.txt") as fp: for ebayno in fp: url http://ebay.com/itm/ebayno.strip() time.sleep(1) #打开间隔时间 webbrowser.open(url) #打开网…

【bat批处理】手把手教你批量打开软件、文件、网页等

【bat批处理】打开软件、文件等 0- 前言1- start 命令用法1.0 注释1.1 start 命令说明1.2 启动软件1.3 打开文件1.4 打开文件夹1.5 打开网页 2-实战2.0 怎么创建bat批处理文件2.1 打开软件、文件、网页2.2 微信多开2.3 定时关机2.4 取消定时关机2.5 显示桌面图标 3 小结 0- 前言…

认识Vue中组件利器-插槽Slot-案例介绍

一. 插槽的使用 1.1. 认识插槽slot 在开发中&#xff0c;我们会经常封装一个个可复用的组件&#xff1a; 前面我们会通过props传递给组件一些数据&#xff0c;让组件来进行展示&#xff1b; 但是为了让这个组件具备更强的通用性&#xff0c;我们不能将组件中的内容限制为固定…

IDEA汉化后转回英文,只要三步

如果你觉得本文对你有帮助&#xff0c;麻烦动动手指顶一下

IntelliJ IDEA全界面汉化(官方插件)

现在很多人用IntelliJ IDEA写java代码&#xff0c;但小白很苦恼&#xff0c;看不懂&#xff0c;今天来分享一下怎么汉化 因为现在IDEA官方是支持汉化了&#xff0c;所以我们直接使用IDEA的插件 4. 下载Chinese汉化包&#xff08;第二个&#xff09; 重启IDEA就可以看到页面都变…

IDEA汉化及如何改回英文界面版本

相信很多小伙伴们刚接触IDEA时&#xff0c;看到一堆英文界面不知道如何下手&#xff0c;今天教大家一个插件直接将界面中文版本&#xff0c;以及改回英文版本。建议点赞收藏哈&#xff01; 一&#xff1a;汉化 1.打开左侧file,按箭头所示2.搜索Chinese&#xff0c;安装内存大的…

【IntelliJ IDEA】如何安装汉化插件

我使用的是2020.1的版本 汉化方式: 打开idea 点击settings 选择plugins 在marketplace 搜索 Chinese install之后 点击restart ide即可 汉化后的样子: 用不习惯也可以打开plugins 点开 installed将插件移除

IDEA汉化之2021版本

打开最新版本的IDEA后在浏览器直接进入Chinese (Simplified) Language Pack / 中文语言包 - IntelliJ IDEs | JetBrains&#xff0c;点击右上角&#xff0c;IDEA中会出现弹窗&#xff0c;直接起飞&#xff01;

IDEA汉化教程(一分钟即可)

Idea汉化教程&#xff08;简单&#xff0c;一分钟即可&#xff09; 步骤 打开idea点击左上角的File&#xff0c;然后点击Settings&#xff08;如下图&#xff09; 进去后点击Plugins&#xff0c;然后点击Marketplace&#xff0c;然后再搜索框搜索 chinese 然后搜索出东西&…

idea中文版插件

IDEA怎么设置成中文&#xff1f; 首先点击左上角的File-Settings 进入设置 进入Settings后点击Plugins&#xff0c;在搜索框输入Chinese language pack&#xff0c;点击install安装插件 下载成功后&#xff0c;点击installed,找到下载的汉化插件&#xff0c;点击Restart IDE&…

IntelliJ IDEA中文汉化教程

在找IDEA汉化的过程中&#xff0c;看了好多都没有说第二步的小问题&#xff08;问题虽小&#xff0c;但是也还是会有困扰的人&#xff0c;比如我&#xff0c;所以写了一篇可以解决这个问题的小文章&#xff0c;记录一下处理问题的结果&#xff0c;也希望能帮助到跟我一样的被困…

Intellij IDEA设置中文界面(汉化)

因为现在IDEA官方是支持汉化了&#xff0c;所以我们可以直接使用IDEA的插件来设置。这简直是我们这些英语小白的福音啊啊&#xff08;想起以前刚刚上手满屏英文&#xff0c;一头两大...它认识我我不认识它&#xff0c;这是神马感jio&#xff01;&#xff01;&#xff01;&#…

IDEA汉化

1、下载 resources_cn.jar &#xff08;下载路径&#xff1a;http://www.downza.cn/soft/211722.html&#xff09; 2、打开idea安装目录&#xff0c;打开lib文件夹 3、将 resources_cn.jar 文件复制到lib&#xff0c;重启idea就OK了 4、如果汉化后发现设置&#xff08;Setting&…

2020版 IDEA怎样汉化与怎样切换为英化

害&#xff0c;容我先吐槽吐槽&#xff0c;我这大半天时间用来解决IDEA2017版本占CPU高达80%的问题&#xff0c;还又时不时来个未响应。然鹅–就是各种办法都试了&#xff0c;结果一打开&#xff0c;还是原样子。没办法&#xff0c;我卸载了2017版本&#xff0c;直接安装了2020…

IDEA 2020.1官网汉化插件安装

idea 终于更新了2020.1版本&#xff08;推荐使用2020的版本&#xff09;&#xff0c;新增了好多的特性&#xff0c;官方也终于支持了中文语言包&#xff0c;但是有些兄弟下载后在插件市场无法找到官方的汉化包等问题&#xff0c;请安装下面操作即可&#xff1a; 1、去IDEA插件…

idea汉化教程

1.同样的&#xff0c;第一步&#xff0c;打开软件 2.进入软件后依次点击file→settings 3.接着点击plugins 4.然后点击Marketplace&#xff08;在线搜索插件&#xff09; 5.在搜索框输入chinese&#xff08;看到这个名字&#xff0c;知道是啥了吧&#xff09;&#xff0c;找到C…

如何汉化IDEA

汉化IDEA 距离上次写博客已经过去很久了&#xff0c;期间一直在写前端页面&#xff0c;最近也写后端打开了IDEA发现界面全是英语有些看不懂&#xff0c;想必有人也会跟我一样&#xff0c;接下来我给大家分享下如何汉化IDEA。 1、首先我们百度搜索“Github”&#xff0c;进入官…

IntelliJ IDEA官方汉化教程

IntelliJ IDEA官方汉化教程 MacOS 汉化步骤截图 MacOS 汉化 步骤 启动IntelliJ IDEA找到中文语言包插件 Plugins->在搜索栏中输入关键词“Chinese”->Chinese(Simplified) Language Pack /中文语言包 安装中文插件&#xff1a;Install重启IntelliJ IDEA确认汉化结果 截…

idea 使用中文汉化包教程

知识链接&#xff1a; mybatis 百度百科 mybatis 入门 Maven 存储库 idea 新建maven项目 mybatis 依赖注入详解 认识 idea Maven 存储库 idea 使用中文汉化包教程 maven 依赖打开方式 如何导入项目&#xff0c;如何连接数据库 idea 的安装 idea 新…

IDEA汉化包安装和卸载

idea 终于更新了2020.1版本&#xff08;推荐使用2020的版本&#xff09;&#xff0c;新增了好多的特性&#xff0c;官方也终于支持了中文语言包 在设置之前先查看版本号: 安装方式一: 1.打开设置 2.选择插件选项,搜索Chinese ​(Simplified)​ Language Pack EAP 3.下载完成…