In this notebook we will find the connected pixels whose RGB values are in the range of (+-10, +-10, +-10) of the current pixel location. To solve this problem we can either use an iterative or a recursive approach. I will use the latter because I love recursion. Once we have the input pixel location, we will recursive travel to the neighboring pixels that lie in our range. We will be using the Depth First Search algorithm to accomplish this task. If you are from Computer Science, you should have studied about it in algos course. Nonetheless, it is pretty easy and you can Wikipedia it. We declare a 2D array named mask
of the same size as input image and when ever our condition is met, we set that pixel location equal to True
in the mask. So let's get started -
Import the cv2
and pylab
modules. The cv2
module is used for computer vision and the pylab
environment to save the image in numpy
array and display this image using function from matlabplot
.
import cv2
%pylab inline
Populating the interactive namespace from numpy and matplotlib
Since, Python supports tail recursion only till $999$, we will change it to $10000$ using the below command.
import sys
sys.setrecursionlimit(10000)
Now, we will write the depth first search algorithm The signature of dfs function is -
dfs(x, y, r, g, b, mask, im, Prange)
Here,
x
, y
-> current pixel locationr
, g
, b
-> the RGB that we want to compare withmask
-> This will be set to True where the conditions are metim
-> The input imagePrange
-> Is the range in the RGB values that is alloweddef dfs(x, y, r, g, b, mask, im, Prange):
# Check if image dimensions are not violated and the pixel is not previously visited
if (x < 0 or y < 0 or x == im.shape[1] or y == im.shape[0] or mask[y, x] == True):
return;
# Check the if the current values are in +- range (Prange) of the required pixel value
elif ( (abs(int(im[y, x, 2])- r) < Prange) and (int(abs(im[y, x, 1])- g) < Prange) and (int(abs(im[y, x, 0])- b) < Prange)):
# If yes, set the value for the pixel in mask is equal to True
mask[y, x] = True
# Move to the pixel on above the current pixel
dfs(x , y - 1, r, g, b, mask, im, Prange);
# Move to the pixel right of current pixel
dfs(x + 1, y, r, g, b, mask, im, Prange);
# Move to the pixel left of current pixel
dfs(x - 1, y , r, g, b, mask, im, Prange);
# Move to the pixel below the current pixel
dfs(x, y + 1, r, g, b, mask, im, Prange);
#Similarly
dfs(x - 1, y - 1, r, g, b, mask, im, Prange);
dfs(x - 1, y + 1, r, g, b, mask, im, Prange);
dfs(x + 1, y + 1, r, g, b, mask, im, Prange);
dfs(x + 1, y - 1, r, g, b, mask, im, Prange);
return
Now we will write a wrapper function named dfsFunction
to access the dfs
function we wrote previously in an easy way.
The signature of the function is -
dfsFunction(x, y, im, Prange)
Here,
x
= x co-ordinate of the input pixely
= y co-ordinate of the input pixelim
= the input imagePrange
= the range in the RGB values that will be considereddef dfsFunction(x, y, im, Prange):
# Initiate a boolean array named mask and set all values equal to false
mask = np.zeros(im.shape[:2], dtype = 'bool')
# Call the recursive function
dfs(x, y, int(im[y, x ,2]), int(im[y, x , 1]), int(im[y, x , 0]), mask, im, Prange)
return mask
Let's read the input image and display the image -
im = imread("/home/bikz05/Desktop/$_35.JPG")
# Display the original image
title("Original Image")
axis("off")
imshow(im)
show()
Call the function dfsFunction
with the pixel location where we want to run the algo. Here, we are passing a pixel location of the red mark in the left-bottom of the image. Note here that OpenCV
stores an image in BGR
format and matplotlib
interprets it in RGB
format. So, while running an cv2
function, we will first convert the image from BGR
format to RGB
format. You can change the format by using the command(s) below whenever needed -
im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB) # BGR to RGB format
im = cv2.cvtColor(im, cv2.COLOR_RGB2BGR) # RGB to BGR format
Also, once we are done with the OpenCV part, we will again convert the image into RGB
format.
im = cv2.cvtColor(im, cv2.COLOR_RGB2BGR)
mask = dfsFunction(60, 256, im, 50)
im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
Now, we will create an RGB image new
using the mask
and the input image im
.
new = im * np.dstack((mask, mask, mask))
Now, we will display both the input and the resulting image.
# Display the resulting image
title("Resulting Image")
axis("off")
imshow(new)
show()