How to label numbers and draw circles on image with OpenCV

Viewed 1186

I have code to count the number of pipes in an image. It basically displays the total number of pipes in the image. Here is the code

# import Libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt

#load image
image=cv2.imread("enhanced.sample3.png")
#cv2.imshow("figure",image)
cv2.waitKey(0)
#create blob detector
detector=cv2.SimpleBlobDetector_create()
#keypoints
keypoints=detector.detect(image)
#create a blank file which is a numpy array to hold our circle that we will detect and mark during the process
blank = np.zeros((1,1))
blobs = cv2.drawKeypoints(image, keypoints, blank, (0,0,255),cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

number_of_blobs = len(keypoints)
text = "Total Number of Blobss: " + str(len(keypoints))
cv2.putText(blobs, text, (2, 55), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2)

# Display image with blob keypoints
#cv2.imshow("Blobs using default parameters", blobs)
cv2.waitKey(0)
#another function to create blobs
params=cv2.SimpleBlobDetector_Params()
#AREA
params.filterByArea=True
params.minArea=100
#CIRCULARITY
params.filterByCircularity=True
params.minCircularity=0.4
#CONVEXITY
params.filterByConvexity=True
params.minConvexity=0.3
#INERTIA
params.filterByInertia=True
params.minInertiaRatio=0.01

detector=cv2.SimpleBlobDetector_create(params)
keypoints=detector.detect(image)
blank=np.zeros((1,1))
number_of_blobs = len(keypoints)

#for i in range(number_of_blobs):
print("Number of Circular Blobs: " + str(number_of_blobs))

blobs=cv2.drawKeypoints(image,keypoints,blank,(0,200,222),cv2.DRAW_MATCHES_FLAGS_DEFAULT)

#number_of_blobs = len(keypoints)
text = "Number of Circular Blobs: " + str(len(keypoints))

cv2.putText(blobs, text, (1, 55), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2)


cv2.imshow("blobs",blobs)
cv2.waitKey(0)



cv2.destroyAllWindows()

Which displayed output like this

Image

But I want it something like this, with bigger circles.

image2

How can I achieve this?

1 Answers

With the assumption that you already have the contours of the circles that you want to draw or write text on, you can find the centroid for each circle contour and write the contour number using cv2.putText(). To actually draw the circles, you can use cv2.minEnclosingCircle() + cv2.circle(). Since you didn't provide a sample input image, here's a quick example with contour numbers in teal and drawn circles in red.

Input image -> Result

import cv2

# Load image, convert to grayscale, Otsu's threshold
image = cv2.imread('1.png')
result = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find contours, sort by contour area from smallest to largest 
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=lambda x: cv2.contourArea(x))

for count, c in enumerate(cnts):
    # Find centroid for each contour and label contour
    M = cv2.moments(c)
    cx = int(M['m10']/M['m00'])
    cy = int(M['m01']/M['m00'])
    cv2.putText(result, str(count), (cx-5, cy+5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (246,255,12), 3)

    # Find circle radius and draw circle 
    ((x, y), r) = cv2.minEnclosingCircle(c)
    cv2.circle(result, (int(x), int(y)), int(r), (100, 100, 255), 2)

# Display
cv2.imshow('image', image)
cv2.imshow('result', result)
cv2.waitKey()
Related