首页 > 解决方案 > 计算图像中两个像素之间的距离

问题描述

我正在尝试以特定方式计算两个像素之间的距离。我需要知道图像中红线的粗细,所以我的想法是逐列遍历图像,找到两个边缘点的坐标并计算它们之间的距离。对顶部和底部的两条线执行此操作。对每一列执行此操作,然后计算平均值。我还应该进行从像素到真实比例的转换。

这是我现在的代码:

# Make numpy array from image
npimage = np.array(image)

# Describe what a single red pixel looks like
red = np.array([255, 0, 0], dtype=np.uint8)   

firs_point = 0
first_find = False
for i in range(image.width):
    column = npimage[:,i]
    for row in column:
        comparison = row == red
        equal_arrays = comparison.all()
        if equal_arrays == True and first_find == False:
                first_x_coord = i
                first_find = True

我无法获得坐标。有人能帮助我吗?当然,如果有更优化的计算方法,我很乐意接受建议。我很新!非常感谢!

标签: pythonnumpyopencvdistancepoints

解决方案


正确屏蔽所有红色像素后,您可以计算该掩码中每列的累积总和:

累计金额

在每条红线下方,您有一个具有恒定值的大面积:在第一条红线下方,是那条红线的粗细。在第二条红线下方,是两条红线的累积粗细,依此类推(如果还有更多红线的话)。

所以,现在,对于每一列,从累积和计算直方图,并过滤掉这些峰值;省略0直方图中的 ,那将是顶部的大黑色区域。每列,您将获得所有红线的上述(累积)厚度值。剩下的就是提取实际的单个厚度值,并计算所有这些值的平均值。

这是我的代码:

import cv2
import numpy as np

# Read image
img = cv2.imread('Dc4zq.png')

# Mask RGB pure red
mask = (img == [0, 0, 255]).all(axis=2)

# We check for two lines
n = 2

# Cumulative sum for each column
cs = np.cumsum(mask, axis=0)

# Thickness values for each column
tvs = np.zeros((n, img.shape[1]))
for c in range(img.shape[1]):

    # Calculate histogram of cumulative sum for a column
    hist = np.histogram(cs[:, c], bins=np.arange(img.shape[1]+1))

    # Get n highest histogram values
    # These are the single thickness values for a column
    tv = np.sort(np.argsort(hist[0][1:])[::-1][0:n]+1)
    tv[1:] -= tv[:-1]
    tvs[:, c] = tv

# Get mean thickness value
mtv = np.mean(tvs.flatten())
print('Mean thickness value:', mtv)

最终结果是:

Mean thickness value: 18.92982456140351
----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
NumPy:         1.20.1
OpenCV:        4.5.1
----------------------------------------

编辑:我将提供有关所涉及的“NumPy 魔法”的更多细节。

# Calculate the histogram of the cumulative sum for a single column
hist = np.histogram(cs[:, c], bins=np.arange(img.shape[1] + 1))

在这里,bins表示直方图的区间,即[0, 1][1, 2]等。还要获取最后一个区间[569, 570],需要img.shape[1] + 1np.arange调用中使用,因为正确的限制不包含在np.arange.

# Get the actual histogram starting from bin 1
hist = hist[0][1:]

通常,np.histogram返回一个元组,其中第一个元素是实际的直方图。我们提取它,并且只查看所有更大的 bin 0(记住,大的黑色区域)。

现在,让我们反汇编这段代码:

tv = np.sort(np.argsort(hist[0][1:])[::-1][0:n]+1)

这一行可以改写为:

# Get the actual histogram starting from bin 1
hist = hist[0][1:]

# Get indices of sorted histogram; these are the actual bins
hist_idx = np.argsort(hist)

# Reverse the found indices, since we want those bins with the highest counts
hist_idx = hist_idx[::-1]

# From that indices, we only want the first n elements (assuming there are n red lines)
hist_idx = hist_idx[:n]

# Add 1, because we cut the 0 bin
hist_idx = hist_idx + 1

# As a preparation: Sort the (cumulative) thickness values
tv = np.sort(hist_idx)

到目前为止,我们已经有了每列的(累积)厚度值。为了重建实际的单个厚度值,我们需要累积和的“倒数”。关于那个主题有这个很好的问答。

# The "inverse" of the cumulative sum to reconstruct the actual thickness values
tv[1:] -= tv[:-1]

# Save thickness values in "global" array
tvs[:, c] = tv

推荐阅读