cv1.8凸包检测以及形态学滤波

作者 群号 C语言交流中心 240137450  微信 15013593099


形态学滤波

形态滤波进行角点检测

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
#include "morphoFeatures.h"

int main()
{
		
	Mat image = imread("f:/img/adc.jpg",0);
	if(!image.data)
		return -1;
	imshow("源图像",image);
	
	MorphoFeatures morpho;
	morpho.setThreshold(40);

	//获取边沿
	Mat edges;
	edges = morpho.getEdges(image);
	imshow("边沿",edges);

	//获取角点
	morpho.setThreshold(-1);
	Mat corners;
	corners = morpho.getCorners(image);
	morphologyEx(corners,corners,MORPH_TOPHAT,Mat());
	threshold(corners,corners,40,255,THRESH_BINARY_INV);
	//imshow("角点",corners);
	
	//展示图片上的角点
	morpho.drawOnImage(corners,image);
	imshow("图片上的角点",image);
	

	waitKey(0);
	return 0;
}

MorphoFeatures.h


#if ! defined MORPHOF
#define MORPHOF

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;

class MorphoFeatures
{
private:
	//产生二值图像的门限
	int threshold;
	//结构元
	Mat cross;
	Mat diamond;
	Mat square;
	Mat x;
	//对图像二值化
	void applyThreshold(Mat &result)
	{
		if(threshold>0)
			cv::threshold(result,result,threshold,255,THRESH_BINARY_INV);
	}


public:
	//构造函数
	MorphoFeatures():threshold(-1),
					cross(5,5,CV_8U,Scalar(0)),
					diamond(5,5,CV_8U,Scalar(255)),
					square(5,5,CV_8U,Scalar(255)),
					x(5,5,CV_8U,Scalar(0))
	{
		//创建十字型结构元
		for(int i = 0; i < 5; i++)
		{
			cross.at<uchar>(2,i) = 255;
			cross.at<uchar>(i,2) = 255;
		}

		//创建菱形结构元:手动画,只需要把不是菱形的部分变白即可
		diamond.at<uchar>(0,0)= 0;
		diamond.at<uchar>(0,1)= 0;
		diamond.at<uchar>(1,0)= 0;
		diamond.at<uchar>(4,4)= 0;
		diamond.at<uchar>(3,4)= 0;
		diamond.at<uchar>(4,3)= 0;
		diamond.at<uchar>(4,0)= 0;
		diamond.at<uchar>(4,1)= 0;
		diamond.at<uchar>(3,0)= 0;
		diamond.at<uchar>(0,4)= 0;
		diamond.at<uchar>(0,3)= 0;
		diamond.at<uchar>(1,4)= 0;

		//创建X形
		for(int i = 0; i < 5; i++)
		{
			//主对角线
			x.at<uchar>(i,i) = 255;
			//副对角线
			x.at<uchar>(4-i,i) = 255;
		}

	}
	
	//设置门限函数
	void setThreshold(int t)
	{
		threshold = t;
	}

	//获取当前门限
	int getThreshold() const
	{
		return threshold;
	}

	//检测直线函数
	Mat getEdges(const Mat &image)
	{
		Mat result;
		//获取图像的梯度
		morphologyEx(image,result,cv::MORPH_GRADIENT,Mat());
		//结果二值化
		applyThreshold(result);
		return result;
	}

	//检测角点函数
	Mat getCorners(const Mat &image)
	{
		Mat result;
		dilate(image,result,cross);
		erode(result,result,diamond);
		Mat result2;
		dilate(image,result2,x);
		erode(result2,result2,square);
		absdiff(result2,result,result);
		applyThreshold(result);
		return result;
	}

	//在角点处画圆
	void drawOnImage(const Mat &binary,Mat &image)
	{
		Mat_<uchar>::const_iterator it = binary.begin<uchar>();
		Mat_<uchar>::const_iterator itend = binary.end<uchar>();
		for(int i = 0;it != itend;++it,++i)
		{
			if(!*it)
				circle(image,Point(i%image.step,i/image.step),5,Scalar(255,0,0));
		}
	}

};



#endif

角点检测2

#include <stdio.h>
#include <opencv\\cv.h>
#include <opencv\\highgui.h>
#define max_corners 100
int main( int argc, char** argv )
{
    int cornerCount=max_corners;
    CvPoint2D32f corners[max_corners];
    IplImage *srcImage = 0, *grayImage = 0, *corners1 = 0, *corners2 = 0;
    int i;
    CvScalar color = CV_RGB(255,0,0);
    char* filename = "f:\\img\\cornor.png"; // 注意相对路径
    
        cvNamedWindow( "image", 1 ); // create HighGUI window with name "image"
     cvNamedWindow( "src", 1 );
    //Load the image to be processed
    srcImage = cvLoadImage(filename, 1);
	cvShowImage("src",srcImage);
    
    grayImage = cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_8U, 1);
    
    //copy the source image to copy image after converting the format
    cvCvtColor(srcImage, grayImage, CV_BGR2GRAY);
    
    //create empty images of same size as the copied images
    corners1= cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_32F, 1);
    corners2= cvCreateImage(cvGetSize(srcImage),IPL_DEPTH_32F, 1);
    
    cvGoodFeaturesToTrack (grayImage, corners1, 
        corners2, corners,
        &cornerCount, 0.05,
        5, 
        0,
        3, // block size
        0, // not use harris
        0.4 );
    
    printf("num corners found: %d\n", cornerCount);
    
    // draw circles at each corner location in the gray image and
    //print out a list the corners 
    if(cornerCount>0) 
    {
        for (i=0; i<cornerCount; i++) 
        {
            cvCircle(srcImage, cvPoint((int)(corners[i].x), (int)(corners[i].y)), 6,
                color, 2, CV_AA, 0);
        }
    }
    
    cvShowImage( "image", srcImage ); 
    
    cvReleaseImage(&srcImage);
    cvReleaseImage(&grayImage);
    cvReleaseImage(&corners1);
    cvReleaseImage(&corners2);
    
    cvWaitKey(0); // wait for key. The function has
    return 0;
}

凸包

例子1


#include "opencv\\cv.h"
#include "opencv\\highgui.h"
#include <stdlib.h>
#define ARRAY 0 /* switch between array/sequence method by replacing 0<=>1 */
int main( int argc, char** argv )
{
    IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
    cvNamedWindow( "hull", 1 );
#if !ARRAY
        CvMemStorage* storage = cvCreateMemStorage();
#endif
    for(;;)
    {
        int i, count = rand()%100 + 1, hullcount;
        CvPoint pt0;
#if !ARRAY
        CvSeq* ptseq = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour),
                                     sizeof(CvPoint), storage );
        CvSeq* hull;
        for( i = 0; i < count; i++ )
        {
            pt0.x = rand() % (img->width/2) + img->width/4;
            pt0.y = rand() % (img->height/2) + img->height/4;
            cvSeqPush( ptseq, &pt0 );
        }
        hull = cvConvexHull2( ptseq, 0, CV_CLOCKWISE, 0 );
        hullcount = hull->total;
#else
        CvPoint* points = (CvPoint*)malloc( count * sizeof(points[0]));
        int* hull = (int*)malloc( count * sizeof(hull[0]));
        CvMat point_mat = cvMat( 1, count, CV_32SC2, points );
        CvMat hull_mat = cvMat( 1, count, CV_32SC1, hull );
        for( i = 0; i < count; i++ )
        {
            pt0.x = rand() % (img->width/2) + img->width/4;
            pt0.y = rand() % (img->height/2) + img->height/4;
            points[i] = pt0;
        }
        cvConvexHull2( &point_mat, &hull_mat, CV_CLOCKWISE, 0 );
        hullcount = hull_mat.cols;
#endif
        cvZero( img );
        for( i = 0; i < count; i++ )
        {
#if !ARRAY
            pt0 = *CV_GET_SEQ_ELEM( CvPoint, ptseq, i );
#else
            pt0 = points[i];
#endif
            cvCircle( img, pt0, 2, CV_RGB( 255, 0, 0 ), CV_FILLED );
        }
#if !ARRAY
        pt0 = **CV_GET_SEQ_ELEM( CvPoint*, hull, hullcount - 1 );
#else
        pt0 = points[hull[hullcount-1]];
#endif
        for( i = 0; i < hullcount; i++ )
        {
#if !ARRAY
            CvPoint pt = **CV_GET_SEQ_ELEM( CvPoint*, hull, i );
#else
            CvPoint pt = points[hull[i]];
#endif
            cvLine( img, pt0, pt, CV_RGB( 0, 255, 0 ));
            pt0 = pt;
        }
        cvShowImage( "hull", img );
        int key = cvWaitKey(0);
        if( key == 27 ) // 'ESC'
            break;
#if !ARRAY
        cvClearMemStorage( storage );
#else
        free( points );
        free( hull );
#endif
    }
}

例子2

#include "opencv\cv.h"
#include "opencv\highgui.h"
#include <stdlib.h>

#define ARRAY  1 /* switch between array/sequence method by replacing 0<=>1 */

int main( int argc, char** argv )
{
    IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
    cvNamedWindow( "hull", 1 );

#if !ARRAY
        CvMemStorage* storage = cvCreateMemStorage();
#endif

    for(;;)
    {
        int i,count = rand()%100+1,hullcount;
        CvPoint pt0;
#if !ARRAY
        CvSeq *ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2,
            sizeof(CvContour),sizeof(CvPoint),storage);
        CvSeq *hull;
        //随机得到点
        for (i=0;i<count;i++)
        {
            pt0.x = rand()%(img->width/2) + img->height/4;
            pt0.y = rand()%(img->height/2) + img->width/4;
            cvSeqPush(ptseq,&pt0);
        }
        hull = cvConvexHull2(ptseq,0,CV_CLOCKWISE,0);//顺时针
        hullcount = hull->total;
#else
        CvPoint *points = (CvPoint *)malloc(count * sizeof(points[0]));
        int *hull = (int *)malloc(count*sizeof(hull[0]));
        CvMat point_mat = cvMat(1,count,CV_32SC2,points);
        CvMat hull_mat = cvMat(1,count,CV_32SC1,hull);
        //随机得到点
        for (i=0;i<count;i++)
        {
            pt0.x = rand()%(img->width/2) + img->height/4;
            pt0.y = rand()%(img->height/2) + img->width/4;
            points[i]=pt0;
        }
        cvConvexHull2(&point_mat,&hull_mat,CV_CLOCKWISE,0);
        hullcount = hull_mat.cols;//注意这些与序列处理方式不同的地方
#endif
        cvZero(img);//清空img,准备画新图

        //画点
        for (i=0;i<count;i++)
        {
#if !ARRAY
            pt0 = *CV_GET_SEQ_ELEM(CvPoint , ptseq ,i);
#else
            pt0 = points[i];
#endif
            cvCircle(img,pt0,2,CV_RGB(255,0,0),CV_FILLED);
        }

//确定一个端点
#if !ARRAY
        pt0 = **CV_GET_SEQ_ELEM(CvPoint*,hull,hullcount -1);
#else
        pt0 = points[hull[hullcount-1]];
#endif

        for (i=0;i<hullcount;i++)
        {
#if !ARRAY
            CvPoint pt = **CV_GET_SEQ_ELEM(CvPoint*,hull,i);
#else
            CvPoint pt = points[hull[i]];
#endif
            cvLine(img,pt0,pt,CV_RGB(0,255,0));
            pt0 = pt;
        }
        cvShowImage("hull",img);
        cvWaitKey(0);
        cvSaveImage("hull.jpg",img);
        cvDestroyWindow("hull");
#if !ARRAY
        cvClearMemStorage(storage);
#else
        free(points);
        free(hull);
#endif
    }
    return 0;
}

例子3

    #include <opencv\cv.h>  
    #include <opencv\cxcore.h>  
    #include <opencv\highgui.h>  
    #include <opencv\cvaux.h>  
    #include <iostream>  
    using namespace std;  
      
    int main()  
    {  
        IplImage *src = cvLoadImage("f:\\img\\1.bmp",CV_LOAD_IMAGE_GRAYSCALE);  
        IplImage *dst = cvCreateImage(cvGetSize(src),8,3);cvZero(dst);  
        CvMemStorage *storage = cvCreateMemStorage();  
        CvSeq *contour = NULL , *hull = NULL;  
        cvShowImage("src",src);
      
        CvContourScanner scanner = cvStartFindContours(src,storage);  
        while((contour = cvFindNextContour(scanner)) != NULL){  
            cvDrawContours(dst,contour,CV_RGB(255,0,0),CV_RGB(0,255,0),0);  
              
            cout<<cvCheckContourConvexity(contour)<<endl;  
      
            hull = cvConvexHull2(contour,0,CV_CLOCKWISE,0);  
              
            CvPoint pt0 = **(CvPoint**)cvGetSeqElem(hull,hull->total - 1);  
            for(int i = 0;i<hull->total;++i){  
                CvPoint pt1 = **(CvPoint**)cvGetSeqElem(hull,i);  
                cvLine(dst,pt0,pt1,CV_RGB(0,0,255));  
                pt0 = pt1;  
            }  
      
            CvSeq *defect = cvConvexityDefects(contour,hull);  
              
            for(int i = 0;i<defect->total;++i){  
                CvConvexityDefect df = *(CvConvexityDefect*)cvGetSeqElem(defect,i);  
                cvCircle(dst,*df.start,2,CV_RGB(255,255,0),-1);  
                cvCircle(dst,*df.end,2,CV_RGB(255,255,0),-1);  
                cvCircle(dst,*df.depth_point,2,CV_RGB(0,255,255),-1);  
            }  
              
            cvShowImage("dst",dst);  
            cvWaitKey();  
        }  
        cvEndFindContours(&scanner);  
    }  


例子4

    #include <opencv/cv.h>  
    #include <opencv/cxcore.h>  
    #include <opencv/highgui.h>  
	#include <math.h>
      
    #define POINT_NUM 100  
    #define WIDTH 800  
    #define HEIGHT 800  
    #define zero 1e-12  
      
    #define DIS(a,b) sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y))  
    #define SGN(x) (fabs(x)<zero?0:(x>0?1:-1))  
    #define CROSS(a,b,c) ((b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x))//叉积,用来判断旋转方向  
    #define CMP(a,b) (a.x < b.x || SGN((float)a.x -(float) b.x)==0 && a.y < b.y)//坐标的比较  
    #define RAND (rand() % 100000 / 100000.0)//产生0-1之间的浮点数  
      
    CvPoint p[POINT_NUM];  
    CvPoint* hull_p = new CvPoint[POINT_NUM];//用来储存凸包上的点  
    int hull_size = 0;  
    IplImage* img;  
    //下面简单实现了栈操作  
    inline void push(CvPoint* S,CvPoint pt)  
    {  
        S[hull_size++] = pt;  
    }  
    inline CvPoint pop(CvPoint* S)  
    {  
        return S[--hull_size];  
    }  
      
    inline void swap(int x,int y)  
    {  
        CvPoint pt = p[x];  
        p[x] = p[y];  
        p[y] = pt;  
    }  
      
    inline bool compare(CvPoint a,CvPoint b,CvPoint c)  
    {  
        int tmp = SGN((float)CROSS(a,b,c));  
        if(tmp != 0)  
            return tmp > 0;  
        else//如果两点共线的话,就需要比较远近了  
            return DIS((float)a,(float)b) < DIS((float)a,(float)b);  
    }  
    //快排,极角的排序  
    void sort(int l,int r)  
    {  
        CvPoint tmp = p[(l + r) / 2];  
        int i = l;  
        int j = r;  
        do  
        {  
            while(compare(p[0],p[i],tmp))i++;  
            while(compare(p[0],tmp,p[j]))j--;  
            if(i <= j)  
            {  
                swap(i,j);  
                i++;  
                j--;  
            }  
        }while(i <=j);  
        if(i < r)sort(i,r);  
        if(j > l)sort(l,j);  
    }  
	    void draw_hull()  
    {  
        int min = -1;  
        for(int j = 0;j < POINT_NUM;j++)//找出x坐标最小的,作为起始点  
        {  
            if(min == -1 || CMP(p[j],p[min]))  
                min = j;  
        }  
        if(min != 0)  
            swap(0,min);  
      
        sort(1,POINT_NUM - 1);//其他点排序  
      
        push(hull_p,p[0]);  
        push(hull_p,p[1]);  
        push(hull_p,p[2]);  
        for(int i = 3;i < POINT_NUM;i++)  
        {  
            while(CROSS(hull_p[hull_size - 2],hull_p[hull_size - 1],p[i]) < 0)//非左转  
            {  
                pop(hull_p);  
                cvLine(img,hull_p[hull_size - 1],p[i],cvScalar(255,0,255));//为了看清运行过程而加的  
                cvShowImage("Image",img);  
                cvWaitKey(100);  
            }  
            cvLine(img,hull_p[hull_size - 1],p[i],cvScalar(255,0,255));  
            push(hull_p,p[i]);  
        }  
      
        cvPolyLine(img,&hull_p,&hull_size,1,1,cvScalar(0,0,255),2);//最终画出凸包  
    }  
	    void show_outcome()  
    {  
        cvSet(img,cvScalar(255,255,255));  
        CvScalar color = cvScalar(0,0,0);  
        for(int i = 0;i < POINT_NUM;i++)//画出每个点,十字  
        {  
            int x = p[i].x;  
            int y = p[i].y;  
            cvLine(img,cvPoint(x - 5,y),cvPoint(x + 5,y),color,2);  
            cvLine(img,cvPoint(x,y - 5),cvPoint(x,y + 5),color,2);  
        }  
        draw_hull();  
        cvShowImage("Image",img);  
        cvWaitKey(0);  
    }  
		    int main()  
    {  
        img = cvCreateImage(cvSize(WIDTH,HEIGHT),IPL_DEPTH_8U,3);  
          
        srand((unsigned)time(NULL));  
        double phase = RAND * CV_PI * 2.0;  
        for (int i = 0; i < POINT_NUM / 2; i++) {  
            double r =  RAND * WIDTH / 4.0;  
            double theta = RAND * 1.5 * CV_PI + phase;  
            p[i] = cvPoint( WIDTH /4 + r * cos(theta), HEIGHT / 2 + 2 * r * sin(theta) );//椭圆  
        }  
        phase = RAND * CV_PI * 2.0;  
        for (int i = 0; i < POINT_NUM / 2; i++) {  
            double r =  RAND * WIDTH / 4.0;  
            double theta = RAND * 1.5 * CV_PI + phase;  
            p[i + POINT_NUM / 2] = cvPoint(WIDTH / 4 * 3 +  r * cos(theta), HEIGHT / 2 +  r * sin(theta));//圆  
        }  
      
        show_outcome();  
        delete [] hull_p;  
        return 0;  
    }  

例子5


    #include "stdafx.h"    
    #include "opencv\cv.h"    
    #include "opencv\highgui.h"    
    int main( int argc, char** argv )    
    {    
        IplImage* src;    
        src=cvLoadImage("f:\\img\\pf.jpg",CV_LOAD_IMAGE_GRAYSCALE);   
		cvShowImage( "Source", src ); 
        IplImage* dst = cvCreateImage( cvGetSize(src), 8, 3 );    
        CvMemStorage* storage = cvCreateMemStorage(0);    
        CvSeq* contour = 0;    
        cvThreshold( src, src,120, 255, CV_THRESH_BINARY );//二值化    
        //cvNamedWindow( "Source", 1 );    
        //cvShowImage( "Source", src );    
        //提取轮廓    
        cvFindContours( src, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );    
        cvZero( dst );//清空数组    
        CvSeq* _contour =contour;     
        double maxarea=0;    
        double minarea=100;    
        int n=-1,m=0;//n为面积最大轮廓索引,m为迭代索引    
        for( ; contour != 0; contour = contour->h_next )    
        {    
        
            double tmparea=fabs(cvContourArea(contour));    
            if(tmparea < minarea)     
            {    
                cvSeqRemove(contour,0); //删除面积小于设定值的轮廓    
                continue;    
            }    
            CvRect aRect = cvBoundingRect( contour, 0 );     
            if ((aRect.width/aRect.height)<1)    
            {    
                cvSeqRemove(contour,0); //删除宽高比例小于设定值的轮廓    
                continue;    
            }    
            if(tmparea > maxarea)    
            {    
                maxarea = tmparea;    
                n=m;    
            }    
            m++;    
            //  CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );//创建一个色彩值    
            CvScalar color = CV_RGB( 0, 255,255 );    
        
            //max_level 绘制轮廓的最大等级。如果等级为0,绘制单独的轮廓。如果为1,绘制轮廓及在其后的相同的级别下轮廓。    
            //如果值为2,所有的轮廓。如果等级为2,绘制所有同级轮廓及所有低一级轮廓,诸此种种。    
            //如果值为负数,函数不绘制同级轮廓,但会升序绘制直到级别为abs(max_level)-1的子轮廓。     
            cvDrawContours( dst, contour, color, color, -1, 1, 8 );//绘制外部和内部的轮廓    
        }    
        contour =_contour; /*int k=0;*/    
        int count=0;    
        for( ; contour != 0; contour = contour->h_next )    
        {    
            count++;    
            double tmparea=fabs(cvContourArea(contour));    
            if (tmparea==maxarea /*k==n*/)    
            {    
                CvScalar color = CV_RGB( 255, 0, 0);    
                cvDrawContours( dst, contour, color, color, -1, 1, 8 );    
            }    
            /*k++;*/    
        }    
        printf("The total number of contours is:%d",count);    
        cvNamedWindow( "Components", 1 );    
        cvShowImage( "Components", dst );    
        cvWaitKey(0);    
        cvDestroyWindow( "Source" );    
        cvReleaseImage(&src);    
        cvDestroyWindow( "Components" );    
        cvReleaseImage(&dst);    
        return 0;    
    }    

二值化查找最大连通区域的方法


  
#include <opencv2/opencv.hpp>  
#include <iostream>   
#include <vector>
using namespace cv;  
using namespace std;
    int main( int argc, char** argv )    
    {    
        Mat srcImg  ;  
        srcImg=imread("f:\\img\\pf.jpg");   
		imshow( "Source", srcImg ); 
		cv::Mat bwImg;
		 
	vector<vector<cv::Point>> contours ;  

	// 二值化图像
	//cv::threshold(srcImg, bwImg, 0.0, 255.0, CV_THRESH_BINARY | CV_THRESH_OTSU);
	 cv::threshold(srcImg, bwImg, 100, 255, CV_THRESH_BINARY_INV);

	cv::imshow("binary image", bwImg);
	cv::waitKey();

	// 查找轮廓,对应连通域
	cv::findContours(bwImg,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);

	// 寻找最大连通域
	double maxArea = 0;
	vector<cv::Point> maxContour;
	for(size_t i = 0; i < contours.size(); i++)
	{
		double area = cv::contourArea(contours[i]);
		if (area > maxArea)
		{
			maxArea = area;
			maxContour = contours[i];
		}
	}

	// 将轮廓转为矩形框
	cv::Rect maxRect = cv::boundingRect(maxContour);

	// 显示连通域
	cv::Mat result1, result2;

	bwImg.copyTo(result1);
	bwImg.copyTo(result2);
	
	for (size_t i = 0; i < contours.size(); i++)
	{
		cv::Rect r = cv::boundingRect(contours[i]);
		cv::rectangle(result1, r, cv::Scalar(255));
	}
	cv::imshow("all regions", result1) ;
	cv::waitKey();

	cv::rectangle(result2, maxRect, cv::Scalar(255));
	cv::imshow("largest region", result2) ;
	cv::waitKey(); 
        return 0;    
    }    

识别3角形

 #include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream>
 using namespace std;
int thresh = 50;
IplImage* img =NULL;
IplImage* img0 = NULL;
CvMemStorage* storage =NULL;
const char * wndname = "三角形识别 Demo";


// 两个向量之间找到角度的余弦值
// from pt0->pt1 and from pt0->pt2
double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )
{
 double dx1 = pt1->x - pt0->x;
 double dy1 = pt1->y - pt0->y;
 double dx2 = pt2->x - pt0->x;
 double dy2 = pt2->y - pt0->y;
 return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

// 返回图像中找到的轮廓序列
// 序列存储在内存存储器中
CvSeq* findSquares4( IplImage* img, CvMemStorage* storage )
{
 CvSeq* contours;
 int i, c, l, N = 11;
 CvSize sz = cvSize( img->width & -2, img->height & -2 ); 
 
 IplImage* timg = cvCloneImage( img );
 IplImage* gray = cvCreateImage( sz, 8, 1 );
 IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );
 IplImage* tgray;
 CvSeq* result;
 double s, t;
 // 创建一个空序列用于存储轮廓和角点
 CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );

 cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height ));
 // 过滤噪音
 cvPyrDown( timg, pyr, 7 );
 cvPyrUp( pyr, timg, 7 );
 tgray = cvCreateImage( sz, 8, 1 );

 // find squares in every color plane of the image
 for( c = 0; c < 3; c++ )
 {
  // 提取 the c-th color plane
  cvSetImageCOI( timg, c+1 );
  cvCopy( timg, tgray, 0 );

  // try several threshold levels
  for( l = 0; l < N; l++ )
  {
   // hack: use Canny instead of zero threshold level.
   // Canny helps to catch squares with gradient shading  
   if( l == 0 )
   {
    // apply Canny. Take the upper threshold from slider
    // and set the lower to 0 (which forces edges merging)
    cvCanny( tgray, gray, 0, thresh, 5 );
    // dilate canny output to remove potential
    // holes between edge segments
    cvDilate( gray, gray, 0, 1 );
   }
   else
   {
    // apply threshold if l!=0:
    //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
    cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY );
   }

   // 找到所有轮廓并且存储在序列中
   cvFindContours( gray, storage, &contours, sizeof(CvContour),
    CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );

   // test each contour
   while( contours )
   {
    // approximate contour with accuracy proportional
    // to the contour perimeter
    result = cvApproxPoly( contours, sizeof(CvContour), storage,
     CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );
    // 三角形轮廓应当有3个顶点,3条边
    // relatively large area (过滤干扰的轮廓)
    // cvCheckContourConvexity保证是凸面的
    // cvContourArea计算三角形区域面积,去掉一些不相干的区域
    if( result->total == 3 &&
     fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 &&
     fabs(cvContourArea(result,CV_WHOLE_SEQ)) < 100000 &&
     cvCheckContourConvexity(result) )
    {
     

      for( i = 0; i < 3; i++ )
       cvSeqPush( squares,
       (CvPoint*)cvGetSeqElem( result, i ));
    }

    // 继续查找下一个轮廓
    contours = contours->h_next;
   }
  }
 }

 // release all the temporary images
 cvReleaseImage( &gray );
 cvReleaseImage( &pyr );
 cvReleaseImage( &tgray );
 cvReleaseImage( &timg );

 return squares;
}


// the function draws all the squares in the image
void drawSquares( IplImage* img, CvSeq* squares )
{
 CvSeqReader reader;
 IplImage* cpy = cvCloneImage( img );
 int i;

 // initialize reader of the sequence
 cvStartReadSeq( squares, &reader, 0 );

 // read 4 sequence elements at a time (all vertices of a square)
 for( i = 0; i < squares->total; i += 3 )
 {
  CvPoint pt[3], *rect = pt;
  int count = 3;

  // read 3 vertices
  CV_READ_SEQ_ELEM( pt[0], reader );
  CV_READ_SEQ_ELEM( pt[1], reader );
  CV_READ_SEQ_ELEM( pt[2], reader );

  // cvPolyLine函数画出三角形轮廓
  cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );
 }

 // show the resultant image
 cvShowImage( wndname, cpy );
 cvReleaseImage( &cpy );
}


char* names[] = {  "c:\\img\\1.png",  0 };

int main(int argc, char** argv)
{
 int i, c;
 // create memory storage that will contain all the dynamic data
 storage = cvCreateMemStorage(0);

 for( i = 0; names[i] != 0; i++ )
 {
  img0 = cvLoadImage( names[i], 1 );
  if( !img0 )
  {
   cout<<"不能载入"<<names[i]<<"继续下一张图片"<<endl;
   continue;
  }
  img = cvCloneImage( img0 );
  
  cvNamedWindow( wndname, 1 );

  drawSquares( img, findSquares4( img, storage ) );
  c = cvWaitKey(0);
  // release both images
  cvReleaseImage( &img );
  cvReleaseImage( &img0 );
  // clear memory storage - reset free space position
  cvClearMemStorage( storage );
  if( (char)c == 27 )
   break;
 }

 cvDestroyWindow( wndname );
 return 0;
}

识别长方形

#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream>
using namespace std;
int thresh = 50;
IplImage* img =NULL;
IplImage* img0 = NULL;
CvMemStorage* storage =NULL;
const char * wndname = "正方形检测 demo";

//angle函数用来返回(两个向量之间找到角度的余弦值)
double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )
{
 double dx1 = pt1->x - pt0->x;
 double dy1 = pt1->y - pt0->y;
 double dx2 = pt2->x - pt0->x;
 double dy2 = pt2->y - pt0->y;
 return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

// 返回图像中找到的所有轮廓序列,并且序列存储在内存存储器中

CvSeq* findSquares4( IplImage* img, CvMemStorage* storage )
{
 CvSeq* contours;
 int i, c, l, N = 11;
 CvSize sz = cvSize( img->width & -2, img->height & -2 ); 
 
 IplImage* timg = cvCloneImage( img );
 IplImage* gray = cvCreateImage( sz, 8, 1 );
 IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );
 IplImage* tgray;
 CvSeq* result;
 double s, t;
 // 创建一个空序列用于存储轮廓角点
 CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );

 cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height ));
 // 过滤噪音
 cvPyrDown( timg, pyr, 7 );
 cvPyrUp( pyr, timg, 7 );
 tgray = cvCreateImage( sz, 8, 1 );

 // 红绿蓝3色分别尝试提取
 for( c = 0; c < 3; c++ )
 {
  // 提取 the c-th color plane
  cvSetImageCOI( timg, c+1 );
  cvCopy( timg, tgray, 0 );

  // 尝试各种阈值提取得到的(N=11)
  for( l = 0; l < N; l++ )
  {
   // apply Canny. Take the upper threshold from slider
   // Canny helps to catch squares with gradient shading  
   if( l == 0 )
   {
    cvCanny( tgray, gray, 0, thresh, 5 );
    //使用任意结构元素膨胀图像
    cvDilate( gray, gray, 0, 1 );
   }
   else
   {
    // apply threshold if l!=0:
    cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY );
   }

   // 找到所有轮廓并且存储在序列中
   cvFindContours( gray, storage, &contours, sizeof(CvContour),
    CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );

   // 遍历找到的每个轮廓contours
   while( contours )
   {
     //用指定精度逼近多边形曲线
    result = cvApproxPoly( contours, sizeof(CvContour), storage,
     CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );
                  

    if( result->total == 4 &&
     fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 500 &&
     fabs(cvContourArea(result,CV_WHOLE_SEQ)) < 100000 &&
     cvCheckContourConvexity(result) )
    {
     s = 0;

     for( i = 0; i < 5; i++ )
     {
      // find minimum angle between joint edges (maximum of cosine)
      if( i >= 2 )
      {
       t = fabs(angle(
        (CvPoint*)cvGetSeqElem( result, i ),
        (CvPoint*)cvGetSeqElem( result, i-2 ),
        (CvPoint*)cvGetSeqElem( result, i-1 )));
       s = s > t ? s : t;
      }
     }

     // if 余弦值 足够小,可以认定角度为90度直角
     //cos0.1=83度,能较好的趋近直角
     if( s < 0.1 )  
      for( i = 0; i < 4; i++ )
       cvSeqPush( squares,
       (CvPoint*)cvGetSeqElem( result, i ));
    }

    // 继续查找下一个轮廓
    contours = contours->h_next;
   }
  }
 }
 cvReleaseImage( &gray );
 cvReleaseImage( &pyr );
 cvReleaseImage( &tgray );
 cvReleaseImage( &timg );

 return squares;
}

//drawSquares函数用来画出在图像中找到的所有正方形轮廓
void drawSquares( IplImage* img, CvSeq* squares )
{
 CvSeqReader reader;
 IplImage* cpy = cvCloneImage( img );
 int i;
 cvStartReadSeq( squares, &reader, 0 );

 // read 4 sequence elements at a time (all vertices of a square)
 for( i = 0; i < squares->total; i += 4 )
 {
  CvPoint pt[4], *rect = pt;
  int count = 4;

  // read 4 vertices
  CV_READ_SEQ_ELEM( pt[0], reader );
  CV_READ_SEQ_ELEM( pt[1], reader );
  CV_READ_SEQ_ELEM( pt[2], reader );
  CV_READ_SEQ_ELEM( pt[3], reader );

  // draw the square as a closed polyline
  cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 2, CV_AA, 0 );
 }

 cvShowImage( wndname, cpy );
 cvReleaseImage( &cpy );
}


char* names[] = { "c:\\img\\1.png",  0 };

int main(int argc, char** argv)
{
 int i, c;
 storage = cvCreateMemStorage(0);

 for( i = 0; names[i] != 0; i++ )
 {
  img0 = cvLoadImage( names[i], 1 );
  if( !img0 )
  {
   cout<<"不能载入"<<names[i]<<"继续下一张图片"<<endl;
   continue;
  }
  img = cvCloneImage( img0 );
  cvNamedWindow( wndname, 1 );

  // find and draw the squares
  drawSquares( img, findSquares4( img, storage ) );

  c = cvWaitKey(0);
  
  cvReleaseImage( &img );
  cvReleaseImage( &img0 );

  cvClearMemStorage( storage );

  if( (char)c == 27 )
   break;
 }

 cvDestroyWindow( wndname );
 return 0;
}

检测圆

#include "cv.h"
#include "highgui.h"
#include <math.h>
#include <string.h>
#include <iostream>
using namespace std;
int thresh = 50;
IplImage* img =NULL;
IplImage* img0 = NULL;
IplImage * pImg8u=NULL;

CvMemStorage* storage =NULL;
const char * wndname = "圆形检测  Demo";
char* names[] = { "c:\\img\\1.png", 0};

void HoughCircle()
{

 CvSeq * circles=NULL;
 pImg8u=cvCreateImage(cvGetSize(img),8,1);
 CvMemStorage* storage = cvCreateMemStorage(0);
 cvCvtColor(img,pImg8u,CV_BGR2GRAY);
 //最好先cvSmooth一下,再调用cvHoughCircles
 cvSmooth(pImg8u,pImg8u,CV_GAUSSIAN,7,7);
 circles=cvHoughCircles(pImg8u,storage,CV_HOUGH_GRADIENT,
  2,   //最小分辨率,应当>=1
  pImg8u->height/4,   //该参数是让算法能明显区分的两个不同圆之间的最小距离
  140,   //用于Canny的边缘阀值上限,下限被置为上限的一半
  118,    //累加器的阀值
  2,  //最小圆半径 
  120  //最大圆半径
  );

 int k;
 for (k=0;k<circles->total;k++)
 {
  float *p=(float*)cvGetSeqElem(circles,k);
  //cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), 3, CV_RGB(0,255,0), -1, 8, 0 );
  cvCircle(img,cvPoint(cvRound(p[0]),cvRound(p[1])),cvRound(p[2]),CV_RGB(0,0,0),3,CV_AA,0);
 }

 cvClearMemStorage( storage );

}

int main(int argc, char** argv)
{
 int i, c;
 // create memory storage that will contain all the dynamic data


 for( i = 0; names[i] != 0; i++ )
 {
  img0 = cvLoadImage( names[i], 1 );
  if( !img0 )
  {
   cout<<"不能载入"<<names[i]<<"继续下一张图片"<<endl;
   continue;
  }
  img = cvCloneImage( img0 );

  HoughCircle();
  cvNamedWindow( wndname, 1 );
  cvShowImage(wndname,img);

  c = cvWaitKey(0);

  cvReleaseImage( &img );
  cvReleaseImage( &img0 );
  cvReleaseImage(&pImg8u);


  if( (char)c == 27 )
   break;
 }

 cvDestroyWindow( wndname );
 return 0;
}

findrgb


#include "cv.h"
#include "highgui.h"
#include <math.h>
#include <string.h>
#include <iostream>
using namespace std;
IplImage* img =NULL;
IplImage* img0 =NULL;
IplImage* pic = NULL;
CvMemStorage* storage =NULL;
const char * wndname = "RGB检测  Demo";
char* names[] = { "c:\\img\\2.jpg",0};

void findRGB(IplImage *img,IplImage *pic)
{ 
for(int x=0;x<img->height;x++)
 {
 for(int y=0;y<img->width;y++)
 {

  if( ((uchar*)(img->imageData+x*img->widthStep))[y*img->nChannels+0]<30  //b
   &&((uchar*)(img->imageData + x*img->widthStep))[y*img->nChannels + 1]<30  //g
   &&((uchar*)(img->imageData + x*img->widthStep))[y*img->nChannels + 2]>150)  //r
   CV_IMAGE_ELEM(pic,uchar,x,y)=255;

  if (((uchar*)(img->imageData+x*img->widthStep))[y*img->nChannels+0]<30  //b
   &&((uchar*)(img->imageData + x*img->widthStep))[y*img->nChannels + 1]>150  //g
   &&((uchar*)(img->imageData + x*img->widthStep))[y*img->nChannels + 2]<30) //r
   CV_IMAGE_ELEM(pic,uchar,x,y)=255;

  if (((uchar*)(img->imageData+x*img->widthStep))[y*img->nChannels+0]>150  //b
   &&((uchar*)(img->imageData + x*img->widthStep))[y*img->nChannels + 1]<30  //g
   &&((uchar*)(img->imageData + x*img->widthStep))[y*img->nChannels + 2]<30) //r
   CV_IMAGE_ELEM(pic,uchar,x,y)=255; 
 }
}
}

//cvFindContours( pic, storage, &contour, sizeof(CvContour),
      //CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
//cvDrawContours(pic, contour,
     // CV_RGB(180,0,0), CV_RGB(0, 0, 0),
     // 2, 2, 8);

 

int main(int argc, char** argv)
{
 int i, c;
 for( i = 0; names[i] != 0; i++ )
 {
  img0 = cvLoadImage( names[i], 1 );
  if( !img0 )
  {
   cout<<"不能载入"<<names[i]<<"继续下一张图片"<<endl;
   continue;
  }
  img = cvCloneImage( img0 );

  
  IplImage* pic=cvCreateImage( cvSize(img->width,img->height),8,1 );
  cvNamedWindow( wndname, 1 );
  cvShowImage(wndname,img);

  findRGB(img,pic);
  cvNamedWindow("findRGB",1);
  cvShowImage("findRGB",pic);
    
  c = cvWaitKey(0);

  cvReleaseImage( &img );
  cvReleaseImage( &img0 );
  cvReleaseImage(&pic);
  
  if( (char)c == 27 )
   break;
 }

 cvDestroyWindow( "wndname" );
 cvDestroyWindow("findRGB");
 return 0;
 
}

判断点在3角形

#include "stdafx.h"
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
#include <math.h>
#include <iostream>
using namespace std;

double get_distance(CvPoint aA,CvPoint aB)
{
    double distanceAB=0.0;
    distanceAB=sqrt(double(aA.x-aB.x)*double(aA.x-aB.x)+double(aA.y-aB.y)*double(aA.y-aB.y));
    return distanceAB;

}

double get_triangleArea(CvPoint aA, CvPoint aB, CvPoint aC)
{
    double distanceAB=get_distance(aA,aB);
    double distanceBC=get_distance(aB,aC);
    double distanceCA=get_distance(aC,aA);
    double distanceSum=(distanceAB+distanceBC+distanceCA)/2;
    double area=0.0;
    area=sqrt(distanceSum*(distanceSum-distanceAB)*(distanceSum-distanceBC)*(distanceSum-distanceCA));
    return area;

}
bool PointinTriangle(CvPoint aA, CvPoint aB, CvPoint aC, CvPoint aP)
{
    double areaABC=get_triangleArea(aA,aB,aC);
    double areaABP=get_triangleArea(aA,aB,aP);
    double areaACP=get_triangleArea(aA,aC,aP);
    double areaBCP=get_triangleArea(aB,aC,aP);
    if (areaABC==areaABP+areaACP+areaBCP)
    {
        return true;
    }
    else
    {
        return false;
    }



}

int _tmain(int argc, _TCHAR* argv[])
{
    CvPoint A;
    A.x=50;
    A.y=10;
    CvPoint B;
    B.x=10;
    B.y=50;
    CvPoint C;
    C.x=90;
    C.y=50;
    CvPoint P;
    P.x=50;
    P.y=30;
    if(PointinTriangle(A,B,C,P))
    {
        cout<<"在三角形内"<<endl;

    }
    else
    {
        cout <<"不在三角形内"<<endl;
    }
	cvWaitKey(30);

    return 0;
}

定位圆心出现偏斜

#include <cv.h>
#include <highgui.h>
#include <math.h>
#include <iostream> 
using namespace std;

int main(int argc, char* argv[])
{
IplImage* img;
img=cvLoadImage("f:\\img\\circle.jpg", 1);
IplImage* gray = cvCreateImage( cvGetSize(img), 8, 1 );
CvMemStorage* storage = cvCreateMemStorage(0);
cvCvtColor( img, gray, CV_BGR2GRAY );
cvSmooth( gray, gray, CV_GAUSSIAN, 9, 9 ); // smooth it, otherwise a lot of false circles may be detected
CvSeq* circles = cvHoughCircles( gray, storage, CV_HOUGH_GRADIENT, 2, gray->height/4, 200,100,5,200 );
int i;
for( i = 0; i < circles->total; i++ )
{
float* p = (float*)cvGetSeqElem( circles, i );
cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), 3, CV_RGB(0,255,0), -1, 8, 0 );
cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0 );
cout<<"圆心坐标x= "<<cvRound(p[0])<<endl<<"圆心坐标y= "<<cvRound(p[1])<<endl;
cout<<"半径="<<cvRound(p[2])<<endl; 

}
cout<<"圆数量="<<circles->total<<endl;
cvNamedWindow( "circles", 1 );
cvShowImage( "circles", img );
cvWaitKey(0);

return 0;
}

填充孔洞

#include <cv.h>
#include <highgui.h>
#include <math.h>
#include <iostream> 
using namespace std;
    #include <cv.h>   
    #include <cxcore.h>   
    #include <highgui.h>  
      
 
      
    // 内轮廓填充   
    // 参数:   
    // 1. pBinary: 输入二值图像,单通道,位深IPL_DEPTH_8U。  
    // 2. dAreaThre: 面积阈值,当内轮廓面积小于等于dAreaThre时,进行填充。   
    void FillInternalContours(IplImage *pBinary, double dAreaThre)   
    {   
        double dConArea;   
        CvSeq *pContour = NULL;   
        CvSeq *pConInner = NULL;   
        CvMemStorage *pStorage = NULL;   
        // 执行条件   
        if (pBinary)   
        {   
            // 查找所有轮廓   
            pStorage = cvCreateMemStorage(0);   
            cvFindContours(pBinary, pStorage, &pContour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);   
            // 填充所有轮廓   
            cvDrawContours(pBinary, pContour, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), 2, CV_FILLED, 8, cvPoint(0, 0));  
            // 外轮廓循环   
            for (; pContour != NULL; pContour = pContour->h_next)   
            {   
                // 内轮廓循环   
                for (pConInner = pContour->v_next; pConInner != NULL; pConInner = pConInner->h_next)   
                {   
                    // 内轮廓面积   
                    dConArea = fabs(cvContourArea(pConInner, CV_WHOLE_SEQ));   
                    if (dConArea <= dAreaThre)   
                    {   
                        cvDrawContours(pBinary, pConInner, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), 0, CV_FILLED, 8, cvPoint(0, 0));  
                    }   
                }   
            }   
            cvReleaseMemStorage(&pStorage);   
            pStorage = NULL;   
        }   
    }   
    int main()    
    {    
        IplImage *img = cvLoadImage("f:\\img\\1.jpg", 0);    
        IplImage *bin = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);  
        cvCopy(img, bin);  
      
        FillInternalContours(bin, 200);    
      
        cvNamedWindow("img");    
        cvShowImage("img", img);    
      
        cvNamedWindow("result");    
        cvShowImage("result", bin);    
      
        cvWaitKey(-1);    
      
        cvReleaseImage(&img);    
        cvReleaseImage(&bin);    
      
        return 0;    
    }   

角点检测

#include "stdafx.h"
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
#include <math.h>
#include <iostream>
using namespace std;

#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/imgproc/imgproc.hpp"  
#include <cmath>
#include <iostream>
using namespace cv;   

Mat harris(Mat &im, double sigma, int thresh, int radius){
  Mat dx,dy,Ix,Iy,Ix2,Iy2,Ixy,cim;

  Sobel( im, Ix, CV_64F, 1, 0, 3);   //算法第一步,计算水平垂直差分
  Sobel( im, Iy, CV_64F, 0, 1, 3);

  int ksize = max(1, (int)(6*sigma));
  if(ksize % 2 == 0)
    ksize++;
  GaussianBlur(Ix.mul(Ix), Ix2, Size(ksize, ksize), sigma);   //算法第二步,计算二阶高斯差分矩阵   
  GaussianBlur(Iy.mul(Iy), Iy2, Size(ksize, ksize), sigma);
  GaussianBlur(Ix.mul(Iy), Ixy, Size(ksize, ksize), sigma);

  //Harris corner measure
  //cim = (Ix2.*Iy2 - Ixy.^2)./(Ix2 + Iy2);
  cim = (Ix2.mul(Iy2) - Ixy.mul(Ixy)) / (Ix2+Iy2);			//算法第三步,计算响应函数,我使用了另外一种
  
  Mat structedElement(radius, radius, CV_8U, Scalar(1));
  Mat mx,norm_cim;
  normalize( cim, norm_cim, 0, 255, NORM_MINMAX, CV_8U, Mat() );
  dilate(norm_cim, mx, structedElement);
  norm_cim = ( norm_cim == mx) & (norm_cim>thresh);		   //算法第4第5步融合,非极大值抑制和阀值检测	

  return norm_cim;
}

int main( int, char** argv )  
{  
  Mat src,gray;
  
  src = imread( "c:\\img\\1.png");
  cvtColor( src, gray, CV_RGB2GRAY );
  
  Mat corners = harris(gray, 1.5, 30, 2);
  for( int j = 0; j < corners.rows ; j++ ) { 
    for( int i = 0; i < corners.cols; i++ ) {
      if( corners.at<unsigned char>(j,i) > 0)
      {
        circle( gray, Point( i, j ), 3,  Scalar(0), 2, 8, 0 );
      }
    }
  }
  
  namedWindow("result", 1); 
  imshow("result", gray);
  waitKey();  
  return 0;  
}

角点检测2

#include "stdafx.h"
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
#include <math.h>
#include <iostream>
using namespace std;
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

/// Global variables
Mat src, src_gray;
int thresh = 200;
int max_thresh = 255;

char* source_window = "Source image";
char* corners_window = "Corners detected";

/// Function header
void cornerHarris_demo( int, void* );

/** @function main */
int main( int argc, char** argv )
{
  /// Load source image and convert it to gray
  src = imread( "c:\\img\\1.png", 1 );
  cvtColor( src, src_gray, CV_BGR2GRAY );

  /// Create a window and a trackbar
  namedWindow( source_window, CV_WINDOW_AUTOSIZE );
  createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo );
  imshow( source_window, src );

  cornerHarris_demo( 0, 0 );

  waitKey(0);
  return(0);
}

/** @function cornerHarris_demo */
void cornerHarris_demo( int, void* )
{

  Mat dst, dst_norm, dst_norm_scaled;
  dst = Mat::zeros( src.size(), CV_32FC1 );

  /// Detector parameters
  int blockSize = 2;
  int apertureSize = 3;
  double k = 0.04;

  /// Detecting corners
  cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT );

  /// Normalizing
  normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
  convertScaleAbs( dst_norm, dst_norm_scaled );

  /// Drawing a circle around corners
  for( int j = 0; j < dst_norm.rows ; j++ )
     { for( int i = 0; i < dst_norm.cols; i++ )
          {
            if( (int) dst_norm.at<float>(j,i) > thresh )
              {
               circle( dst_norm_scaled, Point( i, j ), 5,  Scalar(0), 2, 8, 0 );
              }
          }
     }
  /// Showing the result
  namedWindow( corners_window, CV_WINDOW_AUTOSIZE );
  imshow( corners_window, dst_norm_scaled );
}

聚类

#include "stdafx.h"
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
#include <math.h>
#include <iostream>
using namespace std;
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
#include <iostream>

using namespace cv;
using namespace std;

// static void help()
// {
//     cout << "\nThis program demonstrates kmeans clustering.\n"
//             "It generates an image with random points, then assigns a random number of cluster\n"
//             "centers and uses kmeans to move those cluster centers to their representitive location\n"
//             "Call\n"
//             "./kmeans\n" << endl;
// }

int main( int /*argc*/, char** /*argv*/ )
{
    const int MAX_CLUSTERS = 5;
    Scalar colorTab[] =     //因为最多只有5类,所以最多也就给5个颜色
    {
        Scalar(0, 0, 255),
        Scalar(0,255,0),
        Scalar(255,100,100),
        Scalar(255,0,255),
        Scalar(0,255,255)
    };

    Mat img(500, 500, CV_8UC3);
    RNG rng(12345); //随机数产生器

    for(;;)
    {
        int k, clusterCount = rng.uniform(2, MAX_CLUSTERS+1);
        int i, sampleCount = rng.uniform(1, 1001);
        Mat points(sampleCount, 1, CV_32FC2), labels;   //产生的样本数,实际上为2通道的列向量,元素类型为Point2f

        clusterCount = MIN(clusterCount, sampleCount);
        Mat centers(clusterCount, 1, points.type());    //用来存储聚类后的中心点

        /* generate random sample from multigaussian distribution */
        for( k = 0; k < clusterCount; k++ ) //产生随机数
        {
            Point center;
            center.x = rng.uniform(0, img.cols);
            center.y = rng.uniform(0, img.rows);
            Mat pointChunk = points.rowRange(k*sampleCount/clusterCount,
                                             k == clusterCount - 1 ? sampleCount :
                                             (k+1)*sampleCount/clusterCount);   //最后一个类的样本数不一定是平分的,
                                                                                //剩下的一份都给最后一类
            //每一类都是同样的方差,只是均值不同而已
            rng.fill(pointChunk, CV_RAND_NORMAL, Scalar(center.x, center.y), Scalar(img.cols*0.05, img.rows*0.05));
        }

        randShuffle(points, 1, &rng);   //因为要聚类,所以先随机打乱points里面的点,注意points和pointChunk是共用数据的。

        kmeans(points, clusterCount, labels,
               TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0),
               3, KMEANS_PP_CENTERS, centers);  //聚类3次,取结果最好的那次,聚类的初始化采用PP特定的随机算法。

        img = Scalar::all(0);

        for( i = 0; i < sampleCount; i++ )
        {
            int clusterIdx = labels.at<int>(i);
            Point ipt = points.at<Point2f>(i);
            circle( img, ipt, 2, colorTab[clusterIdx], CV_FILLED, CV_AA );
        }

        imshow("clusters", img);

        char key = (char)waitKey();     //无限等待
        if( key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
            break;
    }

    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值