Image Pre-Processing through OpenCV (Part 3)

Read Time: 5 min

In part-1 and part-2, we discussed basic terminology used in image processing, functions like denoising, threshold, rescaling, smoothing. Here comes part-3. In this section, I have explained masking, blending, sharpening, transformation, erosion and dilation. All these are used in image processing very frequently.

Let’s check one by one.

Table of content:

  • Masking
  • Blending
  • Image sharpening
  • Geometric transformation
    • Image translation
    • Scaling
    • Rotation
    • Affine transformation
    • Perspective transformation
  • Erosion
  • Dilation

Masking

Masking is overlapping of one image to another. It is used to block out some portion of one image by overlapping of either complete or partial section of another image.

If we understand it at pixel level, only one source image’s pixel is present at one point in the resulted image. Another source image pixel is blacked out by previous source image. Let’s understand it by example.

Masking is a type of filtering that uses bitwise operations to get the result image.

‘AND’ function returns zero if in both the images either of the two pixels at a point is zero. If both the pixels are 255 then return 255.

‘OR’ function returns zero if in both the images corresponding pixels at a point are zero otherwise returns 255.

If Colored image is given as input to ‘and’ function then it finds the minimum of the two images for each pixel

For ‘or’ function it finds the maximum value of pixel at that point.

Let’s understand it’s code:

img1 = cv2.imread('image_1.png')
img2 = cv2.imread('image_2.png')
plt.figure(figsize=(20,10))
plt.subplot(121),plt.imshow(img1),plt.title('Input1')
plt.subplot(122),plt.imshow(img2),plt.title('Input2')
plt.show()
Output:
Masking using 'and' and 'or' bitwise operation:
result = cv2.bitwise_and(img2, img1)
result_or = cv2.bitwise_or(img2, img1) 
plt.figure(figsize=(20,10))
plt.subplot(121),plt.imshow(result),plt.title('output_and')
plt.subplot(122),plt.imshow(result_or),plt.title('output__or')
# plt.subplot(1),plt.imshow(result),plt.title('Output')
plt.show()
Output for colored images
Masking using xor and not bitwise operation:
result = cv2.bitwise_xor(img2, img1)
result_or = cv2.bitwise_not(img2, img1) 
plt.figure(figsize=(20,10))
plt.subplot(121),plt.imshow(result),plt.title('output_xor')
plt.subplot(122),plt.imshow(result_or),plt.title('output__not')
# plt.subplot(1),plt.imshow(result),plt.title('Output')
plt.show()
Output:
For black and white images:
circle = cv2.imread('circle.png')
square = cv2.imread('square.png')
plt.figure(figsize=(20,10))
plt.subplot(121),plt.imshow(circle),plt.title('Input1')
plt.subplot(122),plt.imshow(square),plt.title('Input2')
# plt.subplot(1),plt.imshow(result),plt.title('Output')
plt.show()
Input images:
Masking using 'And' and 'or' operation:
result = cv2.bitwise_and(circle,square)
result_or = cv2.bitwise_or(circle,square)
plt.figure(figsize=(20,10))
plt.subplot(121),plt.imshow(result),plt.title('output_and')
plt.subplot(122),plt.imshow(result_or),plt.title('output__or')
plt.show()

Blending

Blending means mixing of two images. Blending of two images includes addition or subtraction of pixels i.e. arithmetic operations.

It’s like you can see both source images in the resulting image with varied intensity.

There is one more type of blending we can perform using opencv i.e. alpha blending. According to the requirement weights are taken for blending of two images to decide which one will have dominant effect on the resulting image.

It’s like you can see both source images in the resulting image with varied intensity.

Blending can be done in many ways like linear blending, Poisson blending, Feather blending, Alpha blending, Laplacian blending, Multi-band blending, Gradient blending.

img3 = cv2.imread('zebra.jpg')
img3 = cv2.cvtColor(img3, cv2.COLOR_BGR2RGB)
img4 = cv2.imread('sea.jpg')
img4 = cv2.cvtColor(img4, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(20,10))
plt.subplot(121),plt.imshow(img3),plt.title('zebra')
plt.subplot(122),plt.imshow(img4),plt.title('sea')
plt.show()
Input images:
Alpha blending
dim =(275,183) 
img3 = cv2.resize(img3, dim, interpolation = cv2.INTER_AREA)
result_blending = cv2.addWeighted(img3,0.2,img4,0.5,10)
plt.imshow(result_blending)

Blending using addition

result_add = cv2.add(img3,img4) 
plt.imshow(result_add)

Blending using subtraction

result_subtraction = cv2.subtract(img3,img4) 
plt.imshow(result_subtraction)

Geometric transformation

Using opencv four types of geometric transformations are possible:

  • Image translation
  • Scaling (already covered in part-2)
  • Rotation
  • Affine transformation
  • Perspective transformation

Image Translation

Image translation refers image shifting through it’s co-ordinates in rectilinear fashion.

It is generally used in convolution process where kernel as filter are moved around the whole image. By using image translation, animation of moving object can also be created by keeping shifting process in loop.

Let’s understand it via code:

img5 = cv2.imread('zebra.jpg',0)
rows,cols = img5.shape

Mf = np.float32([[1,0,100],[0,1,40]])
result = cv2.warpAffine(img5,Mf,(cols,rows))
cv2.imshow('translated',result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Output:

Rotation

It is used to rotate the image from a particular angle.

rows,cols = img5.shape
M = cv2.getRotationMatrix2D((cols/2,rows/2),60,1)
dst = cv2.warpAffine(img5,M,(cols,rows))
plt.imshow(dst)
Output:

Affine transformation

Through this transformation preserves the proportion between the lines. Usually it is to correct geometric distortion occurred in the image.

img6 = cv2.imread('zebra.jpg')
rows,cols,ch = img6.shape

pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])

M = cv2.getAffineTransform(pts1,pts2)

dst = cv2.warpAffine(img6,M,(cols,rows))

plt.subplot(121),plt.imshow(img6),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
Output:

Perspective transformation

Perspective transformation used to convert 3D world to 2D world. It deals the images like human eye does when an object is far or near.

rows,cols,ch = img6.shape

pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])

M = cv2.getPerspectiveTransform(pts1,pts2)

dst = cv2.warpPerspective(img6,M,(100,100))

plt.subplot(121),plt.imshow(img6),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
Output:

Image Sharpening

Sharpening filter, enhance the edges and fine details present in the image. Level of sharpening depends on kernel size used for sharpening.

sharpening can be done using unsharp masking. Through this process, first extraction of Gaussian blur image is done then it is subtracted with the original image so that smooth part can be filtered out.

Method-1: Unsharp masking

img_ori = cv2.imread("zebra.jpg")
img_ori = cv2.cvtColor(img_ori, cv2.COLOR_BGR2RGB)
image = cv2.GaussianBlur(img_ori,(5,5), 3);
result = cv2.addWeighted(img_ori,1.5,image,-0.7,50)
plt.figure(figsize=(40,30))
plt.subplot(121),plt.imshow(img_ori),plt.title('Input')
plt.subplot(122),plt.imshow(result),plt.title('Output')
plt.show()
Output:

Method-2 using fixed kernel and 2D filtering

img_ori = cv2.imread("zebra.jpg")
img_ori = cv2.cvtColor(img_ori, cv2.COLOR_BGR2RGB)
kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
im = cv2.filter2D(img_ori, -1, kernel)
cv2.imwrite("zebra_sharpen2.jpg",im)
plt.figure(figsize=(40,30))
plt.subplot(121),plt.imshow(img_ori),plt.title('Input')
plt.subplot(122),plt.imshow(im),plt.title('Output')
plt.show()
Output: 

Dilation

Dilation is a convolution process in which a kernel is used to for convolution with the whole image. As kernel starts covolving the image maximum value of the pixel is computed and image pixel at that position is replaced by maximum value pixel.

In short, bright pixels become more brighter.

Let’s check the code to do it.

img2 = cv2.imread('book.jpg', 0) 
img2 = cv2.cvtColor(img2, cv2.COLOR_RGB2BGR)
kernel = np.ones((2,2), np.uint8) 
img_dilation = cv2.dilate(img2, kernel, iterations=1)
plt.figure(figsize=(40,30))
plt.subplot(121),plt.imshow(img2),plt.title('Input')
plt.subplot(122),plt.imshow(img_dilation),plt.title('Output')
plt.show()

Output:

dilation

Erosion

Erosion is reverse of dilation where darker pixels become more darker.

In erosion minimal pixel value is computed when kernel starts convolution over the image and image pixel of that position is replaced with the minimal valued pixel.

Best use of erosion technique is in Optical Character Recognition where text can be converted into bolder one.

img1 = cv2.imread('book.jpg') 
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
kernel = np.ones((2,2), np.uint8) 
img_erosion = cv2.erode(img1, kernel, iterations=1) 
#plt.imshow(img_erosion)
plt.figure(figsize=(40,30))
plt.subplot(121),plt.imshow(img1),plt.title('Input')
plt.subplot(122),plt.imshow(img_erosion),plt.title('Output')
plt.show()
output:

Here is the link for github code:

https://github.com/Appiiee/Image-Pre-processing-using-OpenCV