What I will tell in this article is very different in real projects. In real projects, object detection is not done with this method. This is just one of the steps to be taken when object detection. Here we will start with object detection and counting from the step. I will consider the more advanced algorithms of this, the method of application in the real world, in more detail in my next article.
First of all, let’s load our libraries.
import cv2
import imutils
import numpy as np
import matplotlib.pyplot as plt
I choose a picture with coins for this job.
Let’s import this picture.
image = cv2.imread("coins.jpg")
If you notice, you can see the bright spots on the coin. And again, there are sharp lines on the money. This will reduce efficiency when filtering this image. So let’s make our picture available.
image_blur = cv2.medianBlur(image,25)
When applying the medianBlur method, as seen above, the first parameter is the picture itself, and the second parameter is the blurring rate. If you use different pictures, you can adjust this ratio according to your picture.
One of the most important steps in object detection is to make the picture colorless. So we will turn our picture into a black and white tone. This is generally used in all object detection methods. This allows the image to run more efficiently because it reduces the number of scans.
image_blur_gray = cv2.cvtColor(image_blur, cv2.COLOR_BGR2GRAY)
If pixel value is greater than a threshold value, it is assigned one value (may be white), else it is assigned another value (may be black). The function used is cv2.threshold. First argument is the source image, which should be a grayscale image. Second argument is the threshold value which is used to classify the pixel values. Third argument is the maxVal which represents the value to be given if pixel value is more than (sometimes less than) the threshold value.
image_res ,image_thresh = cv2.threshold(image_blur_gray,240,255,cv2.THRESH_BINARY_INV)
I preferred the “THRESH_BINARY_INV” method because I want the coins to remain white here and the rest to be black. You can choose the appropriate values according to your own picture.
Now we will create a kernel here. This kernel will be 3x3 size.
kernel = np.ones((3,3),np.uint8)
Then we will apply this to our picture as follows.
opening = cv2.morphologyEx(image_thresh,cv2.MORPH_OPEN,kernel)
The reason for creating a kernel and applying it with the morphologyEx method is that although we blur the picture, some small black or white areas (noise) may remain. We used this method to destroy these.
Now it is time to replace the value of each pixel with the distance to the nearest background pixel using distanceTransform. We will do this using the distanceTransform method. When we apply this method, our array type turns into float32. So we will do 2 more steps and convert our array back to uint8 type.
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, last_image = cv2.threshold(dist_transform, 0.3*dist_transform.max(),255,0)
last_image = np.uint8(last_image)
We have the last 2 blocks of code left. In this section, we will now process the counting of objects and recording the positions of the objects. We use findContours to detect objects. Then we make our array regular with the grap_contours method.
cnts = cv2.findContours(last_image.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
Finally, we turn our picture.
def display(img,count,cmap="gray"):
f_image = cv2.imread("coins.jpg")
f, axs = plt.subplots(1,2,figsize=(12,5))
axs[0].imshow(f_image,cmap="gray")
axs[1].imshow(img,cmap="gray")
axs[1].set_title("Total Money Count = {}".format(count))
for (i, c) in enumerate(cnts):
((x, y), _) = cv2.minEnclosingCircle(c)
cv2.putText(image, "#{}".format(i + 1), (int(x) - 45, int(y)+20),
cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 0, 0), 5)
cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
display(image,len(cnts))
I tried to write as briefly and clearly as possible. For more detailed information, I will add the source documents below in this article. You can read them and get more in-depth information.
Top comments (2)
this is interesting and well explained!
Thank you 🙏