Как я могу считать сегменты в изображении в Python? - PullRequest
0 голосов
/ 09 января 2019

Я новичок в обработке изображений и Python. Возможно, вы видели мои любительские коды на этом сайте в последние пару дней.

Я пытаюсь подсчитать количество деревьев, используя аэрофотоснимки. Это мой код:

from PIL import Image
import cv2
import numpy as np
from skimage import io, filters, measure
from scipy import ndimage

img = Image.open("D:\\Texture analysis\\K-2.jpg")
row, col = img.size

hsvimg = img.convert('HSV')
hsvimg.mode = 'RGB'
hsvimg.save('newImage2.jpg')

npHSI = np.asarray(hsvimg)                  #Convert HSI Image to np image

blur = cv2.GaussianBlur(npHSI, (45, 45), 5)

assert isinstance(blur, np.ndarray)         ##############################
assert len(blur.shape) == 3                 #Convert np Image to HSI Image
assert blur.shape[2] == 3                   ##############################

hsiBlur = Image.fromarray(blur, 'RGB')
hsiBlur.save('hsiBlur.jpg')                 #Save the blurred image

## Read
img = cv2.imread("D:\\Texture analysis\\hsiBlur.jpg")

## convert to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

#Threshold the image and segment the trees
mask = cv2.inRange(hsv, (36, 25, 25), (70, 255,255))
imask = mask>0
green = np.zeros_like(img, np.uint8)
green[imask] = img[imask]

## save 
cv2.imwrite("green.png", green)

#Count the number of trees
im = io.imread('green.png', as_grey=True)
val = filters.threshold_otsu(im)
drops = ndimage.binary_fill_holes(im < val)
labels = measure.label(drops)
print(labels.max())

Исходное изображение: K-2.jpg

HSI изображение с гауссовым фильтром: hsiBlur.jpg

Сегментированное изображение: green.png

Последняя часть кода возвращает 7, что является неправильным выводом. Значение должно быть выше 50. Как правильно подсчитать количество зеленых сегментов в конечном сегментированном изображении?

EDIT

Я преобразовал green.png в двоичную и применил эрозию с 3x3 filter и iterated it 7 times для удаления шума. Это то, что я сделал в конце. Я перешел по этой ссылке stackoverflow

##save
cv2.imwrite("green.png", green)

#Convert to grayscale
gray = np.dot(green[...,:3], [0.299, 0.587, 0.114])
cv2.imwrite("grayScale.jpg", gray)

#Binarize the grayscale image
ret,bin_img = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cv2.imwrite("bin_img.jpg", bin_img)

#Erosion to remove the noise
kernel = np.ones((3, 3),np.uint8)
erosion = cv2.erode(gray, kernel, iterations = 7)
cv2.imwrite("erosion.jpg", erosion)

#Count the number of trees
finalImage = cv2.imread('erosion.jpg')
finalImage = cv2.cvtColor(finalImage, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(finalImage, 127, 255, 1)
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
    cv2.drawContours(finalImage,[cnt],0,(0,0,255),1)

Саурав , упомянутый в его ответе ... размер "контуров" даст вам счет . Это print(contour.size()) дает ошибку, а print(contour) просто печатает длинный двумерный массив. Как я могу получить размер контура?

PS. Я не загружал изображения в градациях серого, бинарные и эродированные изображения, потому что чувствовал, что изображения уже занимают слишком много места, и я могу загрузить их, если кто-нибудь захочет.

1 Ответ

0 голосов
/ 10 января 2019

Я нашел 52 деревьев с этим сценарием:

from PIL import Image, ImageDraw, ImageFont

image = Image.open('04uX3.jpg')
pixels = image.load()
size = image.size
draw = ImageDraw.Draw(image)
font = ImageFont.truetype('arial', 60)
i = 1
for x in range(0, size[0], 100):
    for y in range(0, size[1], 100):
        if pixels[x, y][1] > 200:
            draw.text((x, y), str(i), (255, 0, 0), font=font)
            i += 1
image.save('result.png')

Вы можете видеть, что некоторые деревья не были обнаружены, а некоторые не деревья были обнаружены. Так что это очень грубый расчет:

trees detected

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...