尝试使用频域FFT隐写术隐藏JPEG图片中的信息,但加密后无法得到正确的输出图片

问题描述 投票:0回答:1

我正在研究频域隐写术。我的任务是使用FFT隐藏JPEG图片中的文本信息。我用 C# 编写了一些代码,用于拍摄图片,为 FFT 算法做好准备,并使用 FFT 计算其频域。输入图片为here,FFT算法的结果为here。然后此代码获取文本消息,从图片中获取复数值并更改该复数值的 LeastSignificantBit (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");
c# .net fft frequency steganography
1个回答
0
投票

经过一些研究,我发现最好不要使用LSB方法,而是改变频域的“空”值并添加或减去频率数据的实部。 “空”值是从频率数据中获取的

ComplexImage[x, y]
的实际值,等于零。在此代码中,我使用左上角来查找“空”值。此外,在穿过频域时,最好避免频域中间,因为它可能会导致麻烦和不正确的编码数据。一些加密代码示例:

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;
    }

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

© www.soinside.com 2019 - 2024. All rights reserved.