打开cv chessBoard和2d识别

时间:2014-05-21 21:16:09

标签: c++ opencv

我在open cv中做一个项目。 目标是识别棋盘上的2d棋子及其位置。 算法是这样的:

  1. 在图片上运行canny。
  2. 在图像上运行houghLines。 3.Merge关闭线 4.sort到垂直线和水平线。 5.排队并选择所有边界线+1(所以我们得到实际的板线而不是板线)
  3. 找到边界线的交叉点。 (4个角落)
  4. 使用找到的角落进行同步。
  5. 将新图像拆分为8X8单元格(长度/ 8,宽度/ 8)。
  6. 使用模板匹配检测船上和地点的碎片。
  7. 现在我坚持做Homography。 有时我会检测到外板的线条,有时我不会,有时我会在外板上检测到2条线。 我在网上找到的合并线功能似乎并没有做得很好。可以有2条垂直线,它们不会合并。

    void processChessboardImage(Mat & image)
    {
        Vec2f  temp(0,0);
        vector<Vec2f> lines;
        vector<Vec2f> boarderLines;
        vector<Vec2f> verticalLines;
        vector<Vec2f> horizontalLines;
        Mat canny_output,hough_output;
    
        canny_output = CannyOnImage(image);
    
        //cvtColor(canny_output, image, CV_GRAY2BGR);
        HoughLines(canny_output, lines, 1, CV_PI/180, 120, 0, 0 );
    
        //at this point we have lines - all straight lines in image
        MergeRelatedLines(&lines,canny_output);
    
        for(int i=0; i< lines.size(); i++)
        {
            if(lines[i][1] != -100)
            {
                if((lines[i][1] >= 0 && lines[i][1] < 1 )|| lines[i][1] >= 3)//Vertical
                {
                    verticalLines.push_back(lines[i]);
                }
                else // horizontal;
                {
                    horizontalLines.push_back(lines[i]);
                }
            }
        }
    
    
    
        sort(verticalLines.begin(),verticalLines.end(),[](const Vec2f& elem1, const Vec2f& elem2){ return elem1[0]*cos(elem1[1]) < elem2[0]*cos(elem2[1]); });
        sort(horizontalLines.begin(),horizontalLines.end(),[](const Vec2f& elem1, const Vec2f& elem2){ return elem1[0] < elem2[0]; });
    
        int numVerticalLines = verticalLines.size();
        int numHorizontalLines = horizontalLines.size();
    
    
        boarderLines.push_back(verticalLines[0]);
        boarderLines.push_back(verticalLines[verticalLines.size()-1]);
    
        boarderLines.push_back(horizontalLines[0]);
        boarderLines.push_back(horizontalLines[horizontalLines.size() -1 ]);
    
    void MergeRelatedLines(vector<Vec2f> *lines, Mat &img)
    {
        vector<Vec2f>::iterator current;
        vector<Vec4i> points(lines->size());
    
        for(current=lines->begin();current!=lines->end();current++)
        {
    
            if((*current)[0]==0 && (*current)[1]==-100)
                continue;
    
            float p1 = (*current)[0];
            float theta1 = (*current)[1];
    
            Point pt1current, pt2current;
            if(theta1>CV_PI*45/180 && theta1<CV_PI*135/180)
            {
                pt1current.x=0;
                pt1current.y = p1/sin(theta1);
    
                pt2current.x=img.size().width;
                pt2current.y=-pt2current.x/tan(theta1) + p1/sin(theta1);
            }
            else
            {
                pt1current.y=0;
                pt1current.x=p1/cos(theta1);
    
                pt2current.y=img.size().height;
                pt2current.x=-pt2current.y/tan(theta1) + p1/cos(theta1);
            }
    
            vector<Vec2f>::iterator pos;
    
            for(pos=lines->begin();pos!=lines->end();pos++)
            {
                if(*current==*pos)
                    continue;
    
                if(fabs((*pos)[0]-(*current)[0])<20 && fabs((*pos)[1]-(*current)[1])<CV_PI*10/180)
                {
                    float p = (*pos)[0];
                    float theta = (*pos)[1];
    
                    Point pt1, pt2;
                    if((*pos)[1]>CV_PI*45/180 && (*pos)[1]<CV_PI*135/180)
                    {
                        pt1.x=0;
                        pt1.y = p/sin(theta);
    
                        pt2.x=img.size().width;
                        pt2.y=-pt2.x/tan(theta) + p/sin(theta);
                    }
    
                    else
                    {
                        pt1.y=0;
                        pt1.x=p/cos(theta);
    
                        pt2.y=img.size().height;
                        pt2.x=-pt2.y/tan(theta) + p/cos(theta);
                    }
    
                    if(((double)(pt1.x-pt1current.x)*(pt1.x-pt1current.x) 
                        + (pt1.y-pt1current.y)*(pt1.y-pt1current.y)<64*64) 
                        && ((double)(pt2.x-pt2current.x)*(pt2.x-pt2current.x) + (pt2.y-pt2current.y)*(pt2.y-pt2current.y)<64*64))
                    {
                        printf("Merging\n");
                        // Merge the two
                        (*current)[0] = ((*current)[0]+(*pos)[0])/2;
                        (*current)[1] = ((*current)[1]+(*pos)[1])/2;
    
                        (*pos)[0]=0;
                        (*pos)[1]=-100;
                    }
                }
            }
        }
    }
    

    示例图片:

    good image

    bad image

    对于坏图像 - 此代码有效,但当然我需要更通用的东西......

    boarderLines.push_back(verticalLines[1]);
                boarderLines.push_back(verticalLines[verticalLines.size()-3]);
    
                boarderLines.push_back(horizontalLines[1]);
                boarderLines.push_back(horizontalLines[horizontalLines.size() -2 ]);
    

    提前感谢您的帮助!

0 个答案:

没有答案