Inverting an Image using NumPy’s Broadcasting method

Inverting an Image using NumPy’s Broadcasting method

Introduction

In this article, we will learn how to invert an image using NumPy. To get some gist of this, let’s have two values 0 and 1. Here 0 represents Black and 1 represents White. When we apply inversion to these values, we get:

  • 0 → inverted → 1
  • 1 → inverted → 0

The above only works when we have two values. 0 for low and 1 for high. If we were to relate the same with the Binary Image whose pixel values are just 1’s and 0's. The inversion would be reversed. To put it in words we can say from White and Black to Black and White.

Credits of Cover Image - Photo by Jr Korpa on Unsplash

Broadcasting

Unlike lists, if we want to add a number to the values of the list. We iterate through each element and add the number. Whereas, in NumPy, we need not iterate through each element and add. Instead, we can treat the array list as a single element and add the number. NumPy automatically adds that number to all the elements of the array list. This technique is called broadcasting.

The broadcasting technique is applicable to both matrices and arrays. It is very fast when compared to normal loops.

>>> import numpy as np
>>> M = np.array([1, 2, 3, 4, 5, 6])
>>> M = 3 + M
>>> M
array([4, 5, 6, 7, 8, 9])
>>>

Let’s see the demonstration for a random matrix.

White — Black

A simple demonstration of the White — Black matrix and the image can be seen below.

  • 1 is visualized as White
  • 0 is visualized as Black
>>> import numpy as np
>>> image_b = np.array([
...     [1,0,1],
...     [1,1,0],
...     [0,1,1]])
>>> image_b
array([[1, 0, 1],
       [1, 1, 0],
       [0, 1, 1]])
>>>

If we visualize the above matrix, we can see something like the below.

wb_sample.png

Black — White

A simple demonstration of the Black — White matrix and the image can be seen below.

  • 1 is changed to 0 → Black
  • 0 is changed to 1 → White
>>> # Broadcasting
>>> image_i = 1 - image_b
>>> # image_i = ~ image_b
>>> image_i
array([[0, 1, 0],
       [0, 0, 1],
       [1, 0, 0]])
>>>

If we visualize the above matrix, we can see something like the below.

bw_sample.png

To convert a matrix into an inverted matrix we can also use the operation ‘~'. It works in the same way.

If you want to know specifically how to convert an image into binary, you can refer to my article where I explain the procedure for both colored and grayscale images.

The above implementation worked since the images are already binarized. What if we wanted to apply this for a colored and non-binarized image? The scenarios will be different. Let’s find out what we can do for those.


Time to Code

The packages that we mainly use are:

  • NumPy
  • Matplotlib
  • OpenCV

python_packages.png

Import the Packages

import numpy as np
import cv2
import json
from matplotlib import pyplot as plt

Read the Image

def read_this(image_file, gray_scale=False):
    image_src = cv2.imread(image_file)
    if gray_scale:
        image_src = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY)
    else:
        image_src = cv2.cvtColor(image_src, cv2.COLOR_BGR2RGB)
    return image_src

The above function reads the image either in grayscale or RGB and returns the image matrix.

Code Implementation with Library

For inverting an image using the cv2 library, we can use the method bitwise_not() which is available in the library. We can just pass the image matrix as an argument in the method.

def invert_lib(image_file, with_plot=False, gray_scale=False):
    image_src = read_this(image_file=image_file, gray_scale=gray_scale)
    cmap_val = None if not gray_scale else 'gray'
    image_i = cv2.bitwise_not(image_src)

    if with_plot:
        fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(10, 20))

        ax1.axis("off")
        ax1.title.set_text('Original')

        ax2.axis("off")
        ax2.title.set_text("Inverted")

        ax1.imshow(image_src, cmap=cmap_val)
        ax2.imshow(image_i, cmap=cmap_val)
        return True
    return image_i

The above function returns the inverted image of the original image that is passed. The same can be seen when plotted.

Let’s test the above function —

invert_lib(image_file='lena_original.png', with_plot=True)

invertlc_lena.png

invert_lib(image_file='lena_original.png', with_plot=True, gray_scale=True)

invertlg_lena.png

We have obtained the inverted images for both colored and grayscale images.

Code Implementation from Scratch

In order to invert the image, we have to apply the broadcasting technique using NumPy. We have to subtract each pixel value from 255. It is because the highest pixel value or color value is 255 in an image. Either way, we can apply the ‘~’ (negation) operation to the image.

def invert_this(image_file, with_plot=False, gray_scale=False):
    image_src = read_this(image_file=image_file, gray_scale=gray_scale)
    # image_i = ~ image_src
    image_i = 255 - image_src

    if with_plot:
        cmap_val = None if not gray_scale else 'gray'
        fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(10, 20))

        ax1.axis("off")
        ax1.title.set_text('Original')

        ax2.axis("off")
        ax2.title.set_text("Inverted")

        ax1.imshow(image_src, cmap=cmap_val)
        ax2.imshow(image_i, cmap=cmap_val)
        return True
    return image_i

Let’s test the above function —

invert_this(image_file='lena_original.png', with_plot=True)

invertlc_lena.png

invert_this(image_file='lena_original.png', with_plot=True, gray_scale=True)

invertlg_lena.png

This is it! We have successfully written the code for converting the image into an inverted image. The results are similar to that of the library code.

Let’s see what will it result in when applied to the binarized image. I have put the result without the code.

binary_inverted.png

The inverted image is exactly opposite to the binarized image. Hence this concludes the agenda of this article.

You should definitely check out my other articles on the same subject in my profile.


If you liked it, you can buy coffee for me from here.

bmc-button.png