使用 OpenCV 和 C++ 进行激光检测
我想用网络摄像头跟踪激光光点(位于墙上),我正在使用 openCV 来完成此任务。有人可以建议我一种用 C++ 实现的方法吗?
谢谢 !
I want to track a laser light dot(which is on a wall) with a webcam and i am using openCV to do this task. can anybody suggest me a way to do it with C++.
Thank you !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您有三个选择,具体取决于背景的稳定性以及您想要对图像执行的操作。
您可以使图像变暗,以致您唯一能看到的就是激光点。您可以通过关闭光圈和/或减少快门时间来做到这一点。即使使用廉价的网络摄像头,这通常也可以在驱动程序中完成。完成此操作后,找到激光点的工作就非常容易了。您使图像尽可能暗,因为通常激光照射的点太亮,相机无法捕捉到。这意味着(正如您所经历的)您无法区分图像中的光激光点和其他光物体。通过使其变暗,您现在可以做到这一点。
如果您的图像有其他用途(向人们展示)并且您的背景稳定,您还可以使用最后几个视频图像的平均值作为“背景”,然后找到该背景之间存在较大差异的位置和最新的图像。这通常是激光所指向的位置(同样,如果您的背景足够稳定)。
最后,如果您的背景不稳定并且您不想使图像变得非常暗,那么您的最终选择是寻找所有非常亮的像素,并且红色通道中的像素比绿色和蓝色通道中的像素更亮(如果您使用的是红色激光)。该系统仍然会被白点分散注意力,但不会像仅仅寻找明亮像素那样分散注意力。如果无论激光颜色如何,激光笔光点的中心确实显示为亮白色,那么这种技术将允许您找到该亮点周围的“环”(激光点的外部部分,其中激光不如激光颜色那么亮)。它位于中心,因此它在图像中显示出激光的实际颜色)。然后,您可以使用简单的形态操作,(可能关闭就足够了)来填充这些圆圈。
You have three options depending on the stability of your background, and the things you want to do with the image.
You can make your image so dark that the only thing you can see is the laser-point. You can do this by closing the diaphragm and/or reducing the shutter time. Even with cheap webcams this can usually be done in the driver. Once you've done this the job of finding the laser point is very easy. You make the image as dark as possible because usually the point where the laser shines is way too bright for the camera to pick up. This means (as you have experienced) that you cant discern between the light laser dot and other light objects in the image. By making it darker you now can do this.
If you have other uses for your image (showing it to people) and your background is stable you can also use the average of the last few video images as a "background" and then find the spot where there is a large difference between that background and the newest image. This is usually where the laser is pointed (again, if your background is stable enough) .
Finally, if your background is not stable and you don't want to make your image very dark your final option is to look for all pixels that are both very bright, and brighter in the red channel than they are in green and blue (if you are using a red laser). This system will still be distracted by white spots, but not as much as just finding the bright pixels. If the center of your laser-pointer spot is indeed showing up as bright white regardless of laser color then this technique will allow you to find "rings" around this bright spot (the outer part of the dot where the laser is not as bright as it is in the center so that it shows up with the actual color of the laser in the image). You can then use simple morphological operations, (probably closing is enough) to fill these circles.
假设您使用以下颜色之一的激光:红色、绿色、蓝色。
如果激光点看起来非常亮(至少在一个通道中,例如红色),那么只需将图像/通道的阈值设置为 200(例如灰度值 200),就会为您留下一些激光的候选点。如果该区域的其他通道较暗,那么您就知道它是正确颜色的亮光。按大小稍微过滤一下,您就有很大的机会找到该地点。
Let say you use a laser of one of these colors: red, green, blue.
If the laser dot appears very bright (at least in one channel, e.g. red) then simply thresholding the image/channel at, say greyvalue of 200, will leave you with a few candidates for the laser light. If the other channels are dark(er) in this area, then you know it is a bright light of the right color. A little filtering by size, and you have a good chance of finding the spot.
如果您在网络摄像头上安装红外滤镜,您的投影将不会被拾取,从而使激光点的检测变得更加容易(使用简单的背景扣除等)假设激光笔发射红外光......
If you stick a IR filter on your webcam, your projection will not be picked up, making the detection of the laser point much easier (using simple background subtraction e.t.c) That's assuming the laser pointer emits IR light...
正如其他答案中所建议的,搜索颜色可能是一个好主意。
您应该考虑寻找特定的颜色范围。最好的方法是将图片转换为 HSL 或 HSV 颜色空间。
更多信息请参阅维基百科。
然后你就有了三个渠道:
色调(=颜色)、饱和度和亮度(或值)。
使用
cv::inRange(hsv, cv::Scalar(159, 135, 165), cv::Scalar(179, 255, 200), inRange);
您现在可以生成黑白图像,显示颜色范围内的像素。标量是每个通道的低值和高值。
在此示例中,您将获得颜色在 159 到 179(色调)之间、饱和度在 135 到 255 之间、值在 165 到 200 之间的像素。
也许这可以改善您的跟踪。
As suggested in other answers, searching for the color might be a good idea.
You should consider to look for a specific color range. Best way to do this is to convert the picture to HSL or HSV color space.
More information on Wikipedia.
Then you have three channels:
hue (=color), saturation and lightness( or value).
With
cv::inRange(hsv, cv::Scalar(159, 135, 165), cv::Scalar(179, 255, 200), inRange);
you can now generate a Black and white image, which shows what pixels are in the color range.The scalars are the low and high values for each channel.
In this example you will get pixels with a color between 159 and 179 (hue), saturation between 135 and 255 and value between 165 and 200.
Maybe this can improve your tracking.
这段代码怎么样
https://www.youtube.com/watch?v=MKUWnz_obqQ
https://github.com/niitsuma/detect_laser_pointer
在此代码中,将观察到的 HSV 颜色与注册颜色进行比较使用 Hotelling 的 t 方检验
How about this code
https://www.youtube.com/watch?v=MKUWnz_obqQ
https://github.com/niitsuma/detect_laser_pointer
In this code, observed HSV color is compared to registered color using Hotelling's t square test
尝试模板加工。
首先你将指针“指向”一个特定的地方,这样寺庙就可以完成。然后你就去找它。
或者,正如 jilles de wit 所说,您可以获取最后 2 帧的差异,可能差异会向您显示指针。
将最后 2 帧转换为灰度,然后应用 SUB 功能。
try Template Maching.
first you "point the pointer" to an specific place so the temple can be done. Then you just look for it.
Or, as jilles de wit said, you can take the difference of the last 2 frames, probably the difference will show you the pointer.
Convert the last 2 frames do gray scale, then apply the SUB function.