1

我正在对 JPEG 图像执行隐写术。我正在使用DCT系数来隐藏数据。我执行以下步骤:

  1. 将输入图像读入BufferedImage
  2. BufferedImage
  3. 应用正向 DCT 以获得 DCT 系数
  4. 在 DCT 系数中嵌入消息位
  5. 应用逆 DCT 并将块写回BufferedImage

重复步骤 2-5 直到没有剩余消息位,此时我写入BufferedImage名为output.jpg. 值得一提的是,我并不适用DCT于整个图像,而仅适用于我嵌入消息位的块。我将这个源用于 DCT,这个源用于隐写术

问题:我最终ouput.jpg得到表示像素数据发生巨大变化的随机线条。以下是图像写入代码:

static int[][] DCT_coefficients = new int[8][8];
static double[][] DCT_matrix = new double[8][8];
static int[][] Dequantized_m = new int[8][8];
static int[][] YBlock = new int[8][8];
static double[][] resultant = new double[8][8];
static int[][] red = new int[8][8];
static int[][] green = new int[8][8];
static int[][] blue = new int[8][8];
static int[][] Y = new int[8][8];
static int[][] Cb = new int[8][8];
static int[][] Cr = new int[8][8];
static int x = 0, y = 0;

public static void main(String args[]) {
  //I retrieve a pixel block from **BufferedImage** and convert it to YCbCr
  double temp1, temp2, temp3, temp4;
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      Color c = new Color(input_image.getRGB(y, x));
      red = c.getRed();
      green = c.getGreen();
      blue = c.getBlue();
      YCbCr = YCrCb_conversion(red, green, blue);
      YBlock[i][j] = YCbCr[0];
      Cb[i][j] = YCbCr[1];
      Cr[i][j] = YCbCr[2];
      y++;
    }
    x++;
  }
  //calculating DCT matrix
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      if (i == 0) {
        DCT_matrix[i][j] = 1 / Math.sqrt(8.0);
      }
      if (i > 0) {
        temp1 = 0.5;
        Apfloat Atemp1 = new Apfloat(temp1, 15);
        temp3 = ((2 * j) + 1) * i * java.lang.Math.PI;
        temp2 = temp3 / 16;
        Apfloat Atemp2 = new Apfloat(temp2, 15);
        temp4 = Math.cos(java.lang.Math.toRadians(temp2));
        Apfloat Atemp4 = ApfloatMath.cos(Atemp2);
        Apfloat Atemp = Atemp4.multiply(Atemp1);
        DCT_matrix[i][j] = Atemp.doubleValue();
      }
    }
  }
  //Leveling off Yblock
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      leveledoff[i][j] = pixel_block[i][j] - 128;
    }
  }
  // multiplying DCT matrix and leveled off YBlock
  resultant = matrix_multiply(DCT_matrix, leveledoff);
  // taking transpose of DCT matrix
  transpose = obj.transpose(DCT_matrix);
  //multiplying transpose with resultant to get DCT coefficient block
  DCT_Coefficients = matrix_multiply(resultant, trans);
  //quantizing DCT coefficients using 50 % quantization matrix
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      quantized_matrix[i][j] = (int) Math.round(DCT_Coefficients[i][j] / quantzation_matrix[i][j]);
    }
  }
  //Applying zigzag encoding
  ZigZag_encoded = zigzag.ZigzagEncode(quantised_m);
  //Encode data
  ZigZag_encoded = embed_data(ZigZag_encoded, data_buffer);
  //start IDCT
  IDCT(ZigZag_Encoded);
  //end main
}

//Method definitions
//Method to change LSB of integer value
public static int changeBit(int pixel, char bit) {
  String s = Integer.toBinaryString(pixel);
  char[] c = s.toCharArray();
  c[c.length - 1] = bit;
  // converting binary to integer
  String n = "";
  for (int y = 0; y < c.length; y++) {
    n += "" + c[y];
  }
  int j = 0;
  for (int i = 0; i < n.length(); i++) {
    if (n.charAt(i) == '1') {
      j = j + pow(2, n.length() - 1 - i);
    }
  }
  return j;
}

// method to embed data
public static int[] embed_data(int encoded[], char buffer[]) {
  for (int i = 0; i < buffer.length; i++) {
    int newVal = changeBit(encoded[i], buffer[i]);
    encoded[i] = newVal;
  }
  return encoded;
}

// Method to perform IDCT
public static void IDCT(ZigZag_encoded) {
  //converting 1D zigzag array to 2D array
  quantised_matrix = Zigzag_Decode(ZigZag_encoded);
  //Dequantizing 
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      Dequantized[i][j] = quantised_matrix[i][j] * quantzation_matrix[i][j];
    }
  }
  // multiplying transpose of DCT matrix with Dequantized matrix
  resultant = matrix_multiply(transpose, Dequantized);
  //multiplying resultant with DCT matrix
  resultant = matrix_multiply(resultant, dct_mat);
  //adding 128 to each resultant entry and rounding off
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      block[i][j] = (int) Math.round(resultant[i][j] + 128);
    }
  }
  //Converting Yblock to RGB block
  YCrCbToRGB(block, Cb, Cr);
  //writing RGB block to BufferedImage
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      newcolor = new Color(red[i][j], green[i][j], blue[i][j]);
      input_image.setRGB(y, x, newcolor.getRGB());
      y++;
    }
    x++;
  }
}

//method to convert RGB block to YCbCr
public int[] YCrCb_conversion(int red, int green, int blue) {
  int[] YCbCr = new int[3];
  //Y = 0.257R+ 0.504G + 0.098B + 16
  YCbCr[0] = (int)(0.257 * red + 0.504 * green + 0.098 * blue) + 16;
  //Cb=–0.148R – 0.291G+ 0.439B + 128
  YCbCr[1] = (int)((-0.148 * red - 0.291 * green + 0.439 * blue) + 128);
  //Cr = 0.439R – 0.368G – 0.071B + 128
  YCbCr[2] = (int)((0.539 * red - 0.368 * green - 0.071 * blue) + 128);
  return value
  // index 0 holds values of Y 1 holds Cb values and 2 holds Cr vlaues
  return YCbCr;
}

//Method to convert YCbCr block to RGB block
public static void YCrCbToRGB(int y[][], int Cb[][], int Cr[][]) {
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      //R = 1.164(Y – 16) + 1.596(Cr – 128)
      red[i][j] = (int)(1.164 * (y[i][j] - 16) + (1.596 * (Cr[i][j] - 128)));
      //G = 1.164(Y – 16) – 0.813(Cr – 128) – 0.391(Cb – 128)
      green[i][j] = (int)(1.164 * (y[i][j] - 16) - (0.813 * (Cr[i][j] - 128)) - (0.391 * (Cb[i][j] - 128)));
      //B = 1.164(Y – 16) + 2.018(Cb – 128)
      blue[i][j] = (int)(1.164 * (y[i][j] - 16) + (2.018 * (Cb[i][j] - 128)));
    }
  }
}

样本输入和输出:

 pixel block in Y space as input to DCT
 223  224  226  227  229  229  230  230 
 226  227  227  227  228  229  229  230 
 228  228  228  228  228  229  230  231 
 228  228  228  228  229  231  233  234 
 227  228  229  230  231  233  234  234 
 226  227  229  230  232  233  233  233 
 227  228  230  232  232  231  229  228 
 228  230  232  234  232  229  226  223 

量化后和嵌入数据前的 DCT 系数矩阵:

 51  -1  0  0  0  0  0  0 
 -1  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 

嵌入数据后的量化 DCT 系数:

50  -1  0  1  0  0  0  0 
 -1  0  1  0  0  0  0  0 
 1  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 

嵌入数据并应用 IDCT 后,Y 空间中的像素块:

 232  227  223  223  227  231  232  231 
 230  226  222  223  226  230  230  229 
 228  224  221  222  226  229  229  227 
 226  223  221  223  227  229  228  225 
 226  224  223  225  229  230  228  225 
 227  225  225  228  232  233  230  226 
 228  227  228  231  235  236  232  228 
 230  229  230  234  237  238  233  229 

输入.jpg]

输出.jpg]

我认为这是由于 JPEG 的有损性质,所以我尝试了 PNG,但仍然遇到同样的问题。

4

0 回答 0