非零点之间聚类

在二值图像中,非零点之间的进行聚类,使用矩形框进行标记其区域过程中,主要解决相邻的两个矩形框之间重叠区域和嵌套现象。仅作參考.(注:因开发周期仅仅有几个小时的时间.代码有不规范地方,请各位见谅).

cvRectOject头文件

/**
 *
 * File  	: cvRectObject.h.
 * Author 	: Gavin Liu
 * Date 	: 2014-03-20
 * Version	: V1.0.0.0
 */


#ifndef _CVRECTOBJECT_H_
#define _CVRECTOBJECT_H_

#define CONTOUR_MAX_AREA 200
#define _NV_INFO_OBJRECT_

#define  CV_ALGRITHM_MORPHOLOGY  0 
#define  CV_ALGRITHM_FOOLFILL    1 


struct RectObject{			//矩形框结构
	int nx;					//左上角坐标点的X轴
	int ny;					//左上角坐标点的Y轴
	int nWidth;				//矩形框的宽度
	int nHeight;			//矩形框的高度
	int nReserved[8];		//保留
};


typedef std::vector<RectObject> VRectObj;
typedef std::vector<Point> VPointObj;

void cvObjectRectMorphology(const IplImage  *pImg, 
							VRectObj  &vecRectRoi, 
							VRectObj  &vecRectResult,
							int flags);
void cvObjectRectCluster(VRectObj &vecRect,
					     VRectObj &vecRectResult);

#endif //_CVRECTOBJECT_H_

cvRectOject.cpp文件

#include "cvRectObject.h"

inline int cvDataMax (int V1,int V2,int V3, int V4){
	int temp1 = V1>V2?V1:V2;
	int temp2 = V3>V4?V3:V4;
	return(temp1>temp2?temp1:temp2);
}

inline int cvDataMin (int V1,int V2,int V3, int V4){
	int temp1 = V1< V2 ? V1:V2;
	int temp2 = V3< V4 ? V3:V4;
	return(temp1< temp2 ? temp1 : temp2);
}


void cvMergeRect(VRectObj &srcVRectObj,bool flags){
	VRectObj::size_type ix,iy;
	CvPoint pt1,pt2,pt3,pt4;
	CvPoint Tpt1,Tpt2,CTpt1,CTpt2;

	for( ix =0; ix < srcVRectObj.size();ix++){
		if((srcVRectObj[ix].nx !=0)&&(srcVRectObj[ix].ny !=0)&&(srcVRectObj[ix].nHeight !=0)&&(srcVRectObj[ix].nWidth !=0)){
			pt1.x = srcVRectObj[ix].nx;
			pt1.y = srcVRectObj[ix].ny;
			pt2.x = srcVRectObj[ix].nx +srcVRectObj[ix].nWidth;
			pt2.y = srcVRectObj[ix].ny +srcVRectObj[ix].nHeight;
			
			for(iy =0; iy <srcVRectObj.size()&&(iy !=ix); iy++){
				if((srcVRectObj[iy].nx !=0)&&(srcVRectObj[iy].ny !=0)&&(srcVRectObj[iy].nWidth !=0)&&(srcVRectObj[iy].nHeight !=0)){
					pt3.x = srcVRectObj[iy].nx;
					pt3.y = srcVRectObj[iy].ny;
					pt4.x = srcVRectObj[iy].nx +srcVRectObj[iy].nWidth;
					pt4.y = srcVRectObj[iy].ny +srcVRectObj[iy].nHeight;
					
					if(((pt1.x<=pt3.x)&&(pt4.x<=pt2.x)&&(pt1.y<=pt3.y)&&(pt4.y<=pt2.y))||
						((pt1.x>=pt3.x)&&(pt4.x>=pt2.x)&&(pt1.y>=pt3.y)&&(pt4.y>=pt2.y))){
							if((srcVRectObj[ix].nWidth >srcVRectObj[iy].nWidth)&&(srcVRectObj[ix].nHeight >srcVRectObj[iy].nHeight)){
								srcVRectObj[iy].nx =0;
								srcVRectObj[iy].ny =0;
								srcVRectObj[iy].nWidth =0;
								srcVRectObj[iy].nHeight =0;
							}
							else{
								srcVRectObj[ix].nx =0;
								srcVRectObj[ix].ny =0;
								srcVRectObj[ix].nWidth =0;
								srcVRectObj[ix].nHeight =0;
							}
					}
					
					if(((pt4.x>=pt1.x)&&(pt4.x <=pt2.x))&&(((pt1.y<=pt4.y)&&(pt2.y >= pt4.y))||((pt1.y<=pt3.y)&&(pt2.y>=pt3.y)))||
						(((pt3.x>=pt1.x)&&(pt3.x <=pt2.x))&&(((pt1.y<=pt3.y)&&(pt2.y>=pt3.y))||((pt1.y <=pt4.y)&&(pt2.y>=pt4.y))))){
							Tpt1.x = cvDataMin(pt1.x,pt2.x,pt3.x,pt4.x);
							Tpt1.y = cvDataMin(pt1.y,pt2.y,pt3.y,pt4.y);
							Tpt2.x = cvDataMax(pt1.x,pt2.x,pt3.x,pt4.x);
							Tpt2.y = cvDataMax(pt1.y,pt2.y,pt3.y,pt4.y);
					
							if(ix < iy){
								srcVRectObj[ix].nx =Tpt1.x;
								srcVRectObj[ix].ny =Tpt1.y;
								srcVRectObj[ix].nWidth = abs(Tpt2.x - Tpt1.x);
								srcVRectObj[ix].nHeight = abs(Tpt2.y -Tpt1.y);
										
								srcVRectObj[iy].nx =0;
								srcVRectObj[iy].ny =0;
								srcVRectObj[iy].nWidth =0;
								srcVRectObj[iy].nHeight =0;
							}
							
							else if(ix> iy){
								srcVRectObj[iy].nx =Tpt1.x;
								srcVRectObj[iy].ny =Tpt1.y;
								srcVRectObj[iy].nWidth = abs(Tpt2.x - Tpt1.x);
								srcVRectObj[iy].nHeight = abs(Tpt2.y -Tpt1.y);
								
								srcVRectObj[ix].nx =0;
								srcVRectObj[ix].ny =0;
								srcVRectObj[ix].nWidth =0;
								srcVRectObj[ix].nHeight =0;
							}
					}
					
					CTpt1.x = srcVRectObj[ix].nx +int(0.5*(srcVRectObj[ix].nWidth));
					CTpt1.y = srcVRectObj[ix].ny +int(0.5*(srcVRectObj[ix].nHeight));
					CTpt2.x = srcVRectObj[iy].nx +int(0.5*(srcVRectObj[iy].nWidth));
					CTpt2.y = srcVRectObj[iy].ny +int(0.5*(srcVRectObj[iy].nHeight));
					
					double Xdist = abs(CTpt1.x -CTpt2.x);
					double Ydist = abs(CTpt1.y -CTpt2.y);				
					double Dist  = sqrt(Xdist*Xdist +Ydist*Ydist);
					double ThrVal= cvDataMax(srcVRectObj[ix].nHeight,srcVRectObj[ix].nWidth,srcVRectObj[iy].nHeight,srcVRectObj[iy].nWidth);

					if(Dist <= ThrVal){
						Tpt1.x = cvDataMin(pt1.x,pt2.x,pt3.x,pt4.x);
						Tpt1.y = cvDataMin(pt1.y,pt2.y,pt3.y,pt4.y);
						Tpt2.x = cvDataMax(pt1.x,pt2.x,pt3.x,pt4.x);
						Tpt2.y = cvDataMax(pt1.y,pt2.y,pt3.y,pt4.y);
						
						if(ix<iy){
							srcVRectObj[ix].nx =Tpt1.x;
							srcVRectObj[ix].ny =Tpt1.y;
							srcVRectObj[ix].nWidth = abs(Tpt2.x - Tpt1.x);
							srcVRectObj[ix].nHeight = abs(Tpt2.y -Tpt1.y);
											
							srcVRectObj[iy].nx =0;
							srcVRectObj[iy].ny =0;
							srcVRectObj[iy].nWidth =0;
							srcVRectObj[iy].nHeight =0;
						}
						if(ix>iy){
							srcVRectObj[iy].nx =Tpt1.x;
							srcVRectObj[iy].ny =Tpt1.y;
							srcVRectObj[iy].nWidth = abs(Tpt2.x - Tpt1.x);
							srcVRectObj[iy].nHeight = abs(Tpt2.y -Tpt1.y);
											
							srcVRectObj[ix].nx =0;
							srcVRectObj[ix].ny =0;
							srcVRectObj[ix].nWidth =0;
							srcVRectObj[ix].nHeight =0;
						}
					}
				} //end of iy_if
			}//	end of iy_for
		}	// end of ix_if
	}	//end of ix_for
}

void cvObjectRectMorphology( const IplImage *pImg,VRectObj &vecRectRoi, VRectObj &vecRectResult,int flags){
	IplImage * pImgtemp  = NULL;
	IplImage * pBinaryImg = NULL;

	if(!pImg){
		printf("Could not load File in the cvLoadImage(...).
");
		exit(EXIT_FAILURE);
	}

	pImgtemp = cvCreateImage(cvGetSize(pImg),IPL_DEPTH_8U,1);
	if(pImg->nChannels ==1){
		pImgtemp = cvCloneImage(pImg);
	}
	if(pImg->nChannels ==3){
		cvCvtColor(pImg,pImgtemp,CV_RGB2GRAY);
	}

	pBinaryImg = cvCloneImage(pImgtemp);

	if( flags == CV_ALGRITHM_FOOLFILL){
		CvPoint beginPoint;
		for(int i =0; i<pImgtemp->height; i++){
			for(int j =0; j<pImgtemp->width; j++){
				CvScalar cs = cvGet2D(pImgtemp,i,j);
				if(cs.val[0] !=0){
					beginPoint.x = j;
					beginPoint.y = i;
				}
			}
		}
		
		IplImage *pMask = cvCreateImage(cvSize(pImgtemp->width +2 ,pImgtemp->height +2),8,1);
		cvSetZero(pMask);
		cvSmooth(pImgtemp,pImgtemp,CV_GAUSSIAN,3,0,0,0);

		cvFloodFill(pImgtemp,beginPoint,CV_RGB(255,0,0),CV_RGB(0,255,0),cvScalarAll(10),NULL,CV_FLOODFILL_FIXED_RANGE,pMask);
	}

	if(flags == CV_ALGRITHM_MORPHOLOGY){
		cvSmooth(pImgtemp,pImgtemp,CV_GAUSSIAN,3,0,0,0);
		cvMorphologyEx(pImgtemp,pImgtemp,NULL,0,CV_MOP_GRADIENT,1);
	}
	
	CvMemStorage *stor = cvCreateMemStorage(0);
	CvSeq* cont =cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);
	cvFindContours(pImgtemp,stor,&cont,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));
	
	
	CvPoint pt1,pt2;
	std::vector<CvRect> vecRect;

	for(;cont!=0;cont=cont->h_next){
		//cvDrawContours(pImgtemp,cont,CV_RGB(255,0,0),CV_RGB(0,255,0),0,2,0);

		CvRect r =((CvContour*)cont)->rect;
		if((r.height*r.width <CONTOUR_MAX_AREA)){
			cvSeqRemove(cont,0);
			continue;
		}
		else{
			pt1 = cvPoint(r.x,r.y);
			pt2 = cvPoint(r.x+r.width,r.y+r.height);
			//cvRectangle(pBinaryImg,pt1,pt2,CV_RGB(0,255,0),2,CV_AA,0);
			vecRect.push_back(r);
			continue;
		}			
	}

	cvReleaseMemStorage(&stor);

	RectObject Objrect;
	VRectObj vecObjtemp;

	for(vector<CvRect>::size_type ix =0; ix < vecRect.size(); ix++){
		Objrect.nx = vecRect[ix].x;
		Objrect.ny = vecRect[ix].y;
		Objrect.nHeight = vecRect[ix].height;
		Objrect.nWidth = vecRect[ix].width;
		vecObjtemp.push_back(Objrect);
	}

	cvObjectRectCluster(vecObjtemp,vecRectResult);

	cvReleaseImage(&pImgtemp);
	cvReleaseImage(&pBinaryImg);
}

void cvObjectRectCluster(VRectObj& vecRect,VRectObj &vecRectResult){

	if(vecRect.empty()){
		std::cerr <<"The Vector of vecRect is empty!"<<std::endl;
		exit(EXIT_FAILURE);
	}

	Point CenPoint;
	VPointObj vecPoint;
	VRectObj::size_type Ci,Cii;
	RectObject rObj;
	
	for( Ci = 0; Ci<vecRect.size(); Ci++){
		for(Cii = Ci+1; Cii<vecRect.size(); Cii++){
			if((vecRect[Ci].nx > vecRect[Cii].nx)||(vecRect[Ci].nx ==vecRect[Ci].nx)&&(vecRect[Ci].ny > vecRect[Cii].ny)){
				rObj.nx = vecRect[Ci].nx;
				rObj.ny = vecRect[Ci].ny;
				rObj.nWidth = vecRect[Ci].nWidth;
				rObj.nHeight = vecRect[Ci].nHeight;

				vecRect[Ci].nx = vecRect[Cii].nx;
				vecRect[Ci].ny = vecRect[Cii].ny;
				vecRect[Ci].nWidth = vecRect[Cii].nWidth;
				vecRect[Ci].nHeight = vecRect[Cii].nHeight;

				vecRect[Cii].nx = rObj.nx;
				vecRect[Cii].ny = rObj.ny;
				vecRect[Cii].nWidth = rObj.nWidth;
				vecRect[Cii].nHeight = rObj.nHeight;
			}
		}
	}

	for(VRectObj::size_type vx = 0; vx<vecRect.size(); vx++){
		CenPoint.x = vecRect[vx].nx + (int)(0.5*vecRect[vx].nWidth);
		CenPoint.y = vecRect[vx].ny + (int)(0.5*vecRect[vx].nHeight);
		vecPoint.push_back(CenPoint);
		std::cout<<"Sort vecRect["<<vx<<"]:("<<vecRect[vx].nx<<","<<vecRect[vx].ny<<",";
		std::cout<<vecRect[vx].nWidth<<","<<vecRect[vx].nHeight<<")";
		std::cout<<"["<<CenPoint.x <<","<<CenPoint.y << "]"<<std::endl;
	}

	double XDistance = 0.0;
	double YDistance = 0.0;
	double CDistance = 0.0;
	

	Point pt1,pt2,pt3,pt4;
	Point Tpt1,Tpt2,Tpt3,Tpt4;

	for(Ci =0; Ci<vecRect.size(); Ci++){
		if((vecRect[Ci].nx !=0)&&(vecRect[Ci].ny !=0)&&(vecRect[Ci].nWidth !=0)&&(vecRect[Ci].nHeight !=0)){
			pt1.x = vecRect[Ci].nx;
			pt1.y = vecRect[Ci].ny;
			pt2.x = vecRect[Ci].nx +vecRect[Ci].nWidth;
			pt2.y = vecRect[Ci].ny +vecRect[Ci].nHeight;
			
			for(Cii = 0;Cii <vecRect.size()&&(Cii !=Ci);Cii++){
				if((vecRect[Cii].nx !=0)&&(vecRect[Cii].ny !=0)&&(vecRect[Cii].nWidth !=0)&&(vecRect[Cii].nHeight !=0)){
					pt3.x = vecRect[Cii].nx;
					pt3.y = vecRect[Cii].ny;
					pt4.x = vecRect[Cii].nx +vecRect[Cii].nWidth;
					pt4.y = vecRect[Cii].ny +vecRect[Cii].nHeight;
					
					if(((pt1.x<=pt3.x)&&(pt4.x<=pt2.x)&&(pt1.y<=pt3.y)&&(pt4.y<=pt2.y))||
						((pt1.x>=pt3.x)&&(pt4.x>=pt2.x)&&(pt1.y>=pt3.y)&&(pt4.y>=pt2.y))){
							if((vecRect[Ci].nWidth >vecRect[Cii].nWidth)&&(vecRect[Ci].nHeight >vecRect[Cii].nHeight)){
								vecRect[Cii].nx =0;
								vecRect[Cii].ny =0;
								vecRect[Cii].nWidth =0;
								vecRect[Cii].nHeight =0;
							}
							if((vecRect[Ci].nWidth< vecRect[Cii].nWidth)&&(vecRect[Ci].nHeight < vecRect[Cii].nHeight)){
								vecRect[Ci].nx =0;
								vecRect[Ci].ny =0;
								vecRect[Ci].nWidth =0;
								vecRect[Ci].nHeight =0;
							}
					}
					
					
					XDistance = abs(vecPoint[Ci].x -vecPoint[Cii].x);
					YDistance = abs(vecPoint[Ci].y -vecPoint[Cii].y);
					CDistance = sqrt(XDistance*XDistance+YDistance*YDistance);
					int ThrVal = cvDataMax(vecRect[Ci].nWidth,vecRect[Ci].nHeight,vecRect[Cii].nWidth,vecRect[Cii].nHeight);
					
					if(CDistance <= ThrVal){
						Tpt1.x = cvDataMin(pt1.x,pt2.x,pt3.x,pt4.x);
						Tpt1.y = cvDataMin(pt1.y,pt2.y,pt3.y,pt4.y);
						Tpt2.x = cvDataMax(pt1.x,pt2.x,pt3.x,pt4.x);
						Tpt2.y = cvDataMax(pt1.y,pt2.y,pt3.y,pt4.y);
						
						if(Ci< Cii){
							vecRect[Ci].nx = Tpt1.x;
							vecRect[Ci].ny = Tpt1.y;
							vecRect[Ci].nWidth = abs(Tpt2.x - Tpt1.x);
							vecRect[Ci].nHeight = abs(Tpt2.y - Tpt1.y);
							
							vecRect[Cii].nx = 0;
							vecRect[Cii].ny = 0;
							vecRect[Cii].nWidth = 0;
							vecRect[Cii].nHeight = 0;

							for(int i =0; i<10; i++){
								cvMergeRect(vecRect,true);
							}
						}
						if(Ci>Cii){
							vecRect[Cii].nx = Tpt1.x;
							vecRect[Cii].ny = Tpt1.y;
							vecRect[Cii].nWidth = abs(Tpt2.x - Tpt1.x);
							vecRect[Cii].nHeight = abs(Tpt2.y - Tpt1.y);
							
							vecRect[Ci].nx = 0;
							vecRect[Ci].ny = 0;
							vecRect[Ci].nWidth = 0;
							vecRect[Ci].nHeight = 0;
							
							for(int i =0; i<10; i++){
								cvMergeRect(vecRect,true);
							}
						}
					}
				}
			}//Cii_for
		}
	}

	for( VRectObj::size_type ix =0; ix< vecRect.size(); ix++){
		if((vecRect[ix].nx !=0)&&(vecRect[ix].ny !=0)&&(vecRect[ix].nWidth !=0)&&(vecRect[ix].nHeight !=0)){
			vecRectResult.push_back(vecRect[ix]);
		}
	}
}


关于Image Engineering& Computer Vision很多其它讨论与交流,敬请关注本博客和新浪微博songzi_tea.


原文地址:https://www.cnblogs.com/mfrbuaa/p/3946152.html