Reputation: 21
Nowdays I got a code to extract RGB values and calculate the differences between the two given images, but I noticed a problem in one image that made me stop to think if I'm doing it right.
This is my code:
import cv2
import math
dif_R = 0
dif_G = 0
dif_B = 0
img = cv2.imread("image1.jpg", cv2.IMREAD_COLOR)
imgcom = cv2.imread("image2.jpg", cv2.IMREAD_COLOR)
pixel = 100 / (img.shape[0] * img.shape[1])
for ih in range(img.shape[0]):
for iw in range(img.shape[1]):
pixelB, pixelG, pixelR = img[ih][iw]
pixelR = int(pixelR)
pixelG = int(pixelG)
pixelB = int(pixelB)
pixelcomB, pixelcomG, pixelcomR = imgcom[ih][iw]
pixelcomR = int(pixelcomR)
pixelcomG = int(pixelcomG)
pixelcomB = int(pixelcomB)
if pixelR != pixelcomR:
dif = math.fabs(pixelR - pixelcomR)
dif_R += (dif / 255) * pixel
if pixelG != pixelcomG:
dif = math.fabs(pixelG - pixelcomG)
dif_G += (dif / 255) * pixel
if pixelB != pixelcomB:
dif = math.fabs(pixelB - pixelcomB)
dif_B += (dif / 255) * pixel
print(dif_R, dif_G, dif_B)
And my images are this: https://i.sstatic.net/QnVuG.jpg
As you can see if exec the code, the differences are 11.78 for R, 14.02 for G and 16.66 for B. But you can clearly see how the first image is purple and the other orange.
I see an optional method, is using the lab colorspace. The differences with this method going high but I need rgb values... and dont know what should i do...
How can solve this issue or do other thing to take a best accurate differences? im doing anything wrong in my code?
Upvotes: 1
Views: 2676
Reputation: 207445
Try to avoid using for
loops with Numpy, it is fully vectorised:
import cv2
import numpy as np
# Load images
im1 = cv2.imread("image1.jpg", cv2.IMREAD_COLOR)
im2 = cv2.imread("image2.jpg", cv2.IMREAD_COLOR)
# Calculate absolute differences
absdiff = np.abs(im1.astype(np.float) - im2.astype(np.float))
# Calculate mean error for each channel
Berr = np.mean(absdiff[...,0])
Gerr = np.mean(absdiff[...,1])
Rerr = np.mean(absdiff[...,2])
You could write the last 3 lines as:
Berr, Gerr, Rerr = [np.mean(absdiff[...,chan]) for chan in {0,1,2}]
Upvotes: 1
Reputation: 887
I'd like to first point out that the way you have tried accomplish this goal is highly inefficient - there is absolutely no need to loop over pixel values one by one when dealing with images. Numpy is very strong with vectoric operations, saving you valuable time, especially when dealing with large numbers of images. I'm supplying you with a different implementation which, from my understanding of the problem, should solve your problem.
from PIL import Image
import numpy as np
def jpg_image_to_array(image_path):
"""
Loads JPEG image into 3D Numpy array of shape (width, height, channels)
in double precision
"""
with Image.open(image_path) as image:
im_arr = np.fromstring(image.tobytes(), dtype=np.uint8)
im_arr = im_arr.reshape((image.size[1], image.size[0], 3)) /255
return im_arr
img1 = jpg_image_to_array("1.jpg")
img2 = jpg_image_to_array("2.jpg")
diff = np.absolute(img1 - img2)
print(np.sum(diff,axis=(0,1)))
Note that this code computes the absolute difference between the R,G,B channels, and then sums this difference up. The result for your images :
[289702.61960608 344853.21176722 409960.28628742]
Where the first-third numbers are the sum of differences in the R,G,B channels respectively. This makes sense to me, seeing there are 1281 x 1920 pixels in your image.
If you are looking for the average difference, you can divide this list by the number of pixels, which is:
n_pixels = img1.shape[0]*img1.shape[1]
which results in:
[0.11778828 0.14021159 0.16668305]
Upvotes: 1