我正在开发基于LSB-DCT的图像隐写技术,其中我必须将LSB应用于图像的DCT系数,以便将数据嵌入到JPEG中。我是所有这些的新手。所以搜索并阅读了一些研究论文在DCT之后缺乏关于该过程的大量信息。我也在stackoverflow上阅读了许多问题和答案,并且更加困惑。
以下是问题:
1-reasearch论文并且在网上有问题他们都在使用图像中的8x8块大小用于DCT ..如果图像的分辨率没有完全划分为8x8块,如724 x 520,我该怎么做。
520/8 = 65但724/8 = 90.5
2 - 如果我有很多块和一些隐藏的信息,我们认为这些信息可以容纳5个块。我仍然需要使用其余块的dct和idct。
3 - 我需要在dct之后应用量化然后应用lsb或者我可以直接应用lsb吗?
4篇研究论文没有提到任何关于不接触量化0和1的量化dct系数和第一个值的任何内容。现在我应该使用它们吗?那么为何不??我得到它关于0,因为它是高频成分,并在JPEG中删除压缩..我没有做任何压缩..所以我可以使用它仍然生成相同的JPEG文件???
5-in量化我们将DCT系数除以量化矩阵并将值四舍五入。反过来,我必须将量化矩阵与DCT系数相乘..没有取消舍入???
有关DCT的评论,然后是IDCT:
答案 0 :(得分:4)
如果要将图像保存为jpeg,则必须遵循jpeg编码过程。不幸的是,我读过的大多数论文都说不要公平。完整的过程如下(wiki summary的182-page specifications book):
实际上有a lot more details involved,例如标题,节标记,如何存储DC和AC系数的细节等等。然后,有些方面标准只是松散定义,它们的实现可以在编解码器,例如,子采样算法,量化表和熵编码。也就是说,大多数软件都遵循通用的JFIF标准,可以通过各种软件读取。如果您希望您的jpeg文件也这样做,请准备好为编码器编写数百行(至大约一千行)代码。您最好借用已经在互联网上发布的编码器,而不是自己编写。您可以首先查看用C语言编写的libjpeg,并构成许多其他jpeg编解码器的基础,它的C# implementation甚至Java版本受其启发。
在某些伪代码中,编码/解码过程可以描述如下。
function saveToJpeg(pixels, fileout) {
// pixels is a 2D or 3D array containing your raw pixel values
// blocks is a list of 2D arrays of size 8x8 each, containing pixel values
blocks = splitBlocks(pixels);
// a list similar to blocks, but for the DCT coefficients
coeffs = dct(blocks);
saveCoefficients(coeffs, fileout);
}
function loadJpeg(filein) {
coeffs = readCoefficients(filein);
blocks = idct(coeffs);
pixels = combineBlocks(blocks);
return pixels;
}
对于隐写术,您可以按如下方式修改它。
function embedSecretToJpeg(pixels, secret, fileout) {
blocks = splitBlocks(pixels);
coeffs = dct(blocks);
modified_coeffs = embedSecret(coeffs, secret);
saveCoefficients(modified_coeffs, fileout);
}
function extractSecretFromJpeg(filein) {
coeffs = readCoefficients(filein);
secret = extractSecret(coeffs);
return secret;
}
如果您的封面图片已经在jpeg中,则无需使用解码器将其加载到像素,然后将其传递给编码器以嵌入您的消息。你可以这样做。
function embedSecretToJpeg(pixels, secret, filein, fileout) {
coeffs = readCoefficients(filein);
modified_coeffs = embedSecret(coeffs, secret);
saveCoefficients(modified_coeffs, fileout);
}
就您的问题而言,编码器/解码器应该处理1,2,3和5,除非您自己写一个。
问题1 :通常,您希望使用必要数量的行/列填充图像,以便宽度和高度都可以被8整除。在内部,编码器将跟踪填充行/列,以便解码器在重建后丢弃它们。这些虚拟行/列的像素值的选择取决于您,但建议您不要使用常量值,因为它将导致ringing artifacts,这与傅里叶变换的事实有关。方波是sinc函数。
问题2 :虽然您只修改了几个块,但编码过程要求您将它们全部转换,以便将它们存储到文件中。
问题3 :您必须将浮动DCT系数量化为无损保存到文件中的内容。在量化步骤之后,您可以将它们修改为您心脏的内容。
问题4 :没有人会阻止您修改任何系数,但您必须记住每个系数会影响一个块中的所有64个像素。 DC系数和low frequency AC引入最大的失真,因此您可能希望远离它们。更具体地说,由于DC系数的存储方式,修改一个系数会将失真推向所有后续的块。
由于大多数高频系数为0,因此可以使用RLE有效地压缩它们。修改0系数可能会将其翻转为1(如果您正在进行基本的LSB替换),这会破坏这种有效的压缩。
最后,一些算法将其秘密存储在任何非零系数中,并且将跳过任何0。但是,如果您尝试修改1,它可能会翻到0,在提取过程中,您会盲目地跳过它。因此,这些算法不会接近任何值为1或0的系数。
问题5 :在解码时,只需将系数乘以相应的量化表值即可。例如,DC系数为309.443,量化为您提供round(309.443 / 16) = 19
。舍入位是这里的有损部分,它不允许你重建309.433。所以相反的只是19 * 16 = 304
。
频率变换,例如DCT和DWT,可用于隐写术,将秘密嵌入频域,但不一定将隐秘图像存储到jpeg。这个过程是像素 - > DCT - >系数 - >修改系数 - > IDCT - >像素,这是你发送给接收器的。因此,格式的选择在这里很重要。如果您决定将像素保存为jpeg,则通过jpeg编码中的另一层量化将您的秘密保存在DCT系数may be disturbed中。