There are several things to consider:
- It is better to find the range of pipes with a suitable method (search the net).
- In the second step, with PerspectiveTransform, preferably eliminate the rotation of the image and only move the range of the pipes to the next step.
- In the next step, from now on, you can use the following algorithm.
This is not a complete algorithm and will not work for all test_cases. You have to spend time. Read and combine different image processing methods or maybe even machine learning; Change the parameters to get a better result.
Another point is to try to keep the environmental conditions constant.
import sys
import cv2
import numpy as np
# Load image
im = cv2.imread(sys.path[0]+'/im.jpeg')
H, W = im.shape[:2]
# Make a copy from image
out = im.copy()
# Make a grayscale version
gry = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
# Make a clean black and white version of that picture
bw = cv2.adaptiveThreshold(
gry, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 12)
bw = cv2.medianBlur(bw, 3)
bw = cv2.erode(bw, np.ones((5, 5)))
bw = cv2.medianBlur(bw, 9)
bw = cv2.dilate(bw, np.ones((5, 5)))
# Draw a rectangle around image to eliminate errors
cv2.rectangle(bw, (0, 0), (W, H), 0, thickness=17)
# Count number of pipes
cnts, _ = cv2.findContours(bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# Change channels of black/white image
bw = cv2.cvtColor(bw, cv2.COLOR_GRAY2BGR)
# Draw position of pipes
c = 0
for cnt in cnts:
c += 1
x, y, w, h = cv2.boundingRect(cnt)
cv2.circle(out, (x+w//2, y+h//2), max(w, h)//2, (c, 220, 255-c), 2)
if c >= 255:
c = 0
# Count and print number of pipes
print(len(cnts))
# Save output images
cv2.imwrite(sys.path[0]+'/im_out.jpg', np.hstack((bw, out)))
