Table of Contents
Introduction Core Operations in Image Processing
In this article, you will understand how to perform Core Operations in Image Processing, how to change the size of the pixels. Core Operations in Image Processing such as image padding, image addition, and many more functions.
Basic Operations on Images
Now Learn to, Access pixel values and modify them, Access image properties, Set a Region of Interest (ROI), Split, and merge images. Almost all the operations in this section are mainly related to Numpy rather than OpenCV.
Import Required Library
import cv2 as cv
import numpy as np
Read Image
Img = cv.imread(“messi.jpeg”)
You can access a pixel value by its row and column coordinates. For the BGR image, it returns an array of Blue, Green, Red values. For grayscale images, just corresponding intensity is returned.
px = img[100, 100]
print(px)
array([92, 79, 81], dtype=uint8)
#accessing only blue pixel
bl_px = img[100,100,0]
print(bl_px)
92
#modifying the pixel value
img[100,100] = [255,255,255]
print(img[100,100])
[255 255 255]
NOTE: The above method is normally used for selecting a region of an array, say the first 5 rows and last 3 columns. For individual pixel access, the Numpy array methods, array.item(), and array.itemset() are considered better. They always return a scalar, however, so if you want to access all the B, G,R values, you will need to call array.item() separately for each value.
#accessing RED value
img.item(10,10,2)
Output - 64
#modify RED Value
img.itemset((10,10,2),100)
img.item(10,10,2)
Output - 100
#accessing image properties
print(img.shape)
Output - (776, 1300, 3)
NOTE: If an image is grayscale, the tuple returned contains only the number of rows and columns, so it is a good method to check whether the loaded image is grayscale or color.
The total number of pixels is accessed by “img.size”
print(img.size)
Output- 3026400
print(img.dtype)
Output- uint8
NOTE: img.dtype is very important while debugging because a large number of errors in OpenCV-Python code are caused by invalid datatype.
Image ROI
images. For eye detection in images, first face detection is done over the entire image. When a face is obtained, we select the face region alone and search for eyes inside it instead of searching the whole image. It improves accuracy (because eyes are always on faces 😀 ) and performance (because we search in a small area).
ROI is again obtained using Numpy indexing. Here I am selecting the ball and copying it to another region in the image:
Splitting and Merging Image Channels
b,g,r = cv.split(img)
img = cv.merge((b,g,r))
OR
b = img[ :, :, 0]
Suppose you want to set all the red pixels to zero - you do not need to split the channels first. Numpy indexing is faster:
img[: ,:, 2] = 0
Making Borders for Images (Padding)
If you want to create a border around an image, something like a photo frame, you can use cv.copyMakeBorder(). But it has more applications for convolution operation, zero padding etc. This function takes following arguments:
- src – input image
- top, bottom, left, right – border width in number of pixels in corresponding directions
- borderType – Flag defining what kind of border to be added. It can be following types:
- cv.BORDER_CONSTNAT – Adds a constant colored border. The value should be given as the next argument.
- cv.BORDER_REFLECT- Border will be mirror reflection of the border elements, like this : fedcba|abcdefgh|hgfedcb
- cv.BORDER_REFLECT_101 OR cv.BORDER_DEFAULT – Same as above, but with a slight change, like this : gfedcb|abcdefgh|gfedcba
- cv.BORDER_REPLICATE- Last element is replicated throughout, like this: aaaaaa|abcdefgh|hhhhhhh
- cv.BORDER_WRAP – Can’t explain, it will look like this : cdefgh|abcdefgh|abcdefg
- value – Color of border if border type is cv.BORDER_CONSTANT
Below is a sample code demonstrating all these border types for better understanding:
- Arithmetic Operations on Image
Understanding the several arithmetic operations on images, like addition, subtraction, bitwise operations, and etc.
Image Addition
You can add two images with the OpenCV function, cv.add() or simply by the NumPy operation res = img1 + img2. Both images should be of the same depth and type, or the second image can just be a scalar value.
There is a difference between OpenCV addition and Numpy addition. OpenCV addition is a saturated operation while Numpy addition is a modulo operation.
x = np.uint8([250])
y = np.uint8([10])
print( cv.add(x,y) )
Output => 255
print( x+y )
Output =[4]
See the difference.
Bitwise Operations
This includes the bitwise AND, OR, NOT, and XOR operations. They will be highly useful while extracting any part of the image, defining and working with non-rectangular ROI, and etc. Below we will see an example of how to change a particular region of an image.
I want to put the OpenCV logo above an image. If I add two images, it will change the color. If I blend them, I get a transparent effect. But I want it to be opaque. If it was a rectangular region, I could use ROI as we did in the last chapter. But the OpenCV logo is not a rectangular shape. So you can do it with bitwise operations as shown below:
# Load two images
img1 = cv.imread('messi.jpeg')
img2 = cv.imread('ml.jpeg')
# I want to put logo on top-left corner, So I create a ROI
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols]
# Now create a mask of logo and create its inverse mask also
img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY)
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
mask_inv = cv.bitwise_not(mask)
# Now black-out the area of logo in ROI
img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv)
# Take only region of logo from logo image.
img2_fg = cv.bitwise_and(img2,img2,mask = mask)
# Put logo in ROI and modify the main image
dst = cv.add(img1_bg,img2_fg)
img1[0:rows, 0:cols ] = dst
cv.imshow('res',img1)
cv.waitKey(0)
cv.destroyAllWindows()
Conclusion
Understand, read the image and change its pixels. When printing an image without cv library output only a pixel number in matrix form. Then understand the adding the image and blending with the pixel.