4

我的问题类似于OpenCV:检测视频源中的 闪烁灯 openCV 检测闪烁灯

我想从任何具有 LED 对象的图像中检测 LED 开/关状态。LED 对象可以是任意大小(但主要是圆形)。获取该图像中所有 LED 的位置非常重要,尽管它可以打开或关闭。首先,我想获得仅打开的 LED 的状态和位置。现在图像源对于我的工作来说是静态的,但它必须来自任何具有发光 LED 的产品的视频。所以没有机会让模板图像减去背景。

我曾尝试将 OpenCV(OpenCV 的新手)与阈值、轮廓和圆形方法一起使用,但未发现成功。如果有任何源代码或解决方案,请分享。解决方案可以是任何东西,不仅可以使用 OpenCV,它会给我带来结果。这将不胜感激。

与其他两个问题的不同之处在于,我想获取图像中 LED 的数量,无论它可以打开还是关闭,以及所有 LED 的状态。我知道这很复杂。首先,我试图检测图像中发光的 LED。我已经实现了我在下面分享的代码。我有不同的实现,但下面的代码能够通过绘制轮廓向我展示发光的 LED,但轮廓的数量比发光的 LED 多。所以我无法得到至少发光的 LED 总数。请建议我您的意见。

int main(int argc, char* argv[])
{

IplImage* newImg = NULL;
IplImage* grayImg = NULL;
IplImage* contourImg = NULL;
float minAreaOfInterest = 180.0;
float maxAreaOfInterest = 220.0;
//parameters for the contour detection
CvMemStorage * storage = cvCreateMemStorage(0);
CvSeq * contours = 0;
int mode = CV_RETR_EXTERNAL;
mode = CV_RETR_CCOMP; //detect both outside and inside contour
cvNamedWindow("src", 1);
cvNamedWindow("Threshhold",1);
//load original image
newImg = cvLoadImage(argv[1], 1);

IplImage* imgHSV = cvCreateImage(cvGetSize(newImg), 8, 3);
cvCvtColor(newImg, imgHSV, CV_BGR2HSV);

cvNamedWindow("HSV",1);
cvShowImage( "HSV", imgHSV );
IplImage* imgThreshed = cvCreateImage(cvGetSize(newImg), 8, 1);

cvInRangeS(newImg, cvScalar(20, 100, 100), cvScalar(30, 255, 255), imgThreshed);
cvShowImage( "src", newImg );

cvShowImage( "Threshhold", imgThreshed );

//make a copy of the original image to draw the detected contour
contourImg = cvCreateImage(cvGetSize(newImg), IPL_DEPTH_8U, 3);
contourImg=cvCloneImage( newImg );
cvNamedWindow("Contour",1);
//find the contour
cvFindContours(imgThreshed, storage, &contours, sizeof(CvContour), mode, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
int i = 0;
for (; contours != 0; contours = contours->h_next)
{
    i++;
    //ext_color = CV_RGB( rand()&255, rand()&255, rand()&255 ); //randomly coloring different contours      
    cvDrawContours(contourImg, contours, CV_RGB(0, 255, 0), CV_RGB(255, 0, 0), 2, 2, 8, cvPoint(0,0));
}
printf("Total Contours:%d\n", i);
cvShowImage( "Contour", contourImg );

cvWaitKey(0);
cvDestroyWindow( "src" ); cvDestroyWindow( "Threshhold" );
cvDestroyWindow( "HSV" );
cvDestroyWindow( "Contour" );
cvReleaseImage( &newImg ); cvReleaseImage( &imgThreshed ); 
cvReleaseImage( &imgHSV );
cvReleaseImage( &contourImg );



}
4

1 回答 1

8

昨天晚上我有一些时间,这是一个(非常)简单和部分的解决方案,对我来说很好。我创建了一个可以直接克隆的 git 存储库:

git://github.com/jlengrand/image_processing.git

并使用 Python 运行

$ cd image_processing/LedDetector/
$ python leddetector/led_highlighter.py

你可以在这里看到代码

我的方法:

  • 转换为单通道图像
  • 搜索最亮的像素,假设我们至少有一个 LED 亮着且背景为暗色,就像您的图像一样
  • 创建具有图像最亮部分的二值图像
  • 从图像中提取斑点,检索它们的中心和 LED 的数量。

该代码此时仅考虑了一个图像,但您可以通过循环来增强它以获取一批图像(我已经在我的存储库中提供了一些示例图像。)您只需要在找到的中心附近玩一下对于 LED,因为它们从一个图像到另一个图像可能不是一个像素准确的(中心可能会稍微移动)。

为了使算法更健壮(知道是否有 LED 亮起,找到一个自动且非硬编码的边距值),您可以使用直方图(放置在extract_bright中)进行一些操作。我已经为此创建了该功能,您只需要对其进行一些增强即可。

有关输入数据的更多信息:Opencv目前只接受 avi 文件,因此您必须将 mp4 文件转换为 avi(在我的情况下未压缩)。我用了这个,效果很好。由于某种原因,queryframe函数导致我的计算机出现内存泄漏。这就是我创建grab_images函数的原因,该函数将avi 文件作为输入并创建一批您可以更轻松使用的jpg 图像。

这是图像的结果:

输入图像:

输入示例

二进制图像:

二进制结果(图像最亮的部分)

最后结果 :

最终结果(围绕 LED 的边界框)

希望这可以帮助。. .

编辑 :

如果您想使用此图像,您的问题会稍微复杂一些。我发布的方法仍然可以使用,但需要稍微复杂一些。

您想检测显示“信息”(状态、带宽……)的 LED 并丢弃设计部分。

我看到了三个简单的解决方案:

  • 您对 LED 的位置有一定的了解。在这种情况下,您可以应用相同的方法,但在整个图像的精确部分(使用 cv.SetImageROI)。
  • 您对 LED 的颜色有一个预先了解(您可以在图像上看到有两种不同的颜色)。然后您可以搜索整个图像,然后应用颜色过滤器来限制您的选择。
  • 你没有以前的知识。在这种情况下,事情变得有点复杂。我倾向于说没用的 LED 应该都具有相同的颜色,并且状态 LED 通常会闪烁。这意味着通过在该方法中添加一个学习步骤,您可能能够看到实际上必须选择哪些 LED 是有用的。

希望这会带来更多的思考

于 2012-05-25T07:34:03.387 回答