Error level analysis in Image

后端 未结 1 1014
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-02-06 10:03

How do I compute ELA for an image? I would like to get similar ELA image using opencv http://fotoforensics.com/tutorial-ela.php

As per this tutorial, I resaved the image

相关标签:
1条回答
  • 2021-02-06 10:28

    The key to achieve a similar result is to use a variable value for the compression rate and a scale factor to make it easier to visualize the data.

    Here's an example: we have the input image (left) and the processed image after some parameter adjustments (right):

    As expected, the region with the christmas hat presents a different compression rate from the rest of the image. This result is very similar to what FotoForensics presents:

    With a few tweaks on this code you can achieve an even closer result. The source code of this project can be found on my Github:

    main.cpp:

    #include <opencv2/highgui/highgui.hpp>
    #include <iostream>
    #include <vector> 
    
    // Control
    int scale = 15,
        quality = 75;
    
    // Image containers
    cv::Mat input_image,
        compressed_image;
    
    void processImage(int, void*)
    {
       // Setting up parameters and JPEG compression
       std::vector<int> parameters;
       parameters.push_back(CV_IMWRITE_JPEG_QUALITY);
       parameters.push_back(quality);
       cv::imwrite("temp.jpg", input_image, parameters);
    
       // Reading temp image from the disk
       compressed_image = cv::imread("temp.jpg");
    
       if (compressed_image.empty())
       {
          std::cout << "> Error loading temp image" << std::endl;
          exit(EXIT_FAILURE);
       }
    
       cv::Mat output_image = cv::Mat::zeros(input_image.size(), CV_8UC3);
    
       // Compare values through matrices
       for (int row = 0; row < input_image.rows; ++row)
       {
        const uchar* ptr_input = input_image.ptr<uchar>(row);
        const uchar* ptr_compressed = compressed_image.ptr<uchar>(row);
        uchar* ptr_out = output_image.ptr<uchar>(row);
    
            for (int column = 0; column < input_image.cols; column++)
            {
                // Calc abs diff for each color channel multiplying by a scale factor
                ptr_out[0] = abs(ptr_input[0] - ptr_compressed[0]) * scale;
                ptr_out[1] = abs(ptr_input[1] - ptr_compressed[1]) * scale;
                ptr_out[2] = abs(ptr_input[2] - ptr_compressed[2]) * scale;
    
                ptr_input += 3;
                ptr_compressed += 3;
                ptr_out += 3;
            }
        }
    
        // Shows processed image
        cv::imshow("Error Level Analysis", output_image);
    } 
    
    int main (int argc, char* argv[])
    {
       // Verifica se o número de parâmetros necessário foi informado
       if (argc < 2)
       {
         std::cout << "> You need to provide an image as parameter" << std::endl;
         return EXIT_FAILURE;
       }
    
       // Read the image
       input_image = cv::imread(argv[1]);
    
       // Check image load
       if (input_image.empty())
       {
          std::cout << "> Error loading input image" << std::endl;
          return EXIT_FAILURE;
       }
    
       // Set up window and trackbar
       cv::namedWindow("Error Level Analysis", CV_WINDOW_AUTOSIZE);
       cv::imshow("Error Level Analysis", input_image);
       cv::createTrackbar("Scale", "Error Level Analysis", &scale, 100, processImage);
       cv::createTrackbar("Quality", "Error Level Analysis", &quality, 100, processImage);
    
       // Press 'q' to quit
       while (char(cv::waitKey(0)) != 'q') {};
    
       return EXIT_SUCCESS;
    } 
    

    Here are some nice references that were used to build this mash-up:

    • ELA with HTML5
    • FotoForensics Tutorial
    • Blackhat USA '07 Paper
    0 讨论(0)
提交回复
热议问题