关于c ++:OpenCV针对图像集检测图像

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小。很少有人在上面写了文字,但其他人只是标志。这里有一个例子:

enter image description here

enter image description here

你们知道我怎么做吗?


这里有几件事。我将分解你的问题,并指出一些可能的解决办法。

  • 分类:您的主要任务是确定某个图像是否属于某个类。这个问题本身可以分解为几个问题:

    • 特征表示您需要决定如何对特征建模,即如何在特征空间中表示每个图像,以便训练分类器来分离这些类。特征表示本身已经是一个很大的设计决策。可以(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)。