如何使用Python检测图像中的激光线
使用Python检测图像中大致水平的红色激光线的最快、最可靠的方法是什么?我正在做一个与3d激光扫描相关的小项目,我需要能够检测图像中的激光,以便计算其变形的距离 首先,我有两个图像,一个参考图像a已知不包含激光线,另一个图像B肯定包含激光线,可能是扭曲的。e、 g 示例图像A: 示例图像B: 由于这些是RGB,但激光是红色的,因此我使用此功能剥离蓝色和绿色通道,以消除一些噪声:如何使用Python检测图像中的激光线,python,image,numpy,image-processing,Python,Image,Numpy,Image Processing,使用Python检测图像中大致水平的红色激光线的最快、最可靠的方法是什么?我正在做一个与3d激光扫描相关的小项目,我需要能够检测图像中的激光,以便计算其变形的距离 首先,我有两个图像,一个参考图像a已知不包含激光线,另一个图像B肯定包含激光线,可能是扭曲的。e、 g 示例图像A: 示例图像B: 由于这些是RGB,但激光是红色的,因此我使用此功能剥离蓝色和绿色通道,以消除一些噪声: from PIL import Image import numpy as np def only_red(i
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()
获取这两个图像的差异来消除更多的噪声。理想情况下,两幅图像之间的曝光是相同的,导致差异除了激光线外不包含任何内容。不幸的是,由于激光增加了光线,每个图像的曝光和整体亮度都有显著差异,导致差异仍然存在相当大的噪声。e、 g
我的最后一步是对线路的位置进行“最佳猜测”。因为我知道这条线大致是水平的,激光线应该是图像中最亮的东西,所以我扫描每一列,找到像素最亮的行,我假设这是激光线。这方面的代码是:
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中每列像素最亮的行
此外,是否有可靠的方法在执行差分之前均衡图像,而不使激光线变暗?首先,您可能可以在将负片图像的强度从正片图像中减去之前重新缩放负片图像的强度,以消除更多噪声。例如,根据平均智力的比率重新调整比例可能是一个好的尝试 你也可以尝试设置一个阈值:如果你的最大值低于任何好的值,那么它可能不是你的激光,而是一个噪声点
然后yes numpy可以使用argmax函数找到最佳行/列。首先输入激光的颜色,只留下红色(在本例中)。然后应用相同的效果并检查结果 在这种情况下,您将得到一个污染小得多的结果。
分析丢失的门上的红色时遇到问题。我试图做些什么。我不认为它是完全健壮的。但在你的例子中,它的效果相对较好 我使用canny边缘检测来检测“差异”图像中的边缘。然后应用Hough线变换,如中所示。 所以我从处理过的图像开始(我在代码中称之为
lineDetection.jpg
)
这是最后的剧本
import cv2
import numpy as np
img = cv2.imread('lineDetection.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,10,100)
minLineLength = 50
maxLineGap = 20
lines = cv2.HoughLinesP(edges,0.05,np.pi/5000,10,minLineLength,maxLineGap)
print(len(lines))
for i in range(len(lines)):
x1,y1,x2,y2 = lines[i][0]
cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)
cv2.imwrite('houghlines5.jpg',img)
在处理后的图像上检测到绿色线条。(您可以将其添加到原始图像中以获得更好的效果)
希望有帮助。我不知道激光的颜色,只是它大致是红色。我不能简单地假设所有红色的东西都是激光,因为场景中可能有红色的物体。此解决方案必须自动化,因此我无法手动指示每张图像中的激光颜色。然后使用您的图像,滚动图形。也许最大的方法是找到一条激光线。在图形的入口处将是任何具有两个黑色和两个白色像素相邻的像素。也许最后,您可以删除y坐标不在25%~75%分位数的所有点。然后可以得到更好的结果,然后使用locf填充缺少的值。。etc@B.Mr.W.,你说得有点对。由于激光器安装在摄像机下方并平行于其焦平面,因此所有激光点都应位于中间行下方,这意味着所有位于中间行上方的点都是噪声。谢谢