【发布时间】:2016-01-17 06:13:54
【问题描述】:
使用 Python 检测图像中大致水平的红色激光线的最快最可靠的方法是什么?我正在做一个与 3d 激光扫描相关的小项目,我需要能够检测图像中的激光,以便计算其失真的距离。
首先,我有两个图像,一个已知不包含激光线的参考图像 A,以及一个肯定包含可能失真的激光线的图像 B。例如
示例图片 A:
示例图片 B:
由于这些是 RGB,但激光是红色的,因此我通过使用此功能去除蓝色和绿色通道来去除一些噪点:
from PIL import Image
import numpy as np
def only_red(im):
"""
Strips out everything except red.
"""
data = np.array(im)
red, green, blue, alpha = data.T
im2 = Image.fromarray(red.T)
return im2
这让我得到了这些图片:
接下来,我尝试通过使用PIL.ImageChops.difference() 获取这两个图像的差异来消除更多噪点。理想情况下,两个图像之间的曝光应该是相同的,从而导致差异只包含激光线。不幸的是,由于激光加光,每张图像的曝光和整体亮度都存在显着差异,导致差异仍然存在相当大的噪点。例如
我的最后一步是对线路的位置做出“最佳猜测”。因为我知道这条线将大致水平并且激光线应该是图像中最亮的东西,所以我扫描每一列并找到具有最亮像素的行,我假设它是激光线。代码如下:
import os
from PIL import Image, ImageOps
import numpy as np
x = Image.open('laser-diff.png', 'r')
x = x.convert('L')
out = Image.new("L", x.size, "black")
pix = out.load()
y = np.asarray(x.getdata(), dtype=np.float64).reshape((x.size[1], x.size[0]))
print y.shape
for col_i in xrange(y.shape[1]):
col_max = max([(y[row_i][col_i], row_i) for row_i in xrange(y.shape[0])])
col_max_brightness, col_max_row = col_max
print col_i, col_max
pix[col_i, col_max_row] = 255
out.save('laser-line.png')
我真正需要执行距离计算的是col_max 值的数组,但laser-line.png 帮助我想象成功,看起来像:
如您所见,估计值非常接近,但仍有一些噪点,主要位于图像左侧,激光线被哑光黑色饰面吸收。
我可以做些什么来提高我的准确性和/或速度?我正在尝试在 Raspberry Pi 等 ARM 平台上运行它,所以我担心我的代码可能效率太低而无法正常运行。
我对 Numpy 的矩阵函数并不完全熟悉,因此我不得不接受一个缓慢的 for 循环来扫描每一列,而不是更高效的方法。有没有一种快速的方法可以在 Numpy 中找到每列最亮像素的行?
另外,是否有可靠的方法在执行差异之前均衡图像而不会使激光线变暗?
【问题讨论】:
-
也许最后,你可以把y坐标不在25%~75%分位数的点全部去掉。然后可以得到更好的结果,然后使用 locf..etc 补上缺失的值
-
@B.Mr.W.,你说对了一部分。由于激光器安装在相机下方并与其焦平面平行,因此所有激光点都应位于中间行下方,这意味着上面的所有点都是噪声。谢谢。
标签: python image numpy image-processing