Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV image subtraction vs Numpy subtraction

I was trying to track how much next picture differs from the previous one, assuming some movement in the scene. Decided to apply subtraction of corresponding pixel values between two jpg images and then calculate the mean value of the resulting matrix in order to check if it's below or under some threshold level (for further analysis).

Subtraction was done by cv2.subtract and np.subtract methods. I've noticed quite big differences in the result. It seems like numpy somehow stretched the histogram and normalized resulting values, but why?

Images were loaded via cv2.open. I know this method use BGR order of channels but it doesn't explain what happened. Loaded images are numpy nd.array with np.uint values. Working on Spyder with Python 3.7.

Edit: argument 0 in cv2.imread tells to load image in greyscale

OpenCV subtraction result

Numpy subtraction result

#loading images

img_cam0 = cv2.imread(r'C:\Users\Krzysztof\Desktop\1.jpg',0)
img_cam1 = cv2.imread(r'C:\Users\Krzysztof\Desktop\2.jpg', 0)
print('img0 type:',type(img_cam0), 'and shape:', img_cam0.shape)
print('img1 type:',type(img_cam1),'and shape:', np.shape(img_cam1))
print('\n')

#opencv subtraction

cv2_subt = cv2.subtract(img_cam0,img_cam1)
cv2_mean = cv2.mean(cv2_subt)

print('open cv mean is:', cv2_mean)
f.show_im(cv2_subt, 'cv2_subtr')

#np subtraction and mean

np_subtr = np.subtract(img_cam0, img_cam1)
np_mean = np.mean(np_subtr)

print('numpy mean is:', np_mean)
f.show_im(np_subtr, 'np_subtr')
like image 768
AnotherLazyPeon Avatar asked Aug 22 '17 11:08

AnotherLazyPeon


People also ask

What is the difference between OpenCV and NumPy?

The main difference between NumPy and OpenCV addition is that NumPy addition is based on modulo operation while OpenCV uses saturated operation.

How do I subtract an image in OpenCV?

Image Subtraction You can subtract two images by OpenCV function, cv. subtract(). res = img1 - img2. Both images should be of same depth and type.

What exactly is the point of image subtraction?

Image subtraction or pixel subtraction is a process whereby the digital numeric value of one pixel or whole image is subtracted from another image. This is primarily done for one of two reasons – levelling uneven sections of an image such as half an image having a shadow on it, or detecting changes between two images.

Why NumPy is used in image processing?

Mostly we find the uses of NumPy in the problems where we are required to perform mathematical and logical operations on different sizes of arrays. Since images can also be considered as made up of arrays, we can use NumPy for performing different image processing tasks as well from scratch.


1 Answers

The difference is simple -- saturation vs. no saturation.

cv2.subtract performs saturation. According to the docs:

dst(I) = saturate(src1(I) - src2(I))

numpy.subtract just performs a regular subtraction, so the results are subject to integer overflow (i.e. the values wrap around).


Saturation means that when the input value v is out of the range of the target type, the result is not formed just by taking low bits of the input, but instead the value is clipped. For example:

uchar a = saturate_cast<uchar>(-100); // a = 0 (UCHAR_MIN)
short b = saturate_cast<short>(33333.33333); // b = 32767 (SHRT_MAX)

Such clipping is done when the target type is unsigned char , signed char , unsigned short or signed short . For 32-bit integers, no clipping is done.


Example

>>> import cv2
>>> import numpy as np

>>> a = np.arange(9, dtype=np.uint8).reshape(3,3)
>>> a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]], dtype=uint8)
>>> b = np.full((3,3), 4, np.uint8)
>>> b
array([[4, 4, 4],
       [4, 4, 4],
       [4, 4, 4]], dtype=uint8)

>>> np.subtract(b,a)
array([[  4,   3,   2],
       [  1,   0, 255],
       [254, 253, 252]], dtype=uint8)

>>> cv2.subtract(b,a)
array([[4, 3, 2],
       [1, 0, 0],
       [0, 0, 0]], dtype=uint8)
like image 62
Dan Mašek Avatar answered Sep 28 '22 16:09

Dan Mašek