Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error level analysis in Image

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 at 95% quality jpeg image and using absDiff method to compute the difference between the source image and the resaved image but all I am getting is zero difference.

Any help on how to compute the difference between two images so as to obtain the error level just like sample images in the tutorial?

like image 433
user973743 Avatar asked Jan 30 '14 18:01

user973743


People also ask

What does ELA stand for in photography?

Error Level Analysis (ELA) permits identifying areas within an image that are at different compression levels. With JPEG images, the entire picture should be at roughly the same level. If a section of the image is at a significantly different error level, then it likely indicates a digital modification.

Is there a way to tell if a photo has been photoshopped?

Look at the light Another way to spot a picture that's been photoshopped is by examining the way light interacts with the objects in the photo. Shadows and highlights will appear to violate the laws of physics, especially when a subject has been removed or added to a photo.

Is there an app that detects Photoshop?

PRO TIP: There is no app that can detect if an image has been edited in Photoshop. However, there are many online tools and websites that can help you determine if an image has been edited.


1 Answers

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
like image 131
Eliezer Bernart Avatar answered Nov 09 '22 23:11

Eliezer Bernart