在图像中提取激光线(使用OpenCV)

时间:2017-06-06 12:12:35

标签: c++ image opencv line detection

我有一张来自激光线的图片,我想从图像中提取该线。

enter image description here

当激光线为红色时,我拍摄图像的红色通道,然后在每一行中搜索最高强度:

enter image description here

现在的问题是,还有一些点不属于激光线(如果放大第二张图片,你可以看到这些点)。

有没有人知道接下来的步骤(删除单个点并提取线条)?

这是另一种检测线路的方法: 首先,我用内核模糊了“黑白”线,然后我将线条模糊(细化)到细线,然后我应用OpenCV函数来检测线条...结果如下图所示:{ {3}}

新:

现在我有另一个更难的情况。 我必须提取绿色激光   这里的问题是激光线的颜色范围更宽广和变化 在激光线的某些部分上,像素仅具有高绿色成分,而在其他部分上,像素也具有高蓝色成分。 enter image description here

2 个答案:

答案 0 :(得分:3)

获取每行中的最高值将始终输出一个值,而不是在值不够高时忽略。考虑使用阈值,以便您可以丢弃那些不够高的阈值。

但是,这根本不是一种非常有效的方法。一个更好更容易的解决方案是使用OpenCV函数inRange();为所有三个通道中的红色定义下限和上限,这将返回带有白色像素的二进制图像,其中图像强度在该BGR范围内。

这是在python中但它完成了工作,应该很容易看到如何使用该函数:

import cv2
import numpy as np

img = cv2.imread('image.png')
lowerb = np.array([0, 0, 120])
upperb = np.array([100, 100, 255])
red_line = cv2.inRange(img, lowerb, upperb)

cv2.imshow('red', red_line)
cv2.waitKey(0)

这会产生输出: Red line binary iamge

可以通过查找轮廓或其他方法将点转换为漂亮的曲线来进一步处理。

答案 1 :(得分:1)

我很抱歉没有任何代码的简短回答,但我建议你采取轮廓并处理它们。

我不确切知道你需要什么,所以这里有两种方法:

  • 只需在单行上尽可能多地收集轮廓(使用中心并尝试找到最小平均值的直线)

  • 作为第一种方式,但尝试启发式地组合分离的线......它更难,但这可能会给你几乎完整的激光线从图像。

-

你的照片的一些例子:

import cv2
import numpy as np
import math

img = cv2.imread('image.png')
hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
# filtering red area of hue
redHueArea = 15
redRange = ((hsv[:, :, 0] + 360 + redHueArea) % 360) 
hsv[np.where((2 * redHueArea) > redRange)] = [0, 0, 0] 
# filtering by saturation
hsv[np.where(hsv[:, :, 1] < 95)] = [0, 0, 0]
# convert to rgb
rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)
# select only red grayscaled channel with low threshold  
gray = cv2.cvtColor(rgb, cv2.COLOR_RGB2GRAY)
gray = cv2.threshold(gray, 15, 255, cv2.THRESH_BINARY)[1]
# contours processing
(_, contours, _) = cv2.findContours(gray.copy(), cv2.RETR_LIST, 1)
for c in contours:
    area = cv2.contourArea(c)
    if area < 8: continue
    epsilon = 0.1 * cv2.arcLength(c, True) # tricky smoothing to a single line
    approx = cv2.approxPolyDP(c, epsilon, True)
    cv2.drawContours(img, [approx], -1, [255, 255, 255], -1)

cv2.imshow('result', img)
cv2.waitKey(0)

在你的情况下,它的工作非常完美,但是,正如我已经说过的那样,你需要在轮廓上做更多的工作。

enter image description here