9

目前我正在开发图像处理项目,我正在使用 javacv 开发图像处理组件。我能够提取图像中一些有趣的部分,现在我需要读取这些对象的 x 和 y 坐标。这是我提取的图像

在此处输入图像描述

我需要识别这些对象并在这些对象周围画出正方形。我浏览了一些教程并尝试使用以下代码识别对象。

    IplImage img="sourceimage";
    CvSize sz = cvSize(img.width(), img.height());
    IplImage gry=cvCreateImage(sz, img.depth(), 1);
    cvCvtColor(img, gry, CV_BGR2GRAY);
    cvThreshold(gry, gry, 200, 250, CV_THRESH_BINARY);


    CvMemStorage mem = CvMemStorage.create();
    CvSeq contours = new CvSeq();
    CvSeq ptr = new CvSeq();
    cvFindContours(gry, mem, contours, Loader.sizeof(CvContour.class) , CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));

    CvRect boundbox;

    for (ptr = contours; ptr != null; ptr = ptr.h_next()) {
        boundbox = cvBoundingRect(ptr, 0);
        if(boundbox.height()>10||boundbox.height()>10){
            cvRectangle( gry, cvPoint( boundbox.x(), boundbox.y() ), cvPoint( boundbox.x() + boundbox.width(), boundbox.y() + boundbox.height()),CvScalar.BLUE, 0, 0, 0 );
            System.out.println(boundbox.x()+", "+boundbox.y());
        }
    }
    cvShowImage("contures", gry);
    cvWaitKey(0);

但它不会在对象周围绘制为矩形。我想知道我是否可以使用 cvFindContours 方法来识别这些对象?请问有人可以解释如何使用 javacv/opencv 归档我的目标吗?

4

5 回答 5

11

尝试通过以下代码,它将为您的问题提供答案。

    IplImage img=cvLoadImage("pathtosourceimage");
    CvSize cvSize = cvSize(img.width(), img.height());
    IplImage gry=cvCreateImage(cvSize, img.depth(), 1);
    cvCvtColor(img, gry, CV_BGR2GRAY);
    cvThreshold(gry, gry, 200, 255, CV_THRESH_BINARY);
    cvAdaptiveThreshold(gry, gry, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, 11, 5);

    CvMemStorage storage = CvMemStorage.create();
    CvSeq contours = new CvContour(null);

    int noOfContors = cvFindContours(gry, storage, contours, Loader.sizeof(CvContour.class), CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, new CvPoint(0,0));

    CvSeq ptr = new CvSeq();

    int count =1;
    CvPoint p1 = new CvPoint(0,0),p2 = new CvPoint(0,0);

    for (ptr = contours; ptr != null; ptr = ptr.h_next()) {

        CvScalar color = CvScalar.BLUE;
        CvRect sq = cvBoundingRect(ptr, 0);

            System.out.println("Contour No ="+count);
            System.out.println("X ="+ sq.x()+" Y="+ sq.y());
            System.out.println("Height ="+sq.height()+" Width ="+sq.width());
            System.out.println("");

            p1.x(sq.x());
            p2.x(sq.x()+sq.width());
            p1.y(sq.y());
            p2.y(sq.y()+sq.height());
            cvRectangle(img, p1,p2, CV_RGB(255, 0, 0), 2, 8, 0);
            cvDrawContours(img, ptr, color, CV_RGB(0,0,0), -1, CV_FILLED, 8, cvPoint(0,0));
            count++;

    }

    cvShowImage("contures",img);
    cvWaitKey(0);

这是我为您的给定图像得到的输出。

在此处输入图像描述

于 2012-09-01T09:49:15.597 回答
4

cvFindContours 是您问题的正确解决方案。
而且我已经验证它适用于您的图像。
这是我的实验

你里面有 System.out.println,输出是什么?

cvFindContours 使用起来可能很棘手,我已经将它包装成一个更通用的 C++ 函数。我还使用一个名为 vBlob 的类来描述 cvFindContours 检测到的对象。从我从您的 java 代码中看到的,java 版本 API 与 C/C++ 版本非常相似。所以重写它并不难。

附言。阿斯特给出了正确的答案。

于 2012-08-26T09:58:26.343 回答
4

您知道该功能在黑色背景上findContours找到白色轮廓吗?

只需bitwise_not对您的图像执行(或 JavaCV 中的类似操作),然后在此之后 apply findContours。这实际上可以解决您的问题。

于 2012-08-27T05:57:25.117 回答
4

无需第三方库!您正在寻找可以在 OpenCV 中使用称为边界框的技术来实现:

在此处输入图像描述

诀窍是用来cvFindContours()检索轮廓,然后cvApproxPoly()改进结果。请注意,您必须使用cvNot()因为cvFindContours()搜索白色轮廓来反转输入图像的颜色。

  • 在这篇文章中有一个很好的轮廓介绍。
  • 有一个Java 演示,它实现了一个版本的边界框来检测车牌。

顺便cvMinEnclosingCircle()将圆心返回为CvPoint2D32f

于 2012-08-27T23:55:39.870 回答
2

我正在使用 c++ api,但我认为 javacv 中也应该有一些名为 drawContours 或 cvDrawContours 的函数,它使用 findContours 的输出。

于 2012-08-29T11:25:07.697 回答