如何在Python中使用图像处理找到输入图像对象的直径?

时间:2018-07-27 00:56:40

标签: python numpy image-processing geometry ndimage

给出一个带有一些圆形物体(例如硬币)的输入图像(例如jpg),我想找到它们各自的直径。

感谢这个问题(How to find the diameter of objects using image processing in Python?,我知道如何识别对象,但是我想测量我插入的图像的直径,而不是使用方法随机生成。我该怎么办?

import numpy as np
from scipy import ndimage
from matplotlib import pyplot as plt

# generate some lowpass-filtered noise as a test image
gen = np.random.RandomState(0)
img = gen.poisson(2, size=(512, 512))  
img = ndimage.gaussian_filter(img.astype(np.double), (30, 30))
img -= img.min()
img /= img.max()

# use a boolean condition to find where pixel values are > 0.75
blobs = img > 0.75

# label connected regions that satisfy this condition
labels, nlabels = ndimage.label(blobs)

# find their centres of mass. in this case I'm weighting by the pixel values in
# `img`, but you could also pass the boolean values in `blobs` to compute the
# unweighted centroids.
r, c = np.vstack(ndimage.center_of_mass(img, labels, np.arange(nlabels) + 1)).T

# find their distances from the top-left corner
d = np.sqrt(r*r + c*c)

# plot
fig, ax = plt.subplots(1, 2, sharex=True, sharey=True, figsize=(10, 5))
ax[0].imshow(img)
ax[1].hold(True)
ax[1].imshow(np.ma.masked_array(labels, ~blobs), cmap=plt.cm.rainbow)
for ri, ci, di in zip(r, c, d):
    ax[1].annotate('', xy=(0, 0), xytext=(ci, ri),
               arrowprops={'arrowstyle':'<-', 'shrinkA':0})
    ax[1].annotate('d=%.1f' % di, xy=(ci, ri),  xytext=(0, -5),
               textcoords='offset points', ha='center', va='top',
               fontsize='x-large')
for aa in ax.flat:
    aa.set_axis_off()
fig.tight_layout()
plt.show()

我是新来的,所以我不知道怎么玩得很好,此代码生成的图像位于我所基于的问题的链接中。

2 个答案:

答案 0 :(得分:0)

一个简单的近似方法是假设完美的圆形物体,则半径为该区域的平方根(即像素数)除以pi:

def radius(A):
    return np.sqrt( A/np.pi )

def max_bounding_box(labels, k):
    idx, idy = np.where( labels==k )
    Sx = max(idx) - min(idx)
    Sy = max(idy) - min(idy)
    return max(Sx, Sy)/2

for k in range(1, nlabels):
    A = len( np.nonzero( labels==k )[0] )
    print(k, radius(A), max_bounding_box(labels, k)


1 41.32472068116174 52.5
2 31.040683392579073 37.0
3 34.37391885593249 39.0
4 26.986904594423443 27.5
5 73.79677393164606 80.0
6 15.012108426804138 17.0

否则,半径的定义不明确:边界框的大小?最大长度的圆弧?

编辑:我添加了对边框最大尺寸的评估

答案 1 :(得分:0)

您可以使用OpenCV2函数cv2.connectedComponentsWithStats(blobs)。此函数返回最左边的(x)坐标,它是水平方向上边界框的包含起始点,最上面的(y)坐标是边界内包含的起始位置边框在垂直方向上的大小,边框的水平大小,边框的垂直大小,所连接组件的总面积(以像素为单位)。要使用这些功能,必须转换blobs.dtype='uint8' 。 使用该区域并假设一个完美的圆形对象,您可以计算直径或按照建议使用边界框的大小。