我在open cv中做一个项目。 目标是识别棋盘上的2d棋子及其位置。 算法是这样的:
现在我坚持做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;
}
}
}
}
}
示例图片:
对于坏图像 - 此代码有效,但当然我需要更通用的东西......
boarderLines.push_back(verticalLines[1]);
boarderLines.push_back(verticalLines[verticalLines.size()-3]);
boarderLines.push_back(horizontalLines[1]);
boarderLines.push_back(horizontalLines[horizontalLines.size() -2 ]);
提前感谢您的帮助!