我想探测到一个自动系统的激光线。
到目前为止,我的工作是: 1.在rgb通道中分割图像;2.只使用红色通道,因为使用了红色激光线;3.手动获取阈值;4.搜索二进制图像中的值!= 0
对于自动化系统的用例,我不能手动地将其阈值化,有什么想法可以解决这个问题吗?
而且仅仅搜索图像中的最高峰是不够好的,因为阳光的影响。
也许我可以搜索短峰..。因为在激光线的区域内,亮度增加很快,然后在激光线后迅速下降。
我如何在opencv中意识到这一点?



发布于 2015-01-07 17:37:08
更新的
好的,我看了你最新的照片。我的算法可以归结为以下步骤。
步骤1-在图像中找到最亮的柱(即激光线)
最简单的方法是压缩图像,使其仍然是原来的宽度,但只有一个像素高,有效地平均每个垂直列中的像素。然后应用-auto-level进行对比,将其扩展到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列是激光线的部分。请注意,如果图片稍微旋转,或者激光不是垂直的,则明亮的列将被分割成多个列。为了抵消这一点,您可以将图像的宽度缩小2到3倍,这样相邻的列往往在较小的图像中合并为一列,然后将该列乘以收缩因子以找到原始位置。
这就完成了步骤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中可以很容易地完成这项技术。
原始答案
我可以告诉您一种方法,但不给您任何opencv代码,因为我倾向于使用ImageMagick。我将图像分割成一系列垂直图像,每幅图像宽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栏似乎很容易被识别为你的答案。
https://stackoverflow.com/questions/27817156
复制相似问题