Sumukh Jadhav
Sumukh Jadhav

Reputation: 262

Counting the number of circular pipes in an image

I'm trying to build a program to count the number of pipes from a given image, https://drive.google.com/drive/folders/1iw2W7dUg3ICGRt3hxOynUJCf-KQj2Pka?usp=sharing are some example test images.

I've tried doing the same with Canny's, Hough's but neither of them seem to be even close to counting them properly. What approach should I go for?

Upvotes: 2

Views: 1926

Answers (2)

Shamshirsaz.Navid
Shamshirsaz.Navid

Reputation: 2362

There are several things to consider:

  1. It is better to find the range of pipes with a suitable method (search the net).
  2. 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.
  3. 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)))

enter image description here

Upvotes: 1

Vlamir
Vlamir

Reputation: 421

Although you may get by with some ad-hoc algorithm, I think you would spend more time tuning it than just training and tuning a model:

The pipes do not seem to have a very complicated texture, so I would create a set of synthetic images by cropping some of the pipes from the images and then I would apply multiple transformations to it. For instance, you can use the imgaug (https://imgaug.readthedocs.io/en/latest/) library in python. Then, you can use HOG, Haar features, LBP, etc.. to get features and train a model adaboost with trees, linear SVM, etc... The object detection pipeline from DLib should be good enough and is easy to use. In general, you need a framework with sliding windows for the detection part.

Another option is to get a bunch of backgrounds as well as transformations over the cropping images and create multiple images with bounding boxes annotations, you could use a tool like this one for that: https://github.com/tylerhutcherson/synthetic-images.

Then, you can use a deep learning model like YOLOv4, RetinaNet, or Faster-RCNN. Notice that you may need to change the strides of the output layers since the objects may be too small.

All in all, If I were you I would start with the object detection from dlib, it should not take you too long to have everything ready.

One thing, given the type of features used for the training the model may detect circles that are not really pipes, but if you expect to have many pipes, that should be easy to remove.

Hope it helps and good luck.

Upvotes: 0

Related Questions