我正在寻找一个适当的解决方案如何计数颗粒和测量其大小在这张图片:
的数据
最后,我必须获得粒子坐标和面积平方的列表。在互联网上搜索后,我意识到有3种方法可以检测粒子:
1.斑点
1.轮廓
- connectedObjectivesWithStats
看着不同的项目,我用它的混合物组装了一些代码。
import pylab
import cv2
import numpy as np
字符串
高斯模糊和阈值
original_image = cv2.imread(img_path)
img = original_image
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = cv2.GaussianBlur(img, (5, 5), 0)
img = cv2.blur(img, (5, 5))
img = cv2.medianBlur(img, 5)
img = cv2.bilateralFilter(img, 6, 50, 50)
max_value = 255
adaptive_method = cv2.ADAPTIVE_THRESH_GAUSSIAN_C
threshold_type = cv2.THRESH_BINARY
block_size = 11
img_thresholded = cv2.adaptiveThreshold(img, max_value, adaptive_method, threshold_type, block_size, -3)
型
过滤小物体
min_size = 4
nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(img, connectivity=8)
sizes = stats[1:, -1]
nb_components = nb_components - 1
# for every component in the image, you keep it only if it's above min_size
for i in range(0, nb_components):
if sizes[i] < min_size:
img[output == i + 1] = 0
型
生成用于填充孔和测量的轮廓。pos_list
和size_list
是我们正在寻找的
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
pos_list = []
size_list = []
for i in range(len(contours)):
area = cv2.contourArea(contours[i])
size_list.append(area)
(x, y), radius = cv2.minEnclosingCircle(contours[i])
pos_list.append((int(x), int(y)))
型
如果我们在原始图像上绘制这些坐标,
pts = np.array(pos_list)
pylab.figure(0)
pylab.imshow(original_image)
pylab.scatter(pts[:, 0], pts[:, 1], marker="x", color="green", s=5, linewidths=1)
pylab.show()
型
我们可能会得到如下结果:
的
而且.我对结果不是很满意。一些清晰可见的颗粒没有被包括在内,另一方面,一些强度的可疑波动被计算在内。我现在正在玩不同的过滤器设置,但感觉是它是错误的。
如果有人知道如何改进我的解决方案,请分享。
1条答案
按热度按时间ejk8hzay1#
由于粒子是白色的,背景是黑色的,我们可以使用Kmeans颜色量化将图像分为两组,
cluster=2
。这将使我们能够轻松区分粒子和背景。由于粒子可能非常微小,我们应该尽量避免模糊,膨胀或任何可能改变粒子轮廓的形态学操作。下面是一种方法:1.**Kmeans颜色量化。**我们用两个聚类、灰度、然后大津阈值来执行Kmeans,以获得二值图像。
1.**过滤掉超微小的噪声。**接下来我们找到轮廓,使用轮廓区域过滤去除微小的噪声,并收集每个粒子
(x, y)
坐标及其面积。我们通过“填充”这些轮廓来有效地删除二进制掩码上的微小粒子。1.**将蒙版应用到原始图像上。**现在我们将过滤后的蒙版逐位和到原始图像上以突出显示粒子簇。
K均值
clusters=2
的数据
结果
的
字符串
代码
型