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

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

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

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

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

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

最佳答案

更新了

好的,我看了看您的最新照片。我的算法可归纳为以下步骤。

  • 在图像
  • 中找到最亮的列(即激光线)
  • 在最亮的列中找到暗隙
  • 在激光行
  • 中找到间隙中最亮的相邻列

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

    最简单的方法是将图像向下压缩,使其仍保持其原始宽度,但是只有一个高像素有效地平均化图像每个垂直列中的像素。然后应用-auto-level将对比度对比度拉伸(stretch)到0-255的整个范围,并将其阈值设置为95%,以找到所有最亮的5%范围内的列。然后寻找阈值为白色(#ffffff)的像素。这是ImageMagick中的一行,如下所示:
    convert http://i.stack.imgur.com/1P1zj.jpg -colorspace gray \
        -resize x1!                                             \
        -auto-level                                             \
        -threshold 95% text: | grep -i ffffff
    

    输出:
    297,0: (255,255,255)  #FFFFFF  white
    298,0: (255,255,255)  #FFFFFF  white
    299,0: (255,255,255)  #FFFFFF  white
    

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

    这样就完成了步骤1,但是在步骤2之前采用了另一种方法。

    我将图像分为1像素宽的列,其内容如下:
    convert input.png -crop 1x +repage line%d.png
    

    现在,我找到了最亮的一列(平均亮度最高的一列):
    for f in line*; do m=$(convert -format "%[fx:mean]" $f info:);echo $m:$f ;done | sort -g
    

    这给了
    ...
    ...
    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
    

    步骤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
    

    步骤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
    

    输出如下:
    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
    

    然后,我可以看到列253在激光线最暗的区域最亮。因此,置换后的线位于第253列中。

    我确信可以在opencv中很容易地完成此技术。

    原始答案

    我可以告诉您一种方法,但是由于我倾向于使用ImageMagick,因此无法为您提供opencv的任何代码。我将图像分成一系列垂直图像,每个垂直图像宽1像素-即单像素列。然后,我获得所有列中亮度的平均值,并且可以立即看到最亮的列。它工作得很好,这是我测试算法的方法:
    Split image into single pixel columns
    convert http://i.stack.imgur.com/vMiU1.jpg -crop 1x +repage line%04d.png
    

    看看我们得到了什么:
    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
    

    是的,有640条垂直线。检查一个...的大小
    identify line0639.png
    line0639.png PNG 1x480 1x480+0+0 8-bit sRGB 1.33KB 0.000u 0:00.000
    

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

    现在获得所有行的平均亮度并按亮度排序:
    for f in line*; do m=$(convert -format "%[fx:mean]" $f info:);echo $m:$f ;done | sort -g
    

    输出
    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
    

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

    关于opencv - 激光线检测opencv,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27817156/

    10-12 23:52