OpenCV Compare values through matrices for error level analysis

Viewed 942

My aim is to generate an error level analysis workflow using opencv and python, and I found this example doing what I need, but in C++ : Error level analysis in Image

While I managed to convert a part of it I'm really stuck on the loop rows part due to my lack of C++ knowledge, so I could use some support here.

This is what I managed to convert :

path=r'C:\****\training\pop_test'
image='source.jpg'

scale = 15
jpg_quality = 75

input_image= cv2.imread(os.path.join(path, image))
w,h,d = img.shape

# save tmp compressed file 
cv2.imwrite(os.path.join(path, 'tmp.jpg'), input_image, [cv2.IMWRITE_JPEG_QUALITY, jpg_quality])
compressed_image= cv2.imread(os.path.join(path, 'tmp.jpg'))

# create matrice
output_image = np.zeros((w, h, d), dtype = "uint8")

And this is the C++ I'm having a hard time with :

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

Anyone that can point me in the right direction?

2 Answers

I think this is what you want for ELA in Python/OpenCV (from reading information at http://www.hackerfactor.com/papers/bh-usa-07-krawetz-wp.pdf

Input:

enter image description here

import cv2
import numpy as np

# read image
img1 = cv2.imread("lenna.png")

# set compression and scale
jpg_quality1 = 95
jpg_quality2 = 90
scale = 15

# write img1 at 95% jpg compression
cv2.imwrite("lenna_c95.jpg", img1, [cv2.IMWRITE_JPEG_QUALITY, jpg_quality1])

# read compressed image
img2 = cv2.imread("lenna_c95.jpg")

# get absolute difference between img1 and img2 and multiply by scale
diff1 = scale * cv2.absdiff(img1, img2)

# write img2 at 90% jpg compression
cv2.imwrite("lenna_c90.jpg", img2, [cv2.IMWRITE_JPEG_QUALITY, jpg_quality2])

# read compressed image
img3 = cv2.imread("lenna_c90.jpg")

# get absolute difference between img1 and img2 and multiply by scale
diff2 = scale * cv2.absdiff(img2, img3)

# write result to disk
cv2.imwrite("lenna_ela_95.jpg", diff1)
cv2.imwrite("lenna_ela_90.jpg", diff2)

# display it
cv2.imshow("ela95", diff1)
cv2.imshow("ela90", diff2)
cv2.waitKey(0)


ELA result at 95%:

enter image description here

ELA result at 90%:

enter image description here

I found this code in this kaggle code. It does the same thing that the @fmw42 just added as a response, but it uses PIL library tools. I hope it come in handy:

def convert_to_ela_image(path, quality):
    temp_filename = 'temp_file_name.jpg'
    ela_filename = 'temp_ela.png'

    image = Image.open(path).convert('RGB')
    image.save(temp_filename, 'JPEG', quality = quality)
    temp_image = Image.open(temp_filename)

    ela_image = ImageChops.difference(image, temp_image)

    extrema = ela_image.getextrema()
    max_diff = max([ex[1] for ex in extrema])
    if max_diff == 0:
        max_diff = 1
    scale = 255.0 / max_diff

    ela_image = ImageEnhance.Brightness(ela_image).enhance(scale)

    return ela_image

real_image_path = '/kaggle/input/casia-dataset/casia/CASIA2/Au/Au_ani_00001.jpg'
Image.open(real_image_path)

Original fake image

convert_to_ela_image(real_image_path, 90)

Fake image error rate analysis

Related