java - 为什么 cvFindContours() 方法不能在 javacv 中正确检测轮廓?

标签 java opencv javacv

我在 StackOverflow 中解决了许多问题,并且能够开发小程序来正确检测正方形和矩形。这是我的示例代码

public static CvSeq findSquares(final IplImage src, CvMemStorage storage) {
    CvSeq squares = new CvContour();
    squares = cvCreateSeq(0, sizeof(CvContour.class), sizeof(CvSeq.class), storage);
    IplImage pyr = null, timg = null, gray = null, tgray;
    timg = cvCloneImage(src);
    CvSize sz = cvSize(src.width(), src.height());
    tgray = cvCreateImage(sz, src.depth(), 1);
    gray = cvCreateImage(sz, src.depth(), 1);
    // cvCvtColor(gray, src, 1);
    pyr = cvCreateImage(cvSize(sz.width() / 2, sz.height() / 2), src.depth(), src.nChannels());
    // down-scale and upscale the image to filter out the noise
    // cvPyrDown(timg, pyr, CV_GAUSSIAN_5x5);
    // cvPyrUp(pyr, timg, CV_GAUSSIAN_5x5);
    // cvSaveImage("ha.jpg",timg);
    CvSeq contours = new CvContour();
    // request closing of the application when the image window is closed
    // show image on window
    // find squares in every color plane of the image
    for (int c = 0; c < 3; c++) {
        IplImage channels[] = { cvCreateImage(sz, 8, 1), cvCreateImage(sz, 8, 1), cvCreateImage(sz, 8, 1) };
        channels[c] = cvCreateImage(sz, 8, 1);
        if (src.nChannels() > 1) {
            cvSplit(timg, channels[0], channels[1], channels[2], null);
        } else {
            tgray = cvCloneImage(timg);
        }
        tgray = channels[c];
        // // try several threshold levels
        for (int l = 0; l < N; l++) {
            // hack: use Canny instead of zero threshold level.
            // Canny helps to catch squares with gradient shading
            if (l == 0) {
                // apply Canny. Take the upper threshold from slider
                // and set the lower to 0 (which forces edges merging)
                cvCanny(tgray, gray, 0, thresh, 5);
                // dilate canny output to remove potential
                // // holes between edge segments
                cvDilate(gray, gray, null, 1);
            } else {
                // apply threshold if l!=0:
                cvThreshold(tgray, gray, (l + 1) * 255 / N, 255,
                        CV_THRESH_BINARY);
            }
            // find contours and store them all as a list
            cvFindContours(gray, storage, contours, sizeof(CvContour.class), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
            CvSeq approx;
            // test each contour
            while (contours != null && !contours.isNull()) {
                if (contours.elem_size() > 0) {
                    approx = cvApproxPoly(contours, Loader.sizeof(CvContour.class), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contours) * 0.02, 0);
                    if (approx.total() == 4 && Math.abs(cvContourArea(approx, CV_WHOLE_SEQ, 0)) > 1000 && cvCheckContourConvexity(approx) != 0) {
                        double maxCosine = 0;
                        for (int j = 2; j < 5; j++) {
                            // find the maximum cosine of the angle between
                            // joint edges
                            double cosine = Math.abs(angle(
                                            new CvPoint(cvGetSeqElem(
                                                    approx, j % 4)),
                                            new CvPoint(cvGetSeqElem(
                                                    approx, j - 2)),
                                            new CvPoint(cvGetSeqElem(
                                                    approx, j - 1))));
                            maxCosine = Math.max(maxCosine, cosine);
                        }
                        if (maxCosine < 0.2) {
                            CvRect x = cvBoundingRect(approx, l);
                            if ((x.width() * x.height()) < 50000) {
                                System.out.println("Width : " + x.width()
                                        + " Height : " + x.height());
                                cvSeqPush(squares, approx);
                            }
                        }
                    }
                }
                contours = contours.h_next();
            }
            contours = new CvContour();
        }
    }
    return squares;
}

我使用这张图片来检测矩形和正方形

enter image description here

我需要识别以下输出

enter image description here

enter image description here

但是当我运行上面的代码时,它只检测到以下矩形。但我不知道这是什么原因。请有人解释一下原因。

这是我得到的输出。

enter image description here

请在上面的代码中解释问题并给出一些建议来检测这个正方形和矩形。

最佳答案

给定一个掩码图像(二进制图像,如您的第二个图),cvFindContours() 为您提供轮廓(几个点列表)。
看这个链接:http://dasl.mem.drexel.edu/~noahKuntz/openCVTut7.html

关于java - 为什么 cvFindContours() 方法不能在 javacv 中正确检测轮廓?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11542259/

相关文章:

java - OpenCV 错误 : Bad argument (The array of layer neuron counters must be an integer vector)

opencv - 使用JavaCV显示摄像机的实时图像

android - 将 Android MediaCodec 编码的 H264 数据包复用到 RTMP 中

java - 我想使用 mysql 查询或使用 xmlrpc api 从 WordPress 获取最新 3 篇帖子,其中包含标题、描述、特色图像、发布日期

python - 无法使用 sort_contors 构建七段 OCR

java - 在java中安排电子邮件通知警报

python - 从 Homography 矩阵计算 Essential 矩阵

android - 静态链接OpenCV 2.4.3.2

java - ArrayAdapter要求资源ID为DialogFragment中的TextView

java - 如何替换已弃用的方法 Date.setHours(int)?