目的:把图像中断断序序的点连成一条连续的曲线
对于点(x,y) 如果k近邻内有亮点就生成一条路线联通过去
//曲线k延伸,如果最近k距离点有亮点,就延伸过去
Mat cursegrow(Mat& MatIn,int growstartx,int growstarty ,int kernel,int iGrowJudge)
{
Mat Matnow=MatIn.clone();//(MatIn.size(),CV_8UC1,Scalar(0));
vector<Point> seeds;
seeds.push_back(Point(growstartx,growstarty));
Point curgrow;
while(!seeds.empty()){
curgrow=seeds.back();
seeds.pop_back();
Matnow.at<uchar>(curgrow.x,curgrow.y)=255;
/*if(neighbourpoints(MatIn,curgrow.x,curgrow.y,kernel)>=kernel*2+1){
continue;
}*/
vector<Point> brightptsforign;
for(int i=0-kernel-1;i<=kernel+1;i++){
for(int j=0-kernel-1;j<=kernel+1;j+=(kernel+1)*2){
int iCurPosX=i+curgrow.x;
int iCurPosY=curgrow.y+j;
if(iCurPosX<0 ||iCurPosX>(MatIn.rows-1)|| iCurPosY<0 || iCurPosY>(MatIn.cols-1)) continue;
if(Matnow.at<uchar>(iCurPosX,iCurPosY)==255)
brightptsforign.push_back(Point(iCurPosX,iCurPosY));
}
}
for(int i=-kernel-1;i<=kernel+1;i+=(kernel+1)*2){
for(int j= -kernel;j<=kernel;j++){
int iCurPosX=i+curgrow.x;
int iCurPosY=curgrow.y+j;
if(iCurPosX<0 ||iCurPosX>(MatIn.rows-1)|| iCurPosY<0 || iCurPosY>(MatIn.cols-1)) continue;
if(Matnow.at<uchar>(iCurPosX,iCurPosY)==255)
brightptsforign.push_back(Point(iCurPosX,iCurPosY));
}
}
for(int i=0;i<brightptsforign.size();i++)
{
if(!isConnectedBetween2Points(Matnow,brightptsforign[i].x,brightptsforign[i].y,curgrow.x,curgrow.y))
{
Matnow.at<uchar>(brightptsforign[i].x,brightptsforign[i].y)=255;
vector<Point> goodpath;
selectshortpath(goodpath,curgrow.x,curgrow.y,brightptsforign[i].x,brightptsforign[i].y);
for(int i=0;i<goodpath.size();i++){
Matnow.at<uchar>(goodpath[i].x,goodpath[i].y)=255;
}
seeds.push_back(Point(brightptsforign[i].x,brightptsforign[i].y));
//break;
}
}
}
return Matnow;
}
void _selectshortpath( vector<Point>& pts,int x,int y, int x1,int y1)
{
//minx,miny------>minx,maxy---->maxx,maxy
if(isnibpt(Point(x,y),Point(x1,y1))){
pts.push_back(Point(x,y));
pts.push_back(Point(x1,y1));
return;
}
for(int i =x;(x<x1)?(i<=x1):(i>=x1);(x<x1)?(i++):(i--)){
pts.push_back(Point(i,y));
}
for(int i =y;(y<y1)?(i<=y1):(i>=y1);(y<y1)?(i++):(i--)){
pts.push_back(Point(x1,i));
}
}
void selectshortpath(Mat& MatIn,vector<Point>& pts,int x,int y, int x1,int y1)
{
//minx,miny------>minx,maxy---->maxx,maxy
vector<Point>ptshighlight;
neighbourpointsInRect2(MatIn,x,y,x1,y1,ptshighlight);
for(int i=0;i<ptshighlight.size()-1;i++){
_selectshortpath(pts,ptshighlight[i].x,ptshighlight[i].y,ptshighlight[i+1].x,ptshighlight[i+1].y);
}
}
int isConnectedBetween2Points(Mat &MatIn,int x,int y,int x1,int y1)
{
if(x==x1||y==y1){
for(int i=x;x<x1?i<=x1:i>=x1;x<x1?i++:i--){
for(int j=y;y<y1?j<=y1:j>=y1;y<y1?j++:j--){
if(MatIn.at<uchar>(i,j)!=255)return 0;
}
}
return 1;
}
int minx,miny;
int maxx,maxy;
minx=min(x,x1);
miny=min(y,y1);
maxx=max(x,x1);
maxy=max(y,y1);
Rect rc(miny,minx,maxy-miny+1,maxx-minx+1);
//PrintMat2(MatIn,minx,miny,maxx-minx+1,maxy-miny+1);
Mat subMat=MatIn(rc);
//PrintMat(subMat);
vector<vector<Point>> ptsclosed;
findlines( subMat.clone(), ptsclosed,2);
//AfxMessageBox("");exit(0);
if(ptInptvv(ptsclosed,x-minx,y-miny)&&ptInptvv(ptsclosed,x1-minx,y1-miny))
{
return 1;
}
return 0;
}
int ptInptv(vector<Point>&ptv,int x,int y)
{
if(ptv.size()==0)return 0;
for(int i=0;i<ptv.size();i++){
if(ptv[i].x==x&&ptv[i].y==y)return 1;
}
return 0;
}
int ptInptvv(vector<vector<Point>>&ptvv,int x,int y)
{
if(ptvv.size()==0)return 0;
for(int i=0;i<ptvv.size();i++){
if(ptInptv(ptvv[i],x,y))return 1;
}
return 0;
}
void findlines(Mat& MatIn, vector<vector<Point>>& ptsclosed,int minpts)
{
for(int i=0;i<MatIn.rows;i++)
{
for(int j=0;j<MatIn.cols;j++)
{
if(MatIn.at<uchar>(i,j)==255 )
{
vector<Point> pts;
findline(MatIn,i,j,pts);
if(pts.size()>=minpts)
{
ptsclosed.push_back(pts);
}
}
}
}
}
void findline(Mat& MatIn,int growstartx,int growstarty ,vector<Point>& ptsclosed)//iGrowPoint为种子点的判断条件,iGrowJudge为生长条件
{
//初始化原始种子点
int DIR[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
//int iJudge=countNonZero(MatTemp);
vector<Point> seeds;
seeds.push_back(Point(growstartx,growstarty));
Point curgrow;
//ptsclosed.clear();
ptsclosed.push_back(Point(growstartx,growstarty));
MatIn.at<uchar>(growstartx,growstarty)=0;
while(!seeds.empty())
{
curgrow=seeds.back();
seeds.pop_back();
int i=curgrow.x;
int j=curgrow.y; ;
for(int iNum=0;iNum<8;iNum++)
{
int iCurPosX=i+DIR[iNum][0];
int iCurPosY=j+DIR[iNum][1];
if(iCurPosX>=0 && iCurPosX<=(MatIn.rows-1) && iCurPosY>=0 && iCurPosY<=(MatIn.cols-1))
{
if(MatIn.at<uchar>(iCurPosX,iCurPosY)==255 )//生长条件,自己调整
{
seeds.push_back(Point(iCurPosX,iCurPosY));
ptsclosed.push_back(Point(iCurPosX,iCurPosY));
MatIn.at<uchar>(iCurPosX,iCurPosY)=0;
//break;
}
}
}
}
}
测试代码
Mat mat = Mat ::zeros(Size(500,500),CV_8U);
for(int i=100;i<=400;i+=10)
{
mat.at<uchar>(i,100)=255;
}
for(int i=100;i<=400;i+=10)
{
mat.at<uchar>(400,i)=255;
}
for(int i=100;i<=400;i+=10)
{
mat.at<uchar>(100,i)=255;
}
for(int i=100;i<=400;i+=10)
{
mat.at<uchar>(i,400)=255;
}
for(int i=100;i<=400;i+=10)
{
mat.at<uchar>(i,i)=255;
}
for(int i=100;i<=400;i+=10)
{
mat.at<uchar>(i,500-i)=255;
}
for(int i=100;i<=400;i+=10)
{
mat.at<uchar>(200,i)=255;
}
for(int i=100;i<=400;i+=10)
{
mat.at<uchar>(i,200)=255;
}
for(int i=100;i<=400;i+=10)
{
mat.at<uchar>(300,i)=255;
}
for(int i=100;i<=400;i+=10)
{
mat.at<uchar>(i,300)=255;
}
Mat m4=cursegrow(mat,100,100,9,0);
imshow("b",m4);
imshow("a",mat);
结果
右边是生长前的,左边是生长后的
后续可以把这个算法和sobel算法结合起来用于字符分割