OpenCV:在一个盒子里找到盒子 [英] Opencv: find box within a box

查看:107
本文介绍了OpenCV:在一个盒子里找到盒子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

opencv 2.4和Python 2.7

opencv 2.4 and Python 2.7

我正在处理的图像:

The image I'm working with:

我感兴趣的是隔离形成围绕9条垂直和水平线的框的轮廓.我只是不确定如何去做.我看过各种教程,例如在数独游戏中完成的那些教程,并且只是假设最大的盒子就是您要寻找的盒子(因为数独游戏的盒子中没有盒子,所以要减去实际的网格). .我试过使用findContour函数并按大小过滤轮廓,但是没有运气.我最终得到不一致的结果,有时发现正确的轮廓,而有时发现完全错误的轮廓.谁能指出我正确的方向?谢谢.

What I'm interested in is isolating the outline that forms the box around the 9 vertical and horizontal lines. I'm just not sure on how to go about this. I've looked at various tutorials, such as those done on Sudoku puzzles and those simply assume that the largest box is the one that you're looking for (since a sudoku puzzle doesn't have boxes within boxes, minus the actual grid). I've tried using the findContour function and filtering contours by size but with no luck. I end up with inconsistent results that sometimes finds the right contour but other times finds contours that are completely wrong. Can anyone point me in the right direction? Thanks.

原始图片:

推荐答案

最好放原始图像,但我试图从轮廓图像中解释

It's better to put the original image, but I tried to interpret from your contours images

我执行了以下步骤

  1. 您可能需要去除一些噪音(侵蚀)
  2. 从这些轮廓计算水平和垂直投影
  3. 在图像上绘制投影以能够分析相对于检查表的投影范围.
  4. 请注意,垂直投影(绿色)如何向您指示左右边界,水平(蓝色)也是如此,以指示纸张的底部和顶部.

您只需要使投影平滑并针对确切的轮廓优化搜索.

You just need to smooth the projection and refine your search about the exact outlines.

如果您认为这很有用,我可以共享opencv c ++(不是python)实现的代码

if you think it's useful i can share the code implemented by opencv c++ (not python)

这是我用来进行水平和垂直投影的代码,您可能需要对其进行优化.

This is the code that i used to make horizontal and vertical projections, you may need to optimize it.

 void HVprojection(Mat image)
{
    // find the vertical projection
    Mat smothedRes = image.clone();
    vector<double> v_vl_proj; // holds the column sum values
    double max_vl_proj_h = 0,max_vl_proj_v=0; // holds the maximum value
    double average_v=0;
    for( int i=0;i<image.cols;++i )
    {
        Mat col;
        Scalar col_sum;
        // get individual columns
        col= image.col(i);
        col_sum = sum( col ); // find the sum of ith column
        v_vl_proj.push_back( col_sum.val[0] ); // push back to vector
        if( col_sum.val[0]>max_vl_proj_v )    max_vl_proj_v = col_sum.val[0];
        average_v+= col_sum.val[0];
    }
    average_v = average_v/image.cols;

    // find the horizontal projection
    vector<double> h_vl_proj; // holds the row sum values

    double average_h=0;
    for( int i=0;i<image.rows;++i )
    {
        Mat row;
        Scalar row_sum;
        // get individual columns
        row= image.row(i);
        row_sum = sum(row); // find the sum of ith row
        h_vl_proj.push_back(row_sum.val[0]); // push back to vector
        if( row_sum.val[0]>max_vl_proj_h )    max_vl_proj_h = row_sum.val[0];
        average_h+= row_sum.val[0];
    }
    average_h = average_h/image.rows;


    //******************Plotting vertical projection*******************
    for(int j =1;j<image.cols;j++)
    {
        int y1 = int(image.rows*v_vl_proj[j-1]/max_vl_proj_v);
        int y2 = int(image.rows*v_vl_proj[j]/max_vl_proj_v);
          line(image,Point(j-1,y1),Point(j,y2),Scalar(255,255,255),1,8);
        }
    int average_y = int(image.rows*average_v/max_vl_proj_v);  // zero level
    line(image,Point(0,average_y),Point(image.cols,average_y),Scalar(255,255,255),1,8);




    //***************Plotting horizontal projection**************
    for(int j =1;j<image.rows;j++)
    {
        int x1 = int(0.25*image.cols*h_vl_proj[j-1]/max_vl_proj_h);
        int x2 = int(0.25*image.cols*h_vl_proj[j]/max_vl_proj_h);
          line(image,Point(x1,j-1),Point(x2,j),Scalar(255,0,0),1,8);
        }
    int average_x = int(0.25*image.cols*average_h/max_vl_proj_h);
    line(image,Point(average_x,0),Point(average_x,image.rows),Scalar(255,0,0),1,8);

    imshow("horizontal_projection",image);
    imwrite("h_p.jpg",image);



// if you want to smooth the signal of projection in case of noisu signal
    v_vl_proj = smoothing(v_vl_proj);

    for(int j =1;j<image.cols;j++)
        {
            int y1 = int(image.rows*v_vl_proj[j-1]/max_vl_proj_v);
            int y2 = int(image.rows*v_vl_proj[j]/max_vl_proj_v);
              line(smothedRes,Point(j-1,y1),Point(j,y2),Scalar(0,255,0),1,8);
            }
        int average_y1 = int(smothedRes.rows*average_v/max_vl_proj_v);  // zero level
        line(smothedRes,Point(0,average_y1),Point(smothedRes.cols,average_y1),Scalar(0,255,0),1,8);

        imshow("SMoothed",smothedRes);
        imwrite("Vertical_projection.jpg",smothedRes);
        waitKey(0);
}

要平滑投影信号:

vector<double> smoothing(vector<double> a)
 {
     //How many neighbors to smooth
     int NO_OF_NEIGHBOURS=5;
     vector<double> tmp=a;
     vector<double> res=a;

     for(int i=0;i<a.size();i++)
     {

         if(i+NO_OF_NEIGHBOURS+1<a.size())
         {
             for(int j=1;j<NO_OF_NEIGHBOURS;j++)
             {
                 res.at(i)+=res.at(i+j+1);
             }
             res.at(i)/=NO_OF_NEIGHBOURS;
         }
         else
         {
             for(int j=1;j<NO_OF_NEIGHBOURS;j++)
             {
                 res.at(i)+=tmp.at(i-j);
             }
             res.at(i)/=NO_OF_NEIGHBOURS;

         }


     }
     return res;

 }

这篇关于OpenCV:在一个盒子里找到盒子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆