二维坐标点位排序
背景:
对vector中乱序的坐标进行排序
目的:
对坐标进行排序,先横向,再纵向,
编译器:
VS2012 + Win32
步骤:
使用vector来装数据,个人习惯
1、首先导入vector
#include <vector>
using namespace std;
2、创建排序函数
//对y方向上的点位进行排序
bool SetSortRule(const Point p1,const Point p2)
{
if(p1.x < p2.x)
return true;
else
return false;
}
//对x方向上的点位进行排序
bool SetSortRule1(const vector<Point> p1,const vector<Point> p2)
{
if(p1.at(0).y < p2.at(0).y)
return true;
else
return false;
}
3、逻辑部分
vector<Point> posP;
posP.push_back(Point(4,2));
posP.push_back(Point(3,2));
posP.push_back(Point(2,2));
posP.push_back(Point(1,2));
posP.push_back(Point(4,1));
posP.push_back(Point(3,1));
posP.push_back(Point(2,1));
posP.push_back(Point(1,1));
posP.push_back(Point(2,4));
posP.push_back(Point(1,4));
posP.push_back(Point(3,3));
posP.push_back(Point(1,3));
posP.push_back(Point(4,3));
posP.push_back(Point(4,4));
posP.push_back(Point(3,4));
posP.push_back(Point(2,3));
我这边是手动push数据,也可以用for循环push
vector<vector<Point>> point_all;
vector<Point> point_row;
point_all.clear();
point_row.clear();
int IErr = 0; //同一行y坐标允许的误差值
for(unsigned int i = 0; i < posP.size();i++)
{
for(unsigned int j =i+1;j<posP.size();j++)
{
if(abs( posP.at(i).y - posP.at(j).y)<= IErr )
{
point_row.push_back(posP.at(j));
posP.erase(posP.begin()+j);
j--;
}
}
point_row.push_back(posP.at(i));//最后将比较的点放入Vector
cout << "size:" << point_row.size() << endl;
sort(point_row.begin(),point_row.end(),SetSortRule);//对同一行的点位进行排序
for(unsigned int k=0; k < point_row.size();k++)
cout << point_row.at(k)<< endl;
//将同一行的点位放入vector
point_all.push_back(point_row);
point_row.clear(); //清空,准备下一次排序
}
由于图像中同一行 实际的像素坐标在Y方向上存在一些误差,所以在误差范围内都认为是同一行。
即满足 abs(posP.at(i).y - posP.at(j).y) <=iErr 这个条件的坐标,都认为是同一行。
每次找到对应的坐标,都将坐标丢进 point_row,并将次坐标从posP中剔除,直到第二个for循环遍历完成,
然后将被比较的坐标丢进point_row,这样代表这一行Y方向相近的坐标,都被获取。
接下来对point_row这一行的坐标进行排序。
然后将排序后点vector丢进point_all中,将point_row清空准备下一次排序
对point_all进行排序
cout << "before:" << endl;
for(unsigned int i=0; i < point_all.size();i++)
{
for(unsigned int j=0; j < point_all.at(i).size();j++)
{
cout << point_all.at(i).at(j)<<endl;
}
}
cout << "after:" << endl;
sort(point_all.begin(),point_all.end(),SetSortRule1);
for(unsigned int i=0; i < point_all.size();i++)
{
for(unsigned int j=0; j < point_all.at(i).size();j++)
{
cout << point_all.at(i).at(j)<<endl;
}
}
system("pause");
return 0;
}
4、结果
posP 中初始坐标顺序
对每一行的坐标进行X方向上的排序
对每一行的坐标进行Y方向上的排序。
如有问题,请指示出来,我会及时改正,谢谢。
附:Mat图实际测试效果:
排序之前:
排序之后:
Code:
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <Windows.h>
#include <opencv2\opencv.hpp>
#include <highgui.hpp>
#include <imgproc.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;
//对y方向上的点位进行排序
bool SetSortRule(const Point p1,const Point p2)
{
if(p1.x < p2.x)
return true;
else
return false;
}
//对x方向上的点位进行排序
bool SetSortRule1(const vector<Point> p1,const vector<Point> p2)
{
if(p1.at(0).y < p2.at(0).y)
return true;
else
return false;
}
int _tmain(int argc, _TCHAR* argv[])
{
Mat mSrc,mGray,mThresh,mDst,mDst2;
mSrc= imread("Test.jpg",-1);
if(mSrc.channels() ==3)
cvtColor(mSrc,mGray,CV_BGR2GRAY);
else
mGray = mSrc.clone();
mDst = mSrc.clone();
if(mDst.channels() ==1)
cvtColor(mDst,mDst,CV_GRAY2BGR);
mDst2 = mDst.clone();
threshold(mGray,mThresh,50,255,THRESH_BINARY);
vector<Point> posP;
vector<vector<Point> > contours;
findContours(mThresh.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
cout << contours.size() << endl;
for(unsigned int i =0;i< contours.size();i++)
{
Rect R =boundingRect(contours[i]);
if(R.width * R.height > 50)
{
Point p;
p.x = R.x;
p.y = R.y;
posP.push_back(p);
char text[20];
sprintf_s(text,"%d",i);
putText(mDst,text,p,cv::FONT_HERSHEY_SIMPLEX,1,cv::Scalar(0, 0, 255), 2, 8, 0);
}
}
imwrite("mDst1.jpg",mDst);
cout<< posP.size() << endl;
//输出
for(unsigned int i=0; i< posP.size();i++)
{
cout <<"posP:" <<posP.at(i) << endl;
}
vector<vector<Point>> point_all;
vector<Point> point_row;
point_all.clear();
point_row.clear();
int IErr = 50; //同一行y坐标允许的误差值
for(unsigned int i = 0; i < posP.size();i++)
{
for(unsigned int j =i+1;j<posP.size();j++)
{
if(abs( posP.at(i).y - posP.at(j).y)<= IErr )
{
point_row.push_back(posP.at(j));
posP.erase(posP.begin()+j);
j--;
}
}
point_row.push_back(posP.at(i));//最后将比较的点放入Vector
cout << "size:" << point_row.size() << endl;
sort(point_row.begin(),point_row.end(),SetSortRule);//对同一行的点位进行排序
for(unsigned int k=0; k < point_row.size();k++)
cout << point_row.at(k)<< endl;
//将同一行的点位放入vector
point_all.push_back(point_row);
point_row.clear(); //清空,准备下一次排序
}
cout << "before:" << endl;
for(unsigned int i=0; i < point_all.size();i++)
{
for(unsigned int j=0; j < point_all.at(i).size();j++)
{
cout << point_all.at(i).at(j)<<endl;
}
}
cout << "after:" << endl;
sort(point_all.begin(),point_all.end(),SetSortRule1);
for(unsigned int i=0; i < point_all.size();i++)
{
for(unsigned int j=0; j < point_all.at(i).size();j++)
{
cout << point_all.at(i).at(j)<<endl;
char text[20];
sprintf_s(text,"%d",(i*(point_all.at(i).size())+j));
putText(mDst2,text,point_all.at(i).at(j),cv::FONT_HERSHEY_SIMPLEX,1,cv::Scalar(0, 0, 255), 2, 8, 0);
}
}
imwrite("Dst2.jpg",mDst2);
waitKey();
system("pause");
return 0;
}