【问题标题】:Detecting edges of lasers/lights in images using Python使用 Python 检测图像中激光/光线的边缘
【发布时间】:2015-11-27 23:29:31
【问题描述】:

我正在用 Python 编写一个程序来遍历从视频帧中提取的图像并检测其中的线条。图像质量相当差,内容差异很大。这里有两个例子: Sample Image 1 | Sample Image 2

我正在尝试检测每张图像中的激光并查看它们的角度。最终我想看看这些角度的分布并输出其中三个的样本。

为了检测图像中的线条,我查看了以下各种组合:

  • 霍夫线
  • Canny 边缘检测
  • 双边/高斯滤波
  • 去噪
  • 直方图均衡化
  • 形态变换
  • 阈值

我尝试了很多不同方法的组合,但我似乎无法想出任何真正有效的方法。我一直在尝试的是这些方面:

import cv2
import numpy as np

img = cv2.imread('testimg.jpg')
grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
equal = clahe.apply(grey)

denoise = cv2.fastNlMeansDenoising(equal, 10, 10, 7, 21)

blurred = cv2.GaussianBlur(denoise, (3, 3), 0)
blurred = cv2.medianBlur(blurred, 9)

(mu, sigma) = cv2.meanStdDev(blurred)
edge = cv2.Canny(blurred, mu - sigma, mu + sigma)

lines = cv2.HoughLines(edge, 1, np.pi/180, 50)

if lines is not None:
    print len(lines[0])

    for rho,theta in lines[0]:
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a*rho
        y0 = b*rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000*(a))
        x2 = int(x0 - 1000*(-b))
        y2 = int(y0 - 1000*(a))

        cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)

cv2.imshow("preview", img)
cv2.waitKey(0)

这只是众多不同尝试中的一种。即使我能找到一种对其中一张图像效果稍好一些的方法,但事实证明它对另一张图像效果要差得多。我并不期待完全完美的结果,但我确信它们可能会比我迄今为止所管理的更好!

谁能提出一个策略来帮助我前进?

【问题讨论】:

  • 我投票结束这个问题,因为它属于信号处理,dsp.stackexchange.com
  • 我不同意这完全是信号处理(如果它移动我很好,但是......规则就是规则)。这是一个非常酷的简历问题。您的示例输出准确吗?相机相对于激光源的位置是否始终相同? (即,你有激光发射器的图像常数坐标?)
  • 还有。检测到的光束长度重要吗?还是只是角度+传播?
  • 您好@user1269942 感谢您抽出宝贵时间查看我的问题。相机是静态的 - 我曾希望激光源可以通过偏离图像的线交叉点来计算(但在我担心之前先努力获得线......)我正在寻找的角度非常简单 - 我' m 寻找图像中线条的角度。长度并不重要。正如您在我上面评论中的两个示例输出中看到的那样,它非常准确地检测线条,但遗漏了很多。

标签: python opencv computer-vision edge-detection hough-transform


【解决方案1】:

这是一个答案。如果您的相机处于固定位置,这是一个可以帮助您的答案,您的激光器也是如此......并且您的激光器从您可以确定的坐标发射。因此,如果您在相同的设置下同时进行许多实验,这可以作为一个起点。

image information along a polar coordinate system 的问题有助于获得极坐标变换。我选择不使用 openCV,因为不是每个人都可以使用它(windows)。我从链接的问题中获取了代码并玩了一下。如果您将他的代码添加到我的代码中(没有导入或 main 方法),那么您将拥有所需的功能。

import numpy as np
import scipy as sp
import scipy.ndimage

import matplotlib.pyplot as plt
import sys

import Image

def main():

    data = np.array(Image.open('crop1.jpg').convert('LA').convert('RGB'))

    origin = (188, -30)
    polar_grid, r, theta = reproject_image_into_polar(data, origin=origin)

    means, angs = mean_move(polar_grid, 10, 5)
    means = np.array(means)
    means -= np.mean(means)
    means[means<0] = 0
    means *= means

    plt.figure()
    plt.bar(angs, means)
    plt.show()

def mean_move(data, width, stride):
  means = []
  angs = []
  x = 0
  while True:
    if x + width > data.shape[1]:
      break
    d = data[:,x:x+width]
    m =  np.mean(d[d!=0])
    means.append(m)
    ang = 180./data.shape[1] * float(x + x+width)/2.
    angs.append(ang)
    x += stride

  return means, angs

# copy-paste Joe Kington code here

上方来源周围的图像。

请注意,我选择了一种激光并在其源周围裁剪了一个区域。这可以自动完成并为每个图像重复。我还根据我认为它发出的位置估计了源坐标 (188, -30)(以 x,y 形式)。下图(gimp 截图!)显示了我的推理(似乎有一条非常微弱的光线,我也回溯并拍摄了交叉点)......它还显示了大约 140 度的角度测量值。

图像的极坐标变换(注意垂直带,如果强度...它是垂直的,因为我们为激光选择了正确的原点)

并使用一个非常仓促创建的移动窗口均值函数和粗略映射到度角,以及均值 + 归零 + 平方的差异。

所以你的任务变成了抓住这些高峰。哦,看~140!谁是你爸爸!

回顾一下,如果设置是固定的,那么这可能会对您有所帮助!我真的需要回去工作,停止拖延。

【讨论】:

  • 这看起来真的很有趣——尤其是因为它是一种完全不同的看待问题的方式。因为它对我来说太新了(而且有点过头了),所以我需要一段时间来玩它并完全理解它。也非常感谢您的详尽解释!祝你工作顺利:)
猜你喜欢
  • 2016-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多