【问题标题】:How to count the number of particles of a certain size in an image?如何计算图像中一定大小的粒子数?
【发布时间】:2019-12-17 02:09:15
【问题描述】:

有没有一种好的算法可以根据大小检测粒子?例如,我有下图,我想检测和计数下图中突出显示的粒子:

它基本上是基于大小的。左边第三个圆圈大约是 20 微米,我想计算所有满足该阈值的粒子。

我该怎么做呢?我需要为 10,000 张图片执行此操作吗?

谢谢

【问题讨论】:

  • 在不知道图像比例的情况下,很难测量 20 微米。此外,这是一个长度而不是一个面积 - 这就是你的意思吗?你有一个多核 CPU 或一个机器网络来处理你的图像吗?您在哪些部分遇到问题 - 处理一张图像,或放大到 10,000 张?
  • 您可以使用简单的斑点检测并设置所需的区域范围以及其他形状参数。示例见stackoverflow.com/questions/59339013/…
  • 查看如何在此处并行处理图像...stackoverflow.com/a/59181995/2836621

标签: python opencv image-processing python-imaging-library


【解决方案1】:

正如 Mark Setchell 的评论中所述,如果没有参考图像,我们就无法测量 20 微米。但是,您已经说过我们可以将第三个轮廓作为参考,因此我首先在使用

对图像进行阈值处理后将其裁剪掉
import cv2

img = cv2.imread('stars.png', 0)
ret, img = cv2.threshold(img,100,255,cv2.THRESH_BINARY)
cv2.imshow("image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('star.png', img)

在油漆中裁剪后

现在,它的面积可以作为其他人的参考。现在再次读取原始图像和提取的星形图像,并为后一个图像计算最大轮廓的面积。然后在对原始图像进行阈值处理后计算原始图像的轮廓,并将它们循环遍历。它们是根据参考区域进行测量的。 (我取了获得的面积的一半。在确定最佳值之前,您可能还必须在其他图像之后为此执行参数调整。)满足给定条件的任何轮廓都绘制在使用创建的结果白色图像上np.ones 与原始图像大小相同,并且计数器变量递增。 cv2.bitwise_and 用于仅获取接受的轮廓并显示总数。

源码-:

import cv2
import numpy as np

img = cv2.imread('stars.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
match = cv2.imread('star.png', 0)
h, w = img.shape[:2]
res = np.ones((h, w), np.uint8)*255
ret, thresh = cv2.threshold(gray,64,255,cv2.THRESH_BINARY)
_, cnts, _ = cv2.findContours(match, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = max(cnts, key = cv2.contourArea)
area = cv2.contourArea(cnt)
_, cnts, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
count = 0
for cnt in cnts:
    if cv2.contourArea(cnt)>=area/2:
        cv2.drawContours(res, cnt, -1, 0, 2)
        count += 1
res = cv2.bitwise_and(img, img, mask = cv2.bitwise_not(res))
cv2.imshow("res", res)
cv2.imshow("star", match)
cv2.imshow("image", img)
cv2.imshow("result", res)
cv2.waitKey(0)
cv2.destroyAllWindows()
print("total count is =", count)

这给出了输出total count is = 3

【讨论】:

  • 如果您不需要非常大的粒子,也可以设置轮廓区域的上限。
  • 非常感谢您。按照您获取源代码的方式,它会在第 10 行和第 13 行引发以下错误: ValueError: not enough values to unpack (expected 3, got 2)。此外,许多图像的边界和底部都有一些伪影。有时这些伪影几乎就像一条“线”或“乐队”……我可以使用一些技术来修剪或不“计算”这些伪影吗?示例 1:i.imgur.com/wlJIoqI.png i.imgur.com/TEv3GIp.png 示例 2:i.imgur.com/oAd8mnF.png i.imgur.com/7Epj2pj.png
  • 对于寻找轮廓的错误,我猜你使用的是OpenCV 4所以你需要写cnts, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
  • 对于边框,您可以使用img = img[10:-10, 10:-10, :] 裁剪图像
  • 再次感谢...您认为有比裁剪更好的方法吗?如何找到一个长于一定数量的水平像素序列,然后在其上方和下方进行裁剪?等
【解决方案2】:

如果您想自己编写代码,请从简单的阈值开始:_,bin_img= cv2.threshold(img, 33,255,cv2.THRESH_BINARY)。使用from skimage.measure import label,您可以标记连接的组件。按大小对它们进行阈值化应该会给你想要的结果。

【讨论】:

    猜你喜欢
    • 2017-04-04
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    • 2011-06-16
    • 2021-07-20
    • 2018-04-27
    相关资源
    最近更新 更多