检测到方形opencv但检测到的方形比它应该更多

时间:2013-11-01 01:28:15

标签: c++ opencv image-processing computer-vision detection

我想检测图片的方块,但在计算现有方块的数量时遇到问题。在图片中有6个方块,但有8个被检测到,其中3个被检测到两次。

这是图像检测的结果 http://i698.photobucket.com/albums/vv347/holybring18/Screenshot_2013-11-01-07-37-17.png

这是预处理 http://i698.photobucket.com/albums/vv347/holybring18/Screenshot_2013-11-01-07-37-49.png

这是我的代码,我从squares.cpp示例代码中获取。我使用母语在我的Android中对此进行编码,因此有关正方形检测的所有内容都由我的本机代码处理。但我修改了一点因为mixChannels()有一个恼人的错误,我不知道如何解决它。

// jlong from java convert to references to Mat
// for image source and image result
Mat& matsrc = *(Mat*)alamatMatSrc;
Mat& matres = *(Mat*)alamatMatRes;

// needed matrix
Mat gray;
Mat blur;
Mat bw;
Mat dil;
Mat er;

// tempat menyimpan kontur dan estimasi sudut
vector<vector<Point> > squares;
vector<vector<Point> > contours;
vector<Point> approx;

// convert to grayscale
cvtColor(matsrc, gray, CV_BGR2GRAY);

// blur for reducing noise
medianBlur(gray, blur, 9);

// edge detection with Canny
Canny(blur, bw, 0, 50);

// dilate to ensure there is no cut off lines
dilate(bw, dil, Mat(), Point(-1,-1));

// find all contours
findContours(dil, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

// loop to find the squares
for (size_t i = 0; i < contours.size(); i++) {

    // approximate contour with accuracy proportional
    // to the contour perimeter
    approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

    // Note: absolute value of an area is used because
    // area may be positive or negative - in accordance with the
    // contour orientation
    if (approx.size() == 4 && fabs(contourArea(Mat(approx))) > 1000 && isContourConvex(Mat(approx))) {
        double maxCosine = 0;

        for (int j = 2; j < 5; j++) {
            Point pt1 = approx[j%4];
            Point pt2 = approx[j-2];
            Point pt3 = approx[j-1];
            double cosine = fabs(sudut(pt1, pt2, pt3));
            maxCosine = MAX(maxCosine, cosine);
            }
        if (maxCosine < 0.1) squares.push_back(approx);
    }
}

这是我调用本机

时的java代码
// provide Mat for the source and for the result
mymatsrc = new Mat(mybmp.getWidth(), mybmp.getHeight(), CvType.CV_8UC1);
mymatres = new Mat(mybmp.getWidth(), mybmp.getHeight(), CvType.CV_8UC1);

// convert bitmap to Mat, then pass the Mat adress to native, process, and convert it again to bitmap
Utils.bitmapToMat(mybmp, mymatsrc);
Utils.bitmapToMat(mybmp, mymatres);
preProcess(mymatsrc.getNativeObjAddr(), mymatres.getNativeObjAddr());
Utils.matToBitmap(mymatres, mybmp);

// show the processed picture
imageView.setImageBitmap(mybmp);

我的观点是:

  1. 为什么我的代码检测到的方块比它应该更多?
  2. 我该如何解决这个问题?
  3. 我发现一些人在mixChannel()上遇到错误,我找不到解决方案,有人知道如何解决这个问题,这是错误信息。
  4.   

    无效的参数'候选者是:void mixChannels(const cv :: Mat *,   ?,cv :: Mat *,?,const int *,?)void mixChannels(const   cv :: _ InputArray&amp;,const cv :: _ InputArray&amp;,const   的std ::矢量&GT; &amp;)void mixChannels(const   的std ::矢量&GT; &安培;,   的std ::矢量&GT; &amp;,const int *,?)'

1 个答案:

答案 0 :(得分:0)

  1. 由于medianBlur()的内核大小为9像素。

  2. 将内核大小减小到3或5。

  3. 请参阅mixChannels() documentation

  4. 来自squares.cpp

    // find squares in every color plane of the image
    for( int c = 0; c < 3; c++ )
    {
        int ch[] = {c, 0};
        mixChannels(&timg, 1, &gray0, 1, ch, 1);
    

    必须预先分配dst gray0。在每个迭代中,c指定的频道将从timg复制到gray0