.net 利用频域FFT隐写技术在JPEG图像中隐藏信息,但加密后不能得到正确的输出图像

nle07wnf  于 2023-11-20  发布在  .NET
关注(0)|答案(1)|浏览(142)

我正在研究频域隐写术,我的任务是利用FFT在JPEG图片中隐藏文本信息。我用C#编写了一些代码,它拍摄一张图片,准备FFT算法并使用FFT计算其频域。输入图片为here,FFT算法的结果为here。然后此代码得到文本消息,从图片中获取复数值并更改此复数值的最低有效位(LSB)。在此之后,我们在this pucture中修改了频域,如您所见,有一条从中心到右侧加密的消息。但是当我尝试在修改后的图片中使用IFFT时,输出的结果是white picture。很明显我在改变频域的时候损坏了图片。这段代码有什么问题吗?
下面是详细注解的代码:

// Uploading image
        var image = AForge.Imaging.Image.FromFile("input.jpg");

        // Find the nearest power of 2 dimensions
        int width = (int)Math.Pow(2, Math.Ceiling(Math.Log(image.Width, 2)));
        int height = (int)Math.Pow(2, Math.Ceiling(Math.Log(image.Height, 2)));
        // Resize the image to the nearest power of 2 dimensions
        Bitmap resizedImage = new Bitmap(image, width, height);

        // Converting image to grayscale
        Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721);
        Bitmap grayImage = filter.Apply(resizedImage);

        // Converting image to the ComplexImage
        ComplexImage complexImage = ComplexImage.FromBitmap(grayImage);

        // Applying FFT
        complexImage.ForwardFourierTransform();

        // Saving result of FFT
        complexImage.ToBitmap().Save("fourier.jpg");

        // -------------------------------------------------------------------------

        // Converting text message to binary
        string textMessage = "Hello world";
        byte[] messageBytes = Encoding.Unicode.GetBytes(textMessage);
        BitArray messageBits = new BitArray(messageBytes);

        // Embedding text bits into the frequency domain
        int bitIndex = 0;
        for (int y = complexImage.Height / 2; y < complexImage.Height; y++)
        {
            for (int x = complexImage.Width / 2; x < complexImage.Width; x++)
            {
                if (bitIndex >= messageBits.Length)
                {
                    break;
                }

                // Getting complex value of frequency
                Complex complexValue = complexImage.Data[y, x];

                // Replacing the LSB of the real and imaginary parts with a bit from the message
                complexValue.Re = SetLeastSignificantBit(complexValue.Re, messageBits[bitIndex++]);
                complexValue.Im = SetLeastSignificantBit(complexValue.Im, messageBits[bitIndex++]);

                // Applying new value
                complexImage.Data[y, x] = complexValue;
            }
        }

        // Setting LSB
        static float SetLeastSignificantBit(double value, bool bit)
        {
            int intValue = BitConverter.ToInt32(BitConverter.GetBytes(value), 0);
            intValue = bit ? (intValue | 1) : (intValue & ~1);
            return BitConverter.ToSingle(BitConverter.GetBytes(intValue), 0);
        }

        // -------------------------------------------------------------------------

        complexImage.ToBitmap().Save("fourier222.jpg");

        // Applying IFFT
        complexImage.BackwardFourierTransform();

        complexImage.ToBitmap().Save("output.jpg");

字符串

busg9geu

busg9geu1#

经过研究,我知道最好不要使用LSB方法,而是改变频域的“null”值,加上或减去频率数据的真实的部分。“Null”值是从频率数据中取的ComplexImage[x, y]的真实的值,它等于零。在本代码中,我使用左上角找到“null”。值。此外,在频域中移动时,最好避免频域的中间,因为它可能会导致麻烦和不正确的编码数据。一些加密代码示例:

public static ComplexImage EmbedData(ComplexImage freqDomain, byte[] data)
    {
        ComplexImage modifiedFreqDomain = freqDomain;
        int xCoordinate = 0;
        int yCoordinate = 0;

        if (data.Length * 8 > modifiedFreqDomain.Data.Length)
        {
            throw new Exception("Data too large to embed into the frequency domain");
        }

        int bitIndex = 0;
        for (int k = 0; k < data.Length; k++)
        {
            for (int i = 0; i < 8; i++)
            {
                int bit = (data[k] >> i) & 1;
                double realPart = modifiedFreqDomain.Data[xCoordinate, yCoordinate].Re;

                if (bit == 1)
                {
                    realPart += 0.00025;
                }
                else
                {
                    realPart -= 0.00025;
                }

                modifiedFreqDomain.Data[xCoordinate, yCoordinate] = new Complex(realPart, modifiedFreqDomain.Data[xCoordinate, yCoordinate].Im);

                yCoordinate += 1;

                if (yCoordinate >= freqDomain.Width / 2.5)
                {
                    yCoordinate = 0;
                    xCoordinate += 1;
                }
                bitIndex++;
            }
        }

        return modifiedFreqDomain;
    }

字符串
当我使用此代码进行加密时,图像可能会略有变化,但它并不重要。此外,此算法应检查“非空”值,因为我们不能从中获取数据。因此,有一些方法可以改进此方法,但基本上它是有效的。

相关问题