OpenCV detect image against a image set
我想知道如何使用OpenCV在我的摄像机上检测图像。图像可以是500个图像中的一个。
我现在做的是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.videoCamera = [[CvVideoCamera alloc] initWithParentView:imageView]; self.videoCamera.delegate = self; self.videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack; self.videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPresetHigh; self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait; self.videoCamera.defaultFPS = 30; self.videoCamera.grayscaleMode = NO; } -(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; [self.videoCamera start]; } #pragma mark - Protocol CvVideoCameraDelegate #ifdef __cplusplus - (void)processImage:(cv::Mat&)image; { // Do some OpenCV stuff with the image cv::Mat image_copy; cvtColor(image, image_copy, CV_BGRA2BGR); // invert image //bitwise_not(image_copy, image_copy); //cvtColor(image_copy, image, CV_BGR2BGRA); } #endif |
我想检测的图像是2-5Kb小。很少有人在上面写了文字,但其他人只是标志。这里有一个例子:
你们知道我怎么做吗?
这里有几件事。我将分解你的问题,并指出一些可能的解决办法。
分类:您的主要任务是确定某个图像是否属于某个类。这个问题本身可以分解为几个问题:
特征表示您需要决定如何对特征建模,即如何在特征空间中表示每个图像,以便训练分类器来分离这些类。特征表示本身已经是一个很大的设计决策。可以(i)使用n个箱子计算图像的柱状图并训练分类器,或者(ii)选择一系列随机补丁比较,例如在随机森林中。然而,在培训之后,您需要评估您的算法的性能,看看您的决策有多好。
有一个已知的问题叫做过度拟合,即当你学习得太好时,你就不能推广你的分类器。这通常可以通过交叉验证来避免。如果您不熟悉假阳性或假阴性的概念,请看本文。
一旦定义了特征空间,就需要选择一种算法来训练这些数据,这可能是您最大的决定。每天都有几种算法出现。举几个经典的例子:朴素贝叶斯、支持向量机、随机森林,最近社区通过深入学习取得了巨大的成果。其中每一个都有自己的特定用法(例如,SVM ARES great for binary classification),您需要熟悉这个问题。你可以从简单的假设开始,比如随机变量之间的独立性,然后训练一个朴素的贝叶斯分类器来尝试分离你的图像。
补丁:现在您提到要识别网络摄像头上的图像。如果要打印图像并在视频中显示,则需要处理几个问题。有必要在大图像上定义补丁(从网络摄像头输入),在其中为每个补丁构建一个功能表示,并按照与上一步相同的方式进行分类。为此,您可以滑动一个窗口,对所有补丁进行分类,以查看它们是属于负类还是属于正类。还有其他的选择。
尺度:考虑到你能够检测出大图像中图像的位置并对其进行分类,下一步就是放松固定尺度的玩具假设。为了处理多尺度的方法,你可以图像金字塔,这几乎可以让你执行多分辨率的检测。另一种方法可以考虑使用关键点探测器,比如筛和冲浪。在SIFT中,有一个图像金字塔,允许不变性。
到目前为止,我们假设您有正交投影下的图像,但很可能您将有轻微的透视投影,这将使整个先前的假设失败。一个简单的解决方案是,在构建特征向量进行分类之前,检测图像白色背景的角点并校正图像。如果你使用过筛或冲浪,你可以设计一种方法来避免显式处理。不过,如果你的输入只是正方形的补丁,比如Artoolkit,我会去手动修正。
我希望我能给你一个更好的了解你的问题。
我建议您使用冲浪,因为照片可以与您的相机保持不同的距离,即更改比例。我做了一个类似的实验,冲浪和预期的一样。但是冲浪有非常困难的调整(和昂贵的操作),你应该尝试不同的设置之前,你得到所需的结果。这里有一个链接:http://docs.opencv.org/modules/nonfree/doc/feature_detection.htmlYouTube视频(C,但可以给出一个想法):http://www.youtube.com/watch?V= ZJXWPKCQQJC
我可能不够资格回答这个问题。上次我认真使用opencv的时候还是1.1。但只是想了想,希望能有所帮助(目前我对DIP和ML感兴趣)。
我认为,如果你只需要对一幅图像进行分类,如果这幅图像只是你500幅图像中的一幅(或与之非常相似),那么这将是一项更简单的任务。为此,您可以使用SVM或一些神经网络(Felix已经给出了一个很好的枚举)。
然而,你的问题似乎是你需要首先在你的网络摄像头中找到这个候选图像,而你事先对它的位置知之甚少。(让我们知道是否如此。我认为这很重要。)
如果是这样,更困难的问题是检测/定位候选图像。我没有一个通用的解决方案。我要做的第一件事是看看你的500张图片中是否有一些常见的特征(例如,是否所有图片都被一个红色圆圈包围,或者其中一半有圆圈,一半有矩形)。如果能做到这一点,问题会更简单(类似于人脸检测问题,有很好的解决方案)。
换言之,这意味着你首先将500幅图像分为几个具有共同特征的组(通过人类),然后首先检测该组,然后缩放并使用上述技术将它们分为良好的结果。这样,它将比逐个检测500个图像更容易被计算接受。
顺便说一句,这个PPT将有助于提供特征提取和图像匹配的视觉线索http://courses.cs.washington.edu/courses/cse455/09wi/letcs/letc6.pdf。
检测与识别:检测图像只是在背景上找到它,从你的评论中我意识到你的歌声可能被背景包围了。如果你能在识别符号之前从背景中裁剪出你的符号(检测),这可能会有助于你的算法。识别是下一个阶段,假设您可以将裁剪后的图像正确分类为以前看到的图像。
如果你需要实时的速度和缩放/旋转不变性,那么无论是筛选还是冲浪都不会这么快。现在,如果你把图像处理的负担转移到一个学习阶段,就像麻风病人做的那样,你可以做得更好。简而言之,他对每个模式进行了一系列仿射变换,并通过大量的二进制比较测试,训练了一个二进制分类树来正确识别每个点。树的速度非常快,更不用说大部分处理都是离线完成的。这种方法对平面外旋转的鲁棒性也比筛或冲浪强。您还将了解树分类,这有助于您完成最后一个处理阶段。
最后,一个识别阶段不仅基于匹配的数量,而且基于匹配的几何一致性。既然你的符号看起来是平的,我建议你在计算匹配点的时候,要么找到仿射变换,要么找到同形变换。
查看您的代码,尽管我意识到您可能不会遵循这些建议中的任何一个。这可能是一个很好的起点,您可以先阅读决策树,然后使用一些示例代码(请参阅上面提到的链接中的moungly.cpp)。