python - 使用 HAAR 级联和 OpenCV 识别图像中的对象

标签 python opencv haar-classifier

(这有点长,但基本上是一个不难理解的解释:)

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

Object to be recognised

在包含不同形状的更大图像中,例如这个 - container image

如您所见,我正在寻找的对象是一条红线,每边都有十字(最后一张图片中有 5 个十字)。 我有大约 4,000 张图片,我需要在其中找到对象,其中一些包含这些对象,而另一些则不包含这些对象,例如这张图片 - An image without the desired object

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

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

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

在这样做的时候,我遇到了一个问题——正如你所看到的,所需的双叉对象的图像大小不一样,甚至不具有相同的比例(因为它们可以以任何角度出现 -水平、对角线等)。

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

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

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

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

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

我尝试调整 cascade.detectMultiScale(img) 的参数,目前我正在使用 36x36 样本训练级联文件,但我不确定它是否有效。

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

更具体地说:

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

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

非常感谢您的帮助, 丹

最佳答案

我猜,你不会从这里的 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

enter image description here

关于python - 使用 HAAR 级联和 OpenCV 识别图像中的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23587296/

相关文章:

python - 如何获得一个程序来计算文件中每个员工的加薪?

python - 如何使用opencv在视频中仅检测左眼?

c++ - 融合多个 Haar 分类器进行人脸检测

python - 照片上的透明蒙版,带有正方形坐标

python - 告诉 PyCharm 代码生成类的字段

python - 如何从我自己的 Instagram api 获取所有媒体?

python - 如何按进程数打印前10个用户?

c++ - OpenCV C++ 接口(interface)如何管理 ROI

Python OpenCV - 文件旋转,但颜色值被覆盖

android - 如何从 Android Studio 调用 C++ 源代码?