激光线检测opencv

Muh*_*uha 5 opencv

我想检测自治系统的激光线。

到目前为止,我的工作是:1.我将图像分成多个rgb通道2.由于使用了红色激光线,因此仅使用红色通道3.手动获取阈值4.在二进制图像中搜索值!= 0

对于自动系统的用例,我无法手动设置阈值,如何解决该问题的任何想法?

而且,由于阳光的入射,仅搜索图像中的最高峰还不够好。

也许我可以搜索短峰。.因为在激光线区域中,亮度快速增加,然后在激光线之后快速减小。

我如何在opencv中意识到这一点?

激光图像

手工tr的图像

与一个对象

Mar*_*ell 1

更新

好的,我已经查看了您更新的图片。我的算法归结为以下步骤。

  • 找到图像中最亮的柱(即激光线)

  • 找到最亮柱中的暗间隙

  • 查找激光线间隙中最亮的相邻柱

步骤 1 - 找到图像中最亮的柱(即激光线)

最简单的方法是将图像向下挤压,使其仍然是原始宽度,但只有一个像素高,有效地平均图像每个垂直列中的像素。然后应用-auto-level对比度拉伸到 0-255 的整个范围,并将阈值设置为 95%,以查找与最亮值相差 5% 以内的所有列。然后查找阈值设置为白色的像素 (#ffffff)。这是ImageMagick中的一行,如下:

convert https://i.stack.imgur.com/1P1zj.jpg -colorspace gray \
    -resize x1!                                             \
    -auto-level                                             \
    -threshold 95% text: | grep -i ffffff
Run Code Online (Sandbox Code Playgroud)

输出:

297,0: (255,255,255)  #FFFFFF  white
298,0: (255,255,255)  #FFFFFF  white
299,0: (255,255,255)  #FFFFFF  white
Run Code Online (Sandbox Code Playgroud)

所以,我现在知道第 297-299 列是激光线所在的位置。请注意,如果图片稍微旋转,或者激光不垂直,则亮柱将分成多个柱。为了解决这个问题,您可以将图像的宽度缩小两倍或三倍,以便相邻的列往往会在较小的图像中合并为一列,然后只需将列乘以缩小因子即可找到原始位置。

步骤 1 就完成了,但在步骤 2 之前还有一种替代方法。

我将图像分成 1 像素宽的列:

convert input.png -crop 1x +repage line%d.png
Run Code Online (Sandbox Code Playgroud)

现在我找到最亮的列(平均亮度最高的一列):

for f in line*; do m=$(convert -format "%[fx:mean]" $f info:);echo $m:$f ;done | sort -g
Run Code Online (Sandbox Code Playgroud)

这给出了这个

...
...
0.559298:line180.png
0.561051:line185.png
0.561337:line306.png
0.562527:line184.png
0.562939:line183.png
0.584523:line295.png
0.590632:line299.png
0.644543:line296.png
0.671116:line298.png
0.71122:line297.png      <--- brightest column = 297
Run Code Online (Sandbox Code Playgroud)

第 2 步 - 找到最亮柱中的暗间隙

现在我取第 297 列并自动调平,使最暗的部分变为零,最亮的部分变白,然后我将其取反。

convert line297.png -colorspace gray -auto-level -threshold 20% -negate txt:

...
0,100: (0,0,0)  #000000  black
0,101: (0,0,0)  #000000  black
0,102: (0,0,0)  #000000  black
0,103: (0,0,0)  #000000  black
0,104: (0,0,0)  #000000  black
0,105: (0,0,0)  #000000  black
0,106: (0,0,0)  #000000  black
0,107: (0,0,0)  #000000  black
0,108: (255,255,255)  #FFFFFF  white  <- gap in laser line
0,109: (255,255,255)  #FFFFFF  white  <- gap in laser line
0,110: (255,255,255)  #FFFFFF  white  <- gap in laser line
0,111: (255,255,255)  #FFFFFF  white  <- gap in laser line
0,112: (0,0,0)  #000000  black
0,113: (0,0,0)  #000000  black
...
0,478: (0,0,0)  #000000  black
0,479: (0,0,0)  #000000  black
Run Code Online (Sandbox Code Playgroud)

第 3 步 - 查找激光线间隙中最亮的相邻柱

现在,如果我将此列与其两侧的每一列相乘,则不在激光线间隙中的其他列的所有部分将变为零,并且在激光线间隙中的所有部分将相乘当我浏览第 297 栏两侧的栏时,将其总计。

因此,我检查第 240 至 340 列,将每一列与上一步中的掩模相乘,然后查看激光线间隙中哪一列最亮:

for i in {240..340} ;do n=$(convert line${i}.png mask.png -compose multiply -composite -format "%[mean]" info:);echo $n:$i ;done | sort -g
Run Code Online (Sandbox Code Playgroud)

输出如下:

458.495:248
466.169:249
468.668:247
498.294:260
502.756:250
536.844:259
557.726:258
564.508:251
624.117:252
627.508:253  <--- column 253 is brightest
Run Code Online (Sandbox Code Playgroud)

然后我可以看到第 253 列在激光线最暗的区域中最亮。所以移位的行位于第 253 列。

我确信这项技术可以在opencv.

原答案

我可以告诉你一种方法,但不会给你任何代码,因为opencv我倾向于使用 ImageMagick。我将图像分成一系列垂直图像,每个图像 1 像素宽 - 即单像素列。然后我得到所有列的亮度平均值,并且可以立即看到最亮的列。它工作得很好,这是我测试算法的方式:

Split image into single pixel columns
convert https://i.stack.imgur.com/vMiU1.jpg -crop 1x +repage line%04d.png
Run Code Online (Sandbox Code Playgroud)

看看我们得到了什么:

ls line*
line0000.png    line0128.png    line0256.png    line0384.png    line0512.png
line0001.png    line0129.png    line0257.png    line0385.png    line0513.png
...
line0126.png    line0254.png    line0382.png    line0510.png    line0638.png
line0127.png    line0255.png    line0383.png    line0511.png    line0639.png
Run Code Online (Sandbox Code Playgroud)

是的,640 条垂直线。检查一个尺寸...

identify line0639.png 
line0639.png PNG 1x480 1x480+0+0 8-bit sRGB 1.33KB 0.000u 0:00.000
Run Code Online (Sandbox Code Playgroud)

是的,它的宽度为 1 像素,高度为 480 像素。

现在获取所有线条的平均亮度并按亮度排序:

for f in line*; do m=$(convert -format "%[fx:mean]" $f info:);echo $m:$f ;done | sort -g
Run Code Online (Sandbox Code Playgroud)

输出

0.5151:line0103.png
0.521621:line0104.png
0.527829:line0360.png
0.54699:line0356.png
0.567822:line0355.png
0.752827:line0358.png  <--- highest brightness
0.76616:line0357.png   <--- highest brightness
Run Code Online (Sandbox Code Playgroud)

第 357 列和第 358 列似乎很容易识别为您的答案。