Возврат объекта Mat в Java в OpenCV 3.2 - PullRequest
0 голосов
/ 14 декабря 2018

Я пытаюсь создать класс Java для реализации стеганографии LSB-изображений.

Для этого я использую OpenCV 3.2.

Я написал логику кодирования в методе encodeImage(String message)класса LSBImageStego, который будет принимать секретное сообщение и кодировать его в заданном изображении обложки (изображение обложки будет взято конструктором).

Я могу изменять значения пикселей путем изменения битов LSB(Я изменяю биты LSB только одного канала). Я использую MatObj.put(row,col,data) для записи новых значений пикселей. Я пытался напечатать эти новые значения пикселей после put(), и значения пикселей были успешно изменены.

Я возвращаю CoverImage (поскольку я внес изменения путем кодирования сообщения) и сохраняю изображение с помощью imwrite().

Теперь, когда я пытаюсь декодировать EncodedImage, я обнаружил, чтоИзображение имело значения старого пикселя, но не значения кодированного пикселя. Это указывает на то, что, хотя я написал значения кодированного пикселя, используя put() в encodeImage(String message), объект Mat не возвращался.

Здесьтрескаe для encodeImage(String message) класса LSBImageStego

/**
getBeautifiedBinaryString()

Returns a binary string of length 8 by taking a number.
This function is working perfectly.

 */
/**
binaryStringMessage

is a private String in the class & contains the Binary form of the Secret Message.
 */


/**
    This function takes Secret Message and replaces 2 bits from LSB(First Channel of Image)
    with the bits of Message
 */
public Mat encodeImage(String message){

/**
        //coverImage is a Mat Object & following is the code in constructor of a class
        this.coverImage = coverImage;
        this.coverImage_rows = (int)coverImage.size().height;
        this.coverImage_cols = (int)coverImage.size().width;


*/
        System.out.println("Number of Rows : " + this.coverImage_rows);
        System.out.println("Number of Columns : " + this.coverImage_cols);

//      This is used as a pointer in the BinaryString ,so that,it can be embedded easily
        int messageStringCounter = 0;
        for(int rowCount = 0 ; rowCount <= this.coverImage_rows -1 ; rowCount++){
            for(int colCount = 0; colCount <= this.coverImage_cols -1 ; colCount++){
                try{

                    if(messageStringCounter > this.binaryStringMessage.length() - 2 ){
                        System.out.println("RETURNING pic");
                        return this.coverImage;
                    }
                    String newLSBBits = this.binaryStringMessage.substring(messageStringCounter , messageStringCounter+2);
                    System.out.println(">> "+messageStringCounter + " >> " + newLSBBits);
                    messageStringCounter+=2;
                    System.out.println("ORIGINAL : "+this.getBeautifiedBinaryString(this.coverImage.get(rowCount , colCount)[0]));
                    String modifiedBinaryString = this.getBeautifiedBinaryString(this.coverImage.get(rowCount , colCount)[0]).substring(0 , this.getBeautifiedBinaryString(this.coverImage.get(rowCount , colCount)[0]).length() - 2) + newLSBBits;
                    System.out.println("MODIFIED : " + modifiedBinaryString);
                    double[] data = new double[3];
                    data[0] = Integer.parseInt(modifiedBinaryString , 2);
                    data[1] = this.coverImage.get(rowCount , colCount)[1];
                    data[2] = this.coverImage.get(rowCount , colCount)[2];

                    // Im checking whether the Pixel values are being changed as expected or not.
                    System.out.println("BEFORE : " + this.coverImage.get(rowCount , colCount)[0]);
                    this.coverImage.put(rowCount , colCount , data);
                    System.out.println("AFTER : " + this.coverImage.get(rowCount , colCount)[0]);
                    // The Pixel values were changed as expected
                }catch(Exception e){
                    System.out.println("Exception Handled");
                }
            }
        }
        return this.coverImage;
}

, и я вызываю вышеуказанный метод из main() в другом классе следующим образом.

public class Imple {
    static{
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }
    public static void main(String[] args){
        Imgcodecs imageCodecs = new Imgcodecs();

        Mat mat = imageCodecs.imread("C:\\Users\\XYZ\\Desktop\\test.jpg");

        LSBImageStego obj = new LSBImageStego(mat);
        String message = "Hello World";
        if(obj.checkEncodePossibility(message)){
            System.out.println("OK");
        }else{
            System.out.println("NO");
        }
        Mat encodedImage = obj.encodeImage(message).clone();
        imageCodecs.imwrite("C:\\Users\\XYZ\\Desktop\\test_ENCODED.jpg" ,encodedImage );


        Mat mat2 = imageCodecs.imread("C:\\Users\\XYZ\\Desktop\\test_ENCODED.jpg");

//      While debugging the Below function,I found that the Changed Pixel values were not being written back to the Disk
        obj.decodeImage(mat2);
//         In the above method,as part of debugging,I'm printing the Pixel values to the console.

    }

}

Я позаботилсядругих логик, таких как длина двоичной строки сообщения нечетная или четная и т. д. ...

Единственная проблема заключается в том, что EncodedImage, который я сохраняю на диск, не содержит значения кодированных пикселей.

Пожалуйста, предложите.

Заранее спасибо:)

1 Ответ

0 голосов
/ 14 декабря 2018

JPEG выполняет сжатие с потерями. Так что значения закодированных пикселей будут потеряны, и существует высокая вероятность того, что это будет то же самое старое исходное значение пикселя, что и изменяется только LSB интенсивности пикселей. Но это не такс PNG или растровым изображением.

Считайте это , чтобы получить больше информации об алгоритме сжатия JPEG.

...