Detecting The Number Of Pizza Slices Using Image Processing

Aditya Mohanty
Analytics Vidhya
Published in
4 min readSep 21, 2020

Deep learning techniques have been quite useful for counting and detecting number of objects in an image. However we can make use of the traditional image processing methods to do the same which would have lesser complexity. This blog explains the step by step process to calculate the number of pizza slices in a plate.

Procedure:

Let us consider the following image that has got four slices.

Our target is to calculate the number of slices which is 4.

First of all we need to read the image. This can be done through the imread function of opencv. It takes the path of the image as argument. Before that we need to import the libraries that are required to execute the given operation. These are listed here.

import osimport cv2import numpy as npimport matplotlib.pyplot as plt

To read the image we need to provide the path to the image as first argument. To do so we can write the following code snippet.

path = ‘/home/aditya123/image_processing/pizza/food’for images in os.listdir(path):   img = cv2.imread(os.path.join(path,images))

Here the image was stored in the above mentioned path. After reading the image in the given variable img we can access various properties of the image. We can get access certain properties of the image using the above-said variable. In the next step we shall convert the image to gray scale using the opencv library. The following code snippet does the work for us.


img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

The reason for converting the image into gray scale because we want to detect the edges which works best with the gray image. The following code snippet does the work for edge detection.

edge = cv2.Canny(img, 100, 200)

Let us understand what happened here. We are applying the canny edge detector to detect edges in the image. Here the first argument is the image that was read. Second and third argument are the threshold values for intensity gradient. Edges with intensity gradient more than the third argument( max_val) are confirmed as edge, whereas edges with intensity gradient less than the second value are discarded. Edges with intensity gradient within the min and max values are considered as edges based on their connected with confirmed edges or discarded edges.

In the next step we would apply thresholding so that the pixel values beyond a certain threshold would be one and below that it would be zero. The following code snippet does the work for us.

_,thresh = cv2.threshold(edged, 130, 255, cv2.THRESH_BINARY)

Here we have ignored the first value as it is not required. Second variable stores the thresholded binary image.

This would be followed by two morphological operations that are closing and opening which shall help us to remove noise and fill the holes of the image. To do so first we shall define a structuring element that would be used to apply morphology. This code creates the kernel for us.

def build_kernel(kernel_type, kernel_size):   if kernel_type == cv2.MORPH_ELLIPSE:   return cv2.getStructuringElement(cv2.MORPH_ELLIPSE, kernel_size)

The above code creates an eliptical structuring element. In the following code snippet the morphological opening and closing operations are applied.

morph = cv2.morphologyEx(thesh, cv2.MORPH_CLOSE, kernel) #Closemorph = cv2.morphologyEx(morph, cv2.MORPH_OPEN, kernel)

Now it is the time to find contours in the image. Contours are basically boundries of shape with similar intensity. For better result we have applied the canny edge detector and thresholding. The following code snippet does the work for us.

vals,_ = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

Consider the final parameter cv2.CHAIN_APPROX_SIMPLE which saves memory by storing relevant point co-ordinate instead of storing all the points. On the otherhand the first parameter cv2.RETR_EXTERNAL gives us only the outer contours that is it would ignore all the internal contours. This is really important for our problem as pizza slices might have contours within eachother.

Now the contours that would be detected will have many small objects. So we need to ignore them.

Here the val is a list that contains the boundary point of all the contours.

The following code snippet will draw all the contours after ignoring the small objects.

for c in cnts:if cv2.contourArea(c) > 200: # ignore small objects    cv2.drawContours(output, [c], -1,(np.random.randint(0,255),np.random.randint(0,255),np.random.randint(0,255)), 2)count += 1

We can use the cv2.putText to write the results detected about the image.

The following code snippet will write about the number of slices detected in the image.

text = “Number of slices detected: {}”.format(count)cv2.putText(img,text,(150,150),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),2,cv2.LINE_AA)

After running all the above code we shall get an output like this

This was an overview of how to detect the pizza slices using the image processing techniques.
To add me on linkedin https://www.linkedin.com/in/aditya-mohanty-7982451a9/.

--

--