leonardean/StegoQR
GitHub: leonardean/StegoQR
基于离散小波变换和SURF特征检测的图像隐写系统,可在任意图像中隐藏信息并支持盲提取与有损压缩容忍。
Stars: 2 | Forks: 2
# StegoQR
基于隐写术的新一代二维码
## 现象
QR code(Quick Response Code,快速响应码)是首先为日本汽车工业设计的一种矩阵条码的商标。它通过相机等成像设备读取,并由底层软件根据图像水平和垂直分量中存在的图案进行算法解释。由于“智能手机”的普及,QR code 已被作为一种在促销、活动和娱乐等各个领域使用静态图像传递文本信息的方法。然而,当前的 QR code 有一个明显的缺点,即外观不够美观,因为它是单色的,并且对人类来说没有太大意义。受隐写术启发,本项目旨在制作美观的 QR code,通过一种将文本信息嵌入到任意图像中而不对图像外观产生明显变化的方法来实现。
## 定义
隐写术提供了一种将信息隐藏到音频、图像和视频等媒体中的方法。结合加密,它被证明甚至更加安全。隐写术通常被定义为以隐蔽方式进行通信的艺术和科学。与将明文更改为密文(窃听者无法理解)的密码学不同,隐写术技术试图隐藏消息本身的存在。在数字隐写术中,要编码的原始图像称为载体图像(cover-image),编码后的图像称为隐写图像(stego-image)。其中一个典型的实现是通过修改像素域中像素的最低有效位(LSB)的值将信息嵌入到载体图像中。
## 目标
信息可以被隐藏在图像中而不被人眼察觉。然而,上述方案在以下情况下很脆弱:
* 由于上述方法涉及像素域中的颜色值修改,因此在解码时,它强烈依赖于隐写图像像素采样的准确性。当数据嵌入的点在提取时可能处于噪声中时,数据提取可能不准确。
* 上述方法不耐颜色改变。它要求在图像从编码器传输到解码器的过程中进行无损数据保存。因此,当接收端的隐写图像可能被压缩、过滤或模糊时,数据提取可能不准确。
* 隐写术是不同步的,也就是说,从上述隐写图像中提取数据需要载体图像。
为了克服上述限制, proposed scheme 将把信息隐藏在载体图像的区域而不是每个像素中。更具体地说,信息将以基于内容的方式隐藏在载体图像的离散小波变换(DWT)域中,因为它具有能够捕获频率和位置信息(优于 Fourier 变换)并逐像素地清晰划分高频和低频信息的优势。此外,将应用加速稳健特征(SURF)技术以通用地获取感兴趣区域。因此,将实现隐写术同步,以便数据提取将允许有损压缩和噪声;数据提取过程也将是完全盲的,因为只需要隐写图像。
## 附加价值
通常,通过极大地改善其外观同时保持其功能特性来重新定义当前的 QR code 将是革命性的。在技术上,将隐藏信息编码到图像中而不明显改变其外观具有挑战性。此外,启用解码数据丢失容忍度是前所未有的。作为一个持续的项目,一旦该项目完成,我还想将解码器移植到移动设备平台,如 Android 和 iOS。
## 算法关键词:
* SURF 检测
* 关键点消除

* Pre-DWT 变换
* 扩展技术

* 双正交和正交
* 小波的选择 (BIOR 4.4, Cohen-Daubechies-Feauveau 9/7 小波)
* 数据嵌入
* DWT 变换



```
//--2d discrete wavelet transform with symmetric extension
void* Wavelet2d::dwt_2d (vector > &signal, // original signal
int J, //number of decomposition levels
string name, //wavelet name
vector & dwt_output, //output coefficients
string command, //whether to embed or extract
String &message_bit) { //bits to be embedded
// initialize filters
vector lp, hp, lpr, hpr;
for (int iter = 0; iter < J; iter ++) {
//assign decomposition and restruction filter coefficients
filter_coef(name, lp, hp, lpr, hpr);
//initialize output coefficients:
//cA-approximation
//cH-horizontal
//cV-vertical
//cD-diagonal
vector > cA(rows, vector(cols));
vector > cH(rows, vector(cols));
vector > cV(rows, vector(cols));
vector > cD(rows, vector(cols));
//convert 2d signal to 1d signal
for (int i = 0; i < rows; i ++) {
vector signal_1d;
for (int j = 0; j < cols; j ++) {
double tmp = signal[i][j];
signal_1d.push_back(tmp);
}
}
//apply dwt to get coefficients
vector > lp_dn(rows, vector(cols_lp));
vector > hp_dn(rows, vector(cols_hp));
//row filtering and column down sampling in each branch/
dwt_1d(name, signal_1d, lp_output, hp_output); //1-D DWT
for (int j = 0; j < (int) lp_output.size(); j ++) {
lp_dn[i][j] = lp_output[j];
hp_dn[i][j] = hp_output[j];
}
//column filtering and row down sampling in low pass branch/
dwt_1d(name, col_lp_dn, lp_output, hp_output); //1-D DWT
for (int j = 0; j < (int) lp_output.size(); j ++) {
cA[i][j] = lp_output[j];
cV[i][j] = hp_output[j];
}
//column filtering and row down sampling in low pass branch/
dwt_1d(name, col_hp_dn, lp_output, hp_output); //1-D DWT
for (int j = 0; j < (int) lp_output.size(); j ++) {
cH[i][j] = lp_output[j];
cD[i][j] = hp_output[j];
}
//at the last level of dwt, embed the bits
if (iter == J - 1) {
if (command == "embed") {
embed(cH, cV, message_bit); //pay load bit embedding as discussed before
} else if (command == "extract") {
extract(cH, cV, message_bit); //pay load bit extraction to be explained
}
}
//allocating coefficients into the output signal, which is the frequency domain of the
//original image or region
dwt_output = alloc_coeff(cA, cH, cV, cD);
}
}
```
* 逆 DWT 变换

* 数据提取
标签:HTTP工具, LSB隐写, meg, OpenCV, Python, QR码, Steganography, 二维码, 二维码生成器, 信息安全, 信息隐藏, 图像处理, 多媒体安全, 抗篡改, 数字图像, 数字水印, 数据加密, 无后门, 生成算法, 生成艺术, 计算机视觉, 隐写术, 隐蔽通信