python - 计算图像中两个像素之间的距离
问题描述
我正在尝试以特定方式计算两个像素之间的距离。我需要知道图像中红线的粗细,所以我的想法是逐列遍历图像,找到两个边缘点的坐标并计算它们之间的距离。对顶部和底部的两条线执行此操作。对每一列执行此操作,然后计算平均值。我还应该进行从像素到真实比例的转换。
这是我现在的代码:
# 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
我无法获得坐标。有人能帮助我吗?当然,如果有更优化的计算方法,我很乐意接受建议。我很新!非常感谢!
解决方案
正确屏蔽所有红色像素后,您可以计算该掩码中每列的累积总和:
在每条红线下方,您有一个具有恒定值的大面积:在第一条红线下方,是那条红线的粗细。在第二条红线下方,是两条红线的累积粗细,依此类推(如果还有更多红线的话)。
所以,现在,对于每一列,从累积和计算直方图,并过滤掉这些峰值;省略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] + 1
在np.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
推荐阅读
- android - 如何在 Play 商店中调试此崩溃?
- r - R ggpubr:将图例标题移动到图例键上方
- eclipse - Maven 和 EJB (JEE)
- html - 主体上带有 Webpack 和 Symfony 的背景颜色
- ffmpeg - 使用 ss 后输出流中的非单调 DTS
- docker - docker私有注册表作为本地机器和服务器机器中的默认注册表
- elasticsearch - Elaticsearch 对单词少的文档有好处吗
- javascript - 在 lit-element 中重用 firebase 常量
- android - 为什么只获取用户名?
- phpmyadmin - PhpMyAdmin 无法加密到 MD5