Non-zero-point clustering, zero-point Clustering
In a binary image, clustering is performed between non-zero points. When a rectangle frame is used to mark its region, overlapping areas and nesting between adjacent rectangular frames are mainly solved. For reference only. (Note: Because the development cycle is only a few hours, please forgive me for code irregularities ).
CvRectOject header file
/***** File: cvRectObject. h. * Author: Gavin Liu * Date: 2014-03-20 * Version: v1.0.0.0 */# ifndef _ blank _ # define pai_max_area 200 # define _ NV_INFO_OBJRECT _ # define limit 0 # define limit 1 struct RectObject {// The rectangle frame structure int nx; // The X axis int ny of the coordinate point in the upper left corner; // the Y axis int nWidth of the coordinate point in the upper left corner; // The int nHeight of the width of the rectangular box; // The height of the Rectangular Box int nReserved [8]; // reserved}; typedef std: vector <RectObject> VRectObj; typedef std: vector <Point> VPointObj; void partition (const IplImage * pImg, VRectObj & vecRectRoi, VRectObj & vecRectResult, int flags); void cvObjectRectCluster (VRectObj & vecRect, VRectObj & vecRectResult); # endif // _ CVRECTOBJECT_H _
CvRectOject. cpp File
#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(...).\n");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]);}}}
For more information about Image Engineering & Computer Vision, please stay tuned to this blog and Sina Weibo songzi_tea.
What is the difference between clustering and classification analysis?
Generally, several labeled modes (pre-classified) are provided for supervised classification. The problem to be solved is to mark a new but unlabeled mode. In typical cases, a given unlabeled pattern is first used for learning (training), and then used to mark a new pattern. Clustering needs to solve the problem of clustering by clustering the given unlabeled mode to make it meaningful. In a sense, tags are also related to clustering, but these types of tags are data-driven, that is, they are only obtained from the data. Clustering is different from classification in Data Mining. In the classification module, you know which classes exist in the target database. What you need to do is to mark the categories of each record: similar to this, but different, clustering aims to make all records into different classes or "clusters" without knowing in advance how many classes the target database has ", in this case, the similarity based on a certain metric is minimized between the same cluster, while the similarity between different clusters is maximized. In fact, the similarity of many clustering algorithms is based on distance, and due to the diversity of Data Types in the real database, there are many discussions about how to measure the distance between two records containing non-numeric fields, and corresponding algorithms are proposed. In many applications, members of each class obtained by cluster analysis can be viewed in a unified manner.
For Cluster Analysis
1. Features of cluster analysis
Cluster analysis is a way to study individual things based on their own characteristics. It aims to classify similar things. The principle is that the individual in the same class has a large degree of similarity, and the individual in different classes is very different. This method has three features: Applicable to classification without prior knowledge. Without such prior experience or some international, domestic, and industrial standards, classification would be casual and subjective. In this case, you only need to set comprehensive classification variables, and then you can use the clustering analysis method to obtain a more scientific and reasonable category. You can process the classification determined by multiple variables. For example, it is easier to classify the data based on the quantity purchased by the consumer, it is usually complicated to classify consumers based on the purchase volume, household income, household expenditure, age, and other indicators, and cluster analysis can solve such problems. Cluster analysis is an exploratory analysis method, it is a common technology in data mining to analyze the inherent characteristics and rules of things and group things based on the similarity principle.
If this mature statistical method is used properly in market analysis, it will certainly improve the marketing effect and provide a useful reference for enterprise decision-making. The application process is to convert problems in market analysis into problems that can be solved by cluster analysis, and use relevant software (such as SPSS, SAS, etc.) to obtain results. The results are interpreted by experts, and convert to actual operation measures to increase enterprise profits and reduce enterprise costs.
2. Application Scope
Application of cluster analysis in Customer Segmentation
Different customers have different consumption characteristics when consuming the same type of products or services. By studying these characteristics, enterprises can develop different marketing combinations to obtain the largest consumer surplus, this is the main purpose of customer segmentation. There are three common customer classification methods: the empirical description method, which is used by decision makers to classify customers based on experience. The traditional statistical method is used to classify customers based on simple statistics of customer attribute characteristics; non-traditional statistical methods, that is, non-numerical methods based on artificial intelligence technology. The clustering analysis method combines the characteristics of the last two methods to effectively complete the customer segmentation process.
For example, a customer's purchase motivation is generally determined by factors such as needs, cognition, learning, and other factors such as culture, society, family, small groups, and reference groups. When dividing customers based on different purchase motives, you can use the aforementioned factors as analysis variables, quantify the index values of each analysis variable of all target customers, and then use Clustering Analysis for classification. If you encounter some qualitative index values during indicator value quantification, you can use some qualitative data quantification methods, such as fuzzy evaluation. In addition, the customer satisfaction level and the size of repeated purchase opportunities can be categorized as attributes. A new category can also be incorporated to differentiate differences between customers, the customer's differential variables are divided into five categories: Product Benefits, interactions between customers, selection barriers, bargaining power, and return rates. These analysis variables are grouped by clustering, it can provide a useful reference for enterprises to make marketing decisions.
All of the above analyses are classified based on multiple variables, which exactly meets the characteristics of cluster analysis to solve the problem. The difference lies in finding and analyzing variables from different perspectives, it provides a reference for decision-making in a certain aspect, which is a reflection of the wide application scope of cluster analysis in customer segmentation issues.
Application of cluster analysis in experiment Market Selection
The experimental survey method is an effective method for collecting first-hand data in market research. It is mainly used for marketing experiments, that is, the so-called market testing. Through small-scale experimental changes, we can observe the customer's response to products or services, so as to analyze whether the changes are worth promoting in a wide range.
The most common areas of experimental survey are market saturation testing. Market saturation reflects the potential purchasing power of the market and is an important reference indicator for marketing strategy and policy decision-making. Enterprises usually test the market saturation by minimizing the various deciding factors (such as prices) of products or services purchased by consumers. In case of unsalable transactions, enterprises may launch similar new products or services to a specific market to test whether the market is saturated and whether it has potential purchasing power. The above two measures cannot be implemented in all the markets covered by the enterprise due to the interests and risks. They can only select an appropriate experimental market and compare the market for testing to obtain a similar market saturation; product ...... remaining full text>