Reputation: 3885
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:
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:
This is the result image:
Upvotes: 2
Views: 1956
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
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