我有一张来自激光线的图片,我想从图像中提取该线。
由于激光线是红色的,我采用图像的红色通道,然后搜索每一行中的最高强度:
现在的问题是,还有一些不属于激光线的点(如果放大第二张图,你可以看到这些点)。
有人对接下来的步骤有想法吗(删除单点并提取线条)?
这是检测这条线的另一种方法: 首先,我用内核模糊了“黑白”线,然后将模糊线细化(骨架)为细线,然后应用 OpenCV 函数来检测该线..结果如下图所示:
新:
现在我遇到了另一个更困难的情况。
我必须提取绿色激光。
这里的问题是激光线的颜色范围更宽并且变化。
在激光线的某些部分,像素仅具有高绿色分量,而在其他部分,像素也具有高蓝色分量。
获取每一行中的最高值将始终输出一个值,而不是当该值不够高时忽略。也考虑使用阈值,以便您可以丢弃不够高的阈值。
但是,这根本不是一个非常有效的方法。更好、更简单的解决方案是使用 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)
这可以通过寻找轮廓或其他方法来进一步处理,将点变成漂亮的曲线。
对于没有任何代码的简短回答,我真的很抱歉,但我建议你绘制轮廓并处理它们。
我不知道你到底需要什么,所以这里有两种方法适合你:
只在单线上收集尽可能多的轮廓(使用中心并尝试找到具有最小均值的直线)
作为第一种方法,但尝试试探性地组合分离的线......这要困难得多,但这可能会为您提供图像中几乎完整的激光线。
--
您的图片的一些示例:
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)
在你的情况下,它工作得很好,但是,正如我已经说过的,你需要对轮廓做更多的工作。
您好,我想问您最终如何解决三角测量或距离测量以及将激光与图像分离的问题,因为我目前也参与了一个类似的项目。如果您也分享您的代码,我将不胜感激。谢谢