taga
taga

Reputation: 3885

Counting special elements on image with OpenCV and Python

I want to count number of trees on this picture from above.

I know how to count elements, but till now I used images with white background, so counting is much easier. But on image like this i do not know what to do:

enter image description here

I converted the image to gray, and then done the threshold *(threshold value is done by hand, is there a way to find it automaticly?), my next idea is to find the 'centers' of black dots, or to 'group' them.

I also tried to change brightness and contrast but it didnt work.

What should I do? This is the code that I wrote:

import cv2
import numpy as np

# Read image
img = cv2.imread('slika.jpg')

# Convert image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Show grayscale image
cv2.imshow('gray image', gray)
cv2.waitKey(0)

#BIG PROBLEM: IM FINDING VALUE OF `40` IN THE LINE BELOW MANUALLY

# Inverse binary threshold image with threshold at 40,
_, threshold_one = cv2.threshold(gray, 40 , 255, cv2.THRESH_BINARY_INV)

# Show thresholded image
cv2.imshow('threshold image', threshold_one)
cv2.waitKey(0)

# Find contours
contours, h = cv2.findContours(threshold_one, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

print('Number of trees found:', len(contours))  #GIVES WRONG RESULT

# Iterate all found contours
for cnt in contours:

    # Draw contour in original/final image
    cv2.drawContours(img, [cnt], 0, (0, 0, 255), 1)

# Show final image
cv2.imshow('result image', img)
cv2.waitKey(0)

This is the image with treshold, I have tried to blur it (in order to connect black dots), but the final output is the same:

enter image description here

This is the result image:

enter image description here

Upvotes: 2

Views: 1956

Answers (1)

nathancy
nathancy

Reputation: 46600

Here's a rough method to estimate the number of trees. The idea to to model each tree as a blob then use contour filtering with a minimum threshold area to ignore the noise. To determine automatic threshold levels, you can use Otsu's threshold by appending cv2.THRESH_OTSU or Adaptive threshold with cv2.adaptiveThreshold(). This approach has problems when the trees are very close together since they form a single blob. Possible improvements could be to find the average area of each tree then find the floor with a large blob. You would probably need to train a classifier and use deep/machine learning for better accuracy

enter image description here

Trees: 102

import cv2

image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
opening = cv2.morphologyEx(close, cv2.MORPH_OPEN, kernel, iterations=2)

cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
trees = 0
for c in cnts:
    area = cv2.contourArea(c)
    if area > 50:
        x,y,w,h = cv2.boundingRect(c)
        cv2.drawContours(image, [c], -1, (36,255,12), 2)
        trees += 1

print('Trees:', trees)
cv2.imshow('image', image)
cv2.waitKey()

Upvotes: 2

Related Questions