opencv曲线生长

目的:把图像中断断序序的点连成一条连续的曲线

对于点(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算法结合起来用于字符分割


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值