查看文章
 
OpenCV使用的一些经验总结
2009-08-19 16:58


使用OpenCV也有一段时间了,中间遇到了不少问题。一般都是到网络上找答案或者自己试验,现在把这些经验好好整理下,方便自己查找也方便同行参考。

最新更新日期:2009.08.05

一、轮廓(Contour)

1.cvDrawContours()可以填充轮廓内部。

cvDrawContours(gray, contour,cvScalar(255,255,255,0),cvScalar(255,255,255,0),0,CV_FILLED);//用黑色填充轮廓内部

2.得到所有轮廓中面积最大的一个

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
CvSeq *GetAreaMaxContour(CvSeq *contour)  
{//在给定的contour中找到面积最大的一个轮廓,并返回指向该轮廓的指针  
    double contour_area_temp=0,contour_area_max=0;  
    CvSeq * area_max_contour = 0 ;//指向面积最大的轮廓  
    CvSeq* c=0;  
    //printf( "Total Contours Detected: %d\n", Nc );  
    for(c=contour; c!=NULL; c=c->h_next )  
    {//寻找面积最大的轮廓,即循环结束时的area_max_contour  
        contour_area_temp = fabs(cvContourArea( c, CV_WHOLE_SEQ )); //获取当前轮廓面积  
        if( contour_area_temp > contour_area_max )  
        {  
            contour_area_max = contour_area_temp; //找到面积最大的轮廓  
            area_max_contour = c;//记录面积最大的轮廓  
        }  
    }  
    return area_max_contour;  
}
CvSeq *GetAreaMaxContour(CvSeq *contour)
{//在给定的contour中找到面积最大的一个轮廓,并返回指向该轮廓的指针
   double contour_area_temp=0,contour_area_max=0;
   CvSeq * area_max_contour = 0 ;//指向面积最大的轮廓
   CvSeq* c=0;
   //printf( "Total Contours Detected: %d\n", Nc );
   for(c=contour; c!=NULL; c=c->h_next )
   {//寻找面积最大的轮廓,即循环结束时的area_max_contour
    contour_area_temp = fabs(cvContourArea( c, CV_WHOLE_SEQ )); //获取当前轮廓面积
    if( contour_area_temp > contour_area_max )
    {
     contour_area_max = contour_area_temp; //找到面积最大的轮廓
     area_max_contour = c;//记录面积最大的轮廓
    }
   }
   return area_max_contour;
}

二、其他

1. 图像旋转

view plaincopy to clipboardprint?
void   RotateImage(IplImage *src,IplImage *dst,CvPoint center,float angle,float factor)  
{//以点center为旋转中心,对src旋转angle度并缩放factor倍。  
    float m[6];  
    CvMat mat=cvMat(2,3,CV_32FC1,m);  
    m[0] = (float)(factor*cos(-angle*CV_PI/180.));  
    m[1] = (float)(factor*sin(-angle*CV_PI/180.));  
    m[2] = center.x;  
    m[3] = -m[1];  
    m[4] = m[0];  
    m[5] = center.y;  
    cvSetZero(dst);  
    cvGetQuadrangleSubPix(src,dst,&mat);  
}
void   RotateImage(IplImage *src,IplImage *dst,CvPoint center,float angle,float factor)
{//以点center为旋转中心,对src旋转angle度并缩放factor倍。
   float m[6];
   CvMat mat=cvMat(2,3,CV_32FC1,m);
   m[0] = (float)(factor*cos(-angle*CV_PI/180.));
   m[1] = (float)(factor*sin(-angle*CV_PI/180.));
   m[2] = center.x;
   m[3] = -m[1];
   m[4] = m[0];
   m[5] = center.y;
   cvSetZero(dst);
   cvGetQuadrangleSubPix(src,dst,&mat);
}

2.把轮廓包括的区域摆正

view plaincopy to clipboardprint?
CvBox2D RegionRotate(IplImage *src,IplImage *dst,CvSeq *contour)  
{//传进来一个contour,然后计算它的最小包围矩形minRect,再把原图以包围矩形中心为旋转中心旋转minRect.angle°,得到调正的图像。  
    //dst 是通过cvClone()src得到的  

    CvMat *mat_contour = cvCreateMat(1,contour->total,CV_32FC2);//双通道  
    CvPoint2D32f *ptr_mat=(CvPoint2D32f*)(mat_contour->data.ptr);  
    for (int i=0;i!=contour->total;++i)  
    {  
        CvPoint *ptr_seq=(CvPoint*)(cvGetSeqElem(contour,i));  
        *ptr_mat=cvPointTo32f(*ptr_seq);//显示把CvPoint转换成CvPoint2D32F  
        ptr_mat++;  
    }//把轮廓变成矩阵  


    CvBox2D minRect = cvMinAreaRect2(mat_contour);//得到最小包围矩形  
    //CvMat *rot = cvCreateMat(2,3,CV_32FC1);  
    //cv2DRotationMatrix(cvPoint2D32f(src->width*0.5f,src->height*0.5f),minRect.angle,0.6,rot);//计算得到旋转矩阵----这里计算得到的矩阵不能使图像变换到想要的旋转结果  
    float m[6];  
    CvMat mat=cvMat(2,3,CV_32FC1,m);  
    float factor=1.0;//缩放  
    float angle = -minRect.angle;  
    float w=0,h=0;  
    w=minRect.center.x; h=minRect.center.y;  
    RotateImage(src,dst,cvPoint(w,h),angle,factor);  

    //cvEllipseBox(dst,minRect,cvScalar(0,0,255));  
    cvReleaseMat(&mat_contour);  
    return minRect;//返回最佳包围盒  

}
CvBox2D RegionRotate(IplImage *src,IplImage *dst,CvSeq *contour)
{//传进来一个contour,然后计算它的最小包围矩形minRect,再把原图以包围矩形中心为旋转中心旋转minRect.angle°,得到调正的图像。
   //dst 是通过cvClone()src得到的

   CvMat *mat_contour = cvCreateMat(1,contour->total,CV_32FC2);//双通道
   CvPoint2D32f *ptr_mat=(CvPoint2D32f*)(mat_contour->data.ptr);
   for (int i=0;i!=contour->total;++i)
   {
    CvPoint *ptr_seq=(CvPoint*)(cvGetSeqElem(contour,i));
    *ptr_mat=cvPointTo32f(*ptr_seq);//显示把CvPoint转换成CvPoint2D32F
    ptr_mat++;
   }//把轮廓变成矩阵


   CvBox2D minRect = cvMinAreaRect2(mat_contour);//得到最小包围矩形
   //CvMat *rot = cvCreateMat(2,3,CV_32FC1);
   //cv2DRotationMatrix(cvPoint2D32f(src->width*0.5f,src->height*0.5f),minRect.angle,0.6,rot);//计算得到旋转矩阵----这里计算得到的矩阵不能使图像变换到想要的旋转结果
   float m[6];
   CvMat mat=cvMat(2,3,CV_32FC1,m);
   float factor=1.0;//缩放
   float angle = -minRect.angle;
   float w=0,h=0;
   w=minRect.center.x; h=minRect.center.y;
   RotateImage(src,dst,cvPoint(w,h),angle,factor);

   //cvEllipseBox(dst,minRect,cvScalar(0,0,255));
   cvReleaseMat(&mat_contour);
   return minRect;//返回最佳包围盒

}

3、cvGetMat()

CvMat* cvGetMat( const CvArr* arr, CvMat* header, int* coi=NULL, int allowND=0 );

可以从一个IplImage *arr得到CvMat *matFromImage.但只是把原来图像的IplImage头变成了CvMat头,数据体部分并没有复制,所以如果此时Release了arr,则再访问matFromImage就会出现错误。

另外第二个参数是临时变量,声明一个CvMat型的就可以了。

view plaincopy to clipboardprint?
CvMat tempMat,*matFromImg;  
matFromImg = cvGetMat(Ibin,&tempMat);//temMat是临时变量

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/include1224/archive/2009/07/27/4384855.aspx


类别:默认分类||添加到搜藏 |分享到i贴吧|浏览(1654)|评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
     

   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu