7

(这出来有点长,但它主要是一个很难理解的解释:)

对于我拥有的项目,我需要识别一般形式的对象,如下所示 -

待识别对象

在包含不同形状的更大图像中,比如这个 - 容器图像

正如你所看到的,我正在寻找的对象是一条红线,两边都有十字(最后一张图片中有 5 个)。我有大约 4,000 张图像库,我需要在其中找到对象,其中一些包含这些对象,而其中一些不包含,就像这张图片 - 没有所需对象的图像

在做了一些研究之后,我发现使用 haar 级联和 openCV 是可行的方法,所以我编写了一个脚本,遍历所有上述 4,000 张图像并提取分离的轮廓,就像这个问题中的第一张图像一样。

然后,我遍历了许多轮廓,抓取了大约 150 个(即 150 个仅包含我需要的对象的文件,类似于第一个图像)和大约 180 个不包含我需要的对象的图像(类似于第三张图在这里)。

然后我开始了训练过程,使用了几个教程,但主要是这个

这样做时,我遇到了一个问题 - 如您所见,所需的双叉对象的图像大小不同,甚至没有相同的比例(因为它们可以以任何角度出现 - 水平,对角, ETC..)。

起初我尝试使用不同尺寸的图像,但这会导致训练过程中出现错误,因此,为了解决这个问题,我将所有正图像的尺寸更改为 350x350(其中一个的最大比例)对象)。为了清楚起见-我没有调整图像的大小-我只是在周围添加了空白以使所有图像都为 350x350 像素。

然后我按照教程中的建议完成了培训过程 - 我创建了样本(宽度 - 24,高度 - 24)并创建了一个级联 xml 文件,结果证明它不是很大(45kb)。

现在,我知道 150 张正面图像和 180 张负面图像并不多,但我想至少在过滤更多图像并投入更多时间之前进行概念验证。

完成 cascade.xml 文件后,我尝试使用它来定位某些图像中的某些对象(使用cv2.CascadeClassifier('cascade.xml')并且cascade.detectMultiScale(img)每次尝试都返回零结果。

最后,我什至尝试在其中一张正面图像中定位一个对象(其中只包含一个所需的对象),但它也返回零结果。

我尝试调整参数,cascade.detectMultiScale(img)目前我正在训练一个具有 36x36 样本的级联文件,但我不相信它会起作用。

由于我对这些东西很陌生,所以我想知道我做错了什么,我想我会在这里问。

进一步来说:

  • 您认为在这种情况下使用 haar 是否正确?我应该使用其他物体识别方法吗?
  • 正面图像尺寸会成为问题的根源吗?如果是这样,我该怎么做?

如果我没有包含一些重要数据,请让我知道我会发布它。

非常感谢你的帮助,丹

4

1 回答 1

5

我想,你不会从这里的 haar(或 hog)级联分类器中得到好的结果。

  • 您的“针”没有足够的特征/角(只有 2 个十字和一条线)
  • 级联分类器对旋转非常敏感。看来您的对象可以在这里进行任意旋转。
  • 如果你训练一个具有许多不同旋转的分类器,它只会过拟合。
  • 如果您训练许多分类器(每个旋转一个), - 相同。;(

所以,恕我直言,对这种方法没有太大希望。

我会改为使用轮廓/形状匹配:

void findNeedles( const std::vector<cv::Point> & needle_contour, const cv::Mat & haystack_binarized)
{
    int nfound = 0;
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(haystack_binarized, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
    for (size_t i = 0; i < contours.size(); i++)
    {
        // pre-filter for size:
        if ( ( contours[i].size() < needle_contour.size()/2 )
          || ( contours[i].size() > needle_contour.size()*2 ) )
          continue;

        double d = cv::matchShapes(contours[i],needle_contour,CV_CONTOURS_MATCH_I2,0);
        if ( d < 8.4 ) // heuristic value, experiments needed !!
        {
            cv::drawContours(haystack_binarized, contours, i, 128, 3);
            nfound ++;
        }
    }
    cerr << nfound << " objects found" << endl;
    cv::imshow("haystack",haystack_binarized);
    //imwrite("hay.png",haystack_binarized);
    cv::waitKey();
}


int main()
{
    // 1. get the contour of our needle:
    Mat needle = imread("needle.png",0);
    Mat needle_b; 
    threshold(needle,needle_b,120,255,1); 
    imshow("needle",needle_b);

    std::vector<std::vector<cv::Point>> needle_conts;
    cv::findContours(needle_b, needle_conts, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
    if ( needle_conts.size() == 0 )
    {
        std::cout << " no contour Found" << std::endl;
        return -1;
    }
    std::vector<cv::Point> needle_contour = needle_conts[0];

    // 2. check a positive sample:
    Mat haypos = imread("hay_pos.png",0);
    Mat haypos_b; 
    threshold(haypos,haypos_b,120,255,1);
    findNeedles(needle_contour, haypos_b);

    // 3. check a negative sample:
    Mat hayneg = imread("hay_neg.png",0);
    Mat hayneg_b; 
    threshold(hayneg,hayneg_b,120,255,1);
    findNeedles(needle_contour, hayneg_b);

    return 0;
}

--------------

> haystack.exe
5 objects found
0 objects found

在此处输入图像描述

于 2014-05-11T09:29:11.840 回答