图像隐写术

图像 · 浏览次数 : 55

小编点评

**图像隐写术原理** 图像隐写是一种通过在图像中隐藏信息的技术。通常,这种技术用于保护敏感信息,例如密码或敏感数据。 **隐写方法** 在隐写之前,图像首先被分割成一个个像素。每个像素被编码为一个整数,表示其在图像中的位置。编码过程通常使用 font 文件,其中每个字节代表一个像素的颜色。 **隐写步骤** 1. 读取图像并对其进行像素编码。 2. 使用 font 文件生成一个隐写图像。 3. 将隐写图像与原始图像进行比较,以确保隐写信息已成功隐藏。 **隐写技术** 隐写技术利用以下几种技术来隐藏信息: * **像素近似**:在编码之前,图像的像素被近似为其他像素。这种技术使隐写图像与原始图像相似, making it harder for an attacker to detect the hidden information. * **字体渲染**:在隐写之前,图像被渲染为单个颜色通道。这种技术使隐写图像的每个像素仅代表一个字节,从而减少了信息量。 * **掩码**:可以在隐写图像中添加一个掩码,该掩码可以用于识别隐写图像的区域。 **项目代码** 您没有提供项目代码,因此我无法详细解释隐写技术的实现。

正文

图像隐写术

本文为图像的隐写提供了一种思路。还有更多的思路,这里不做讲述。

项目源代码在:jeefies/jimg-ivs 中。

原理

利用了像素近似用肉眼难以察觉的前提(这就是为什么 jpeg 会存在……

以及 png 图片会原滋原味的保留像素数据,而不是像 jpeg 一样神秘的变化。

而这里并没有采用利用 8bit 像素最后几位来保存数据的方式,而是采用字体渲染,只在某一个颜色通道中展现文本(只读)。

所在通道中的每一个 8bit 位中,有 64 个取值表示被渲染的像素。

也就是说,要做一个近似处理。

至于如何渲染……利用了 SDL_ttf 来完成这件事。

实现

这次我没有继续使用 dlang 写这个小小的项目。而是纯纯只用了 C++,主要是比较方便,因为不仅使用了 SDL,还使用了 opencv,实在是不想封装一层。

Canvas

这是用来渲染文本的东西。由于一行能显示的文本有限,所以需要适当的裁剪。

一一裁剪太慢了,所以考虑倍增求解。

学算法的好处……仅此一点

int len = 0, lg = (int)log2(s.size()) + 1;
for (int step = 1 << lg; step; step >>= 1) {
    if (len + step <= s.size()) {
        int clen = len + step;
        while (clen > len && !checkCompleteUTF8(s.substr(0, clen)))
            --clen;
        TTF_SizeUTF8(font, s.substr(0, clen).c_str(), &sw, &sh);
        if (x + sw < w) len = clen;
    }
}

但是,你可能关注到了 checkCompleteUTF8,这是用于解决中文被截断无法完整渲染的问题(这个参考 utf8 编码方式)

// Important when showing Chinese!
bool checkCompleteUTF8(const std::string &s) {
	char nBytes = 0;

	for (unsigned char c : s) {
		if (nBytes == 0 && c >= 0x80) {
			if (0xFC <= c && c <= 0xFD) nBytes = 6;
			else if (0xF8 <= c) nBytes = 5;
			else if (0xF0 <= c) nBytes = 4;
			else if (0xE0 <= c) nBytes = 3;
			else if (0xC0 <= c) nBytes = 2;
			else return false;
			--nBytes;
		} else if (nBytes) {
			if ((c & 0xC0) != 0x80) return false;
			--nBytes;
		}
	}

	if (nBytes > 0) return false;
	return true;
}

注意,必须要用 unsigned char

近似处理

核心部分。

void invisibleWrite(SDL_Surface *sur, cv::Mat &mat) {
	SDL_LockSurface(sur);

	int w = sur->w, h = sur->h;
	Uint32 * pixels = (Uint32 *)sur->pixels;

	auto threeSumPixel = [](Uint32 cl) {
		return ((cl & 0xFF) + ((cl >> 8) & 0xFF) + ((cl >> 16) & 0xFF)) / 3;
	};

	auto discrete = [](unsigned char x) -> unsigned char { return (unsigned char)((round((double)x / 8)) * 8 - 1); };

	for (int i = 0; i < h; ++i) {
		int base = i * w;
		unsigned char* data = mat.ptr<unsigned char>(i);
		for (int j = 0; j < w; ++j) {
			if (threeSumPixel(pixels[base + j]) > 128) 
				data[j] = discrete(data[j]);
			else if (data[j] == discrete(data[j])) 
				data[j] = data[j] == 0 ? 1 : data[j] - 1;
		}
	}

	SDL_UnlockSurface(sur);
}

其中呢,mat 表示图像分离后的一个通道。使用的 cv::split 函数完成。

相信我写的代码还是不难读明白的……

读入处理

cv::Mat encode(int channel_id = GREEN) {
	cv::Mat newImage;
	if (!_open) return newImage;
	std::vector<cv::Mat> channels;
	cv::split(image, channels);

	showRendered(cvs.getSurface(), 10);
	invisibleWrite(cvs.getSurface(), channels[channel_id]);
	cv::merge(channels, newImage);

	return newImage;
}

这是从 JIVS_Encoder 中截出来的一段代码。


其他部分的代码与上文代码类似……只要理解的上文中的代码,其他部分也就很好写了。

反正我写了这么多封装也就写了 294 行。不多,1 天就可以再写一遍 QwQ


其实吧

这种隐写术很难看破,因为没有对图像二进制文件做出任何的变动,并且像素的近似也是肉眼难以察觉,所以完全可以成为和神秘的人说神秘的话的一种途径吧(就是只能传输文本信息)。

如果要二进制,可能还是利用掩码或者神秘的异或来完成更好。

与图像隐写术相似的内容:

图像隐写术

# 图像隐写术 本文为图像的隐写提供了一种思路。还有更多的思路,这里不做讲述。 项目源代码在:[jeefies/jimg-ivs](https://gitlab.com/jeefies/jimg-ivs) 中。 [TOC] ## 原理 利用了像素近似用肉眼难以察觉的前提(这就是为什么 `jpeg`

神经网络图像数据训练集成应用 | 可视化图像处理 | 可视化训练器

〇、写在前面 本应用基于开源UI框架PyDracula进行开发,除去最基本的UI框架外,所有功能的前后端实现都由我个人开发完成,但也有部分UI(如开关控件和进度条)是参考其他大佬的分享。 这个应用是我的本科毕业设计,但因为个人能力不足,姑且只能使用Python+PySide6开发。 开发这个应用的启

屏幕图像渲染原理

对于一个客户端开发来说,平时做的的最多的就是写页面,所以有必要了解从视图代码到图像显示到屏幕上的整个过程和原理。 下面以从视图代码到显示器图像的中间产物帧缓冲区图像位图为目标,分析从视图代码到帧缓冲区位图和从帧缓冲区位图到显示器图像这2个过程。 这里把这2个过程命名为:帧缓冲区数据怎么来的、帧缓冲区

在WPF中使用WriteableBitmap对接工业相机及常用操作

写作背景 写这篇文章主要是因为工业相机(海康、大恒等)提供的.NET开发文档和示例程序都是用WinForm项目来说明举例的,而在WPF项目中对图像的使用和处理与在WinForm项目中有很大不同。在WinForm中用System.Drawing.Bitmap来处理图像,而在WPF中是用System.W

Vue 处理异步加载顺序问题:在Konva中确保文本在图片之上显示

Vue 处理异步加载顺序问题:在Konva中确保文本在Konva之上显示 在使用Konva开发应用时,我们经常会遇到需要将文本绘制在图片之上的情况。一个常见的问题是,由于图像加载是异步的,文本有时会显示在图片下方。这篇博客将总结如何正确处理这种异步加载顺序问题。 我之前写过一篇博客,主要是为了说明如

[转帖]FIO 存储性能压测

一、 FIO简介 FIO 是一个多线程IO生成工具,可以生成多种IO模式(随机、顺序、读、写四大类),用来测试磁盘设备的性能。GFIO是FIO的图形监测工具,它提供了图形界面的参数配置,和性能监测图像。 在github上的链接为 https://github.com/axboe/fio 二、 FIO

[转帖]FIO 存储性能压测

一、 FIO简介 FIO 是一个多线程IO生成工具,可以生成多种IO模式(随机、顺序、读、写四大类),用来测试磁盘设备的性能。GFIO是FIO的图形监测工具,它提供了图形界面的参数配置,和性能监测图像。 在github上的链接为 https://github.com/axboe/fio 二、 FIO

ScreenToGif:一款开源免费且好用的录屏转Gif软件

ScreenToGif介绍 GitHub上的介绍:此工具允许您记录屏幕的选定区域、来自网络摄像头的实时提要或来自草图板的实时绘图。之后,您可以编辑动画并将其保存为 gif、apng、视频、psd 或 png 图像。 在平常写公众号的过程中,经常有录屏转Gif的需求,我就是使用ScreenToGif做

人工智能AI图像风格迁移(StyleTransfer),基于双层ControlNet(Python3.10)

图像风格迁移(Style Transfer)是一种计算机视觉技术,旨在将一幅图像的风格应用到另一幅图像上,从而生成一幅新图像,该新图像结合了两幅原始图像的特点,目的是达到一种风格化叠加的效果,本次我们使用Stable-Diffusion结合ControlNet来实现图像风格迁移效果。 安装Contr

从0到1学Python丨图像平滑方法的两种非线性滤波:中值滤波、双边滤波

摘要:常用于消除噪声的图像平滑方法包括三种线性滤波(均值滤波、方框滤波、高斯滤波)和两种非线性滤波(中值滤波、双边滤波),本文将详细讲解两种非线性滤波方法。 本文分享自华为云社区《[Python从零到壹] 五十六.图像增强及运算篇之图像平滑(中值滤波、双边滤波)》,作者:eastmount。 常用于