【问题标题】:Counting special elements on image with OpenCV and Python使用 OpenCV 和 Python 计算图像上的特殊元素
【发布时间】:2019-10-24 04:09:51
【问题描述】:

我想从上面数这张图片上的树数。

我知道如何计算元素,但直到现在我使用的是白色背景的图像,所以计数要容易得多。但是在这样的图像上我不知道该怎么做:

我把图像转成灰色,然后做了阈值*(阈值是手工做的,有没有办法自动找到?),我的下一个想法是找到黑点的“中心”,或者将它们“分组”。

我也尝试改变亮度和对比度,但没有奏效。

我该怎么办? 这是我写的代码:

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)

这是有阈值的图像,我尝试过模糊它(为了连接黑点),但最终输出是一样的:

这是结果图片:

【问题讨论】:

标签: python opencv computer-vision


【解决方案1】:

这是估算树木数量的粗略方法。将每棵树建模为一个 blob 的想法,然后使用具有最小阈值区域的轮廓过滤来忽略噪声。要确定自动阈值级别,您可以通过在cv2.THRESH_OTSUAdaptive threshold 后面附加cv2.adaptiveThreshold() 来使用Otsu's threshold。当树非常靠近时,这种方法会出现问题,因为它们形成一个单一的斑点。可能的改进可能是找到每棵树的平均面积,然后找到有大斑点的地板。您可能需要训练分类器并使用深度/机器学习以获得更好的准确性

树木: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()

【讨论】:

  • 你用过大津的阈值还是自适应阈值?因为我不知道我应该在哪里使用它
  • 是的,在此示例中,我通过附加 cv2.THRESH_OTSU 使用了 Otsu 的阈值。这是Otsu 的文档。要使用自适应阈值,需要另一个函数cv2.adaptiveThreshold()
  • 你帮了我很多,谢谢我的朋友!还有一个问题,你能给我解释一下cv2.MORPH_ELLIPSEcv2.MORPH_CLOSEcv2.MORPH_OPEN是什么?我已经阅读了文档,但我不太了解它
  • 在执行形态学运算时,特别是在使用cv2.morphologyEx() 时,您可以使用cv2.MORPH_CLOSE,即先膨胀后腐蚀,或cv2.MORPH_OPEN,即先腐蚀后膨胀。它本质上结合了cv2.dilate()cv2.erode()。要执行此操作,它需要一个内核,因此在这种情况下,我们使用cv2.MORPH_ELLIPSE 创建一个椭圆形内核。更多详情请关注here
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-10
  • 2020-06-20
相关资源
最近更新 更多