OpenCV:在一个盒子里找到盒子 [英] Opencv: find box within a box
问题描述
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
我执行了以下步骤
- 您可能需要去除一些噪音(侵蚀)
- 从这些轮廓计算水平和垂直投影
- 在图像上绘制投影以能够分析相对于检查表的投影范围.
- 请注意,垂直投影(绿色)如何向您指示左右边界,水平(蓝色)也是如此,以指示纸张的底部和顶部.
您只需要使投影平滑并针对确切的轮廓优化搜索.
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屋!