轮廓随机均匀采样

context shape形状上下文中对轮廓点随机采样的实现
http://www.cnblogs.com/xiaotie/ 用C#实现了该算法且有详细的说明,我用opencv实现了一下。
 
效果图:
 
 
// shapeContenx.cpp : 定义控制台应用程序的入口点。
//
# include "stdafx.h"
# include "highgui.h"
# include "cv.h"
# include "cxcore.h"
# include "ml.h"
# include <list >
using namespace std;
# ifdef DEBUG
# pragma comment(lib, "opencv_core231d.lib")
# pragma comment(lib, "opencv_features2d231d.lib")
# pragma comment(lib, "opencv_flann231d.lib")
# pragma comment(lib, "opencv_gpu231d.lib")
# pragma comment(lib, "opencv_highgui231d.lib")
# pragma comment(lib, "opencv_imgproc231d.lib")
# pragma comment(lib, "opencv_ml231d.lib")
# else
# pragma comment(lib, "opencv_core231.lib")
# pragma comment(lib, "opencv_features2d231.lib")
# pragma comment(lib, "opencv_flann231.lib")
# pragma comment(lib, "opencv_gpu231.lib")
# pragma comment(lib, "opencv_highgui231.lib")
# pragma comment(lib, "opencv_imgproc231.lib")
# pragma comment(lib, "opencv_ml231.lib")
# endif
typedef struct _pairDistance
{
     int i;
     int j;
     int distance;
    _pairDistance( int ni , int nj , int ndistance) :i(ni),j(nj),distance(ndistance)
    {
    }
     bool operator < ( const _pairDistance &pd) const
    {
         return distance < pd.distance;
    }
}pairDistance;
/*
    函数:contoursample 
    功能:轮廓抽样
    参数:seq ------ 轮廓点序列
     samplearry --- 用于存放抽样点
         samplearry ---- 抽样点数
*/

void contoursample(CvSeq * seq , CvPoint *samplearry, int samplenum)
{
     int num = 0
     for (CvSeq *s = seq ; s !=NULL;s =s - >h_next)
        num +=s - >total;
    CvPoint *pointarray = (CvPoint *)malloc(num * sizeof(CvPoint));
    
     int accum = 0
     for (CvSeq *s =seq ; s !=NULL;s =s - >h_next)
    {
        cvCvtSeqToArray( s, pointarray +accum);
        accum +=s - >total;
        
    }
    
     if ( num < samplenum)
    {
        free(pointarray);
         return
    }
     // 轮廓点随机打乱
    CvRNG rng; 
    rng = cvRNG(cvGetTickCount());
    CvPoint pointtemp;
     int tagtemp = - 1;
     for ( int i = 0 ; i < num ; ++i)
    {
         int index = cvRandInt( &rng) %(num -i) +i;
         if(index !=i)
        {
            pointtemp = pointarray[index];
            pointarray[index] = pointarray[i];
            pointarray[i] = pointtemp;
            
        }
    }
     // 如果*samplenum > num 即取样点数远远小于轮廓点数随即抽取samplenum个点节省运算时间
     if (num > 3 * samplenum)
    {
        
        CvPoint *pointarray2 = (CvPoint *)malloc( 3 *samplenum * sizeof(CvPoint));
         for ( int i = 0;i < 3 *samplenum; ++i)
        {
            pointarray2[i] = pointarray[i];
        }
        free(pointarray);
        pointarray = pointarray2;
        num = 3 * samplenum;
    }
     // 计算轮廓点与点间距离
    list <pairDistance > list_pair;
     for ( int i = 0 ; i < num ; i ++)
    {
         for ( int j = i + 1 ; j < num ; ++j)
        {
            list_pair.push_back(pairDistance( i , j ,(pointarray[i].x -pointarray[j].x) * (pointarray[i].x -pointarray[j].x) + 
                (pointarray[i].y -pointarray[j].y) * (pointarray[i].y -pointarray[j].y)));
        }
    }
     // 排序
    list_pair.sort();
     // 删除最小距离点对中的其中一个点直到满足samplenum
     int nneedremove = num - samplenum;
     int *mask = ( int *)malloc( num * sizeof( int));
    memset(mask, 0,num * sizeof( int));
     //list<pairDistance>::iterator iter = list_pair.begin();
    list <pairDistance > : :iterator iter = list_pair.begin();
     while (nneedremove > 0)
    {
         int index0 = ( *iter).i;
         int index1 = ( *iter).j;
         if (mask[index0] == 0 && mask[index1] == 0)
        {
            mask[index1] = 1 ;
            nneedremove --;
        }
        iter ++;
    }
     // 将抽样点存放到samplearry中
     int nstartindex = 0 ;
     for ( int i = 0 ; i < num ; ++i)
    {
         if (mask[i] == 0)
        {
            samplearry[nstartindex] = pointarray[i];
            nstartindex ++;
        }
    }
    free(pointarray);
}
int _tmain( int argc, _TCHAR * argv[])
{
     //1 . 验证对数极坐标的缩放不变性
     //IplImage * im_a1 = cvLoadImage("W1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
     //IplImage * im_a2 = cvLoadImage("W2.jpg",CV_LOAD_IMAGE_GRAYSCALE);
     //cvNot(im_a1,im_a1);
     //cvNot(im_a2,im_a2);
     //IplImage * im_show1 = cvCreateImage(cvSize(360,360),8,1);
     //IplImage * im_show2 = cvCreateImage(cvSize(360,360),8,1);
     //cvLogPolar(im_a1,im_show1,cvPoint2D32f(im_a1->width/2,im_a1->height/2),40,CV_INTER_NN+CV_WARP_FILL_OUTLIERS);
     //cvLogPolar(im_a2,im_show2,cvPoint2D32f(im_a2->width/2,im_a2->height/2),40,CV_INTER_NN+CV_WARP_FILL_OUTLIERS);
     //cvShowImage("a1",im_show1);
     //cvShowImage("a2",im_show2);
    IplImage * im_src = cvLoadImage( "a.PNG",CV_LOAD_IMAGE_GRAYSCALE);
    IplImage * im_show = cvLoadImage( "a.PNG");
    IplImage * im_threshold = cvCreateImage(cvGetSize(im_src), 8, 1);
     // 1 . 统一尺寸大小
        
    cvThreshold(im_src,im_threshold, 128, 255,CV_THRESH_BINARY_INV);    
     // 2 . 轮廓提取
    CvMemStorage * storage = cvCreateMemStorage();
    CvSeq * contour = NULL;
    cvFindContours(im_threshold,storage, &contour, sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_NONE );
    
     //for (CvSeq *s = contour ; s!=NULL ;s=s->h_next)
     //{
     //    cvDrawContours(im_show,s,CV_RGB(255,0,0),CV_RGB(255,0,0),0);
     //}
     //cvShowImage("s",im_show);
     // 3 . 轮廓抽样
     int num = 100;
    CvPoint *samplearray = (CvPoint *)malloc(num * sizeof(CvPoint));
    
    contoursample(contour,samplearray,num);
    
     for ( int i = 0 ; i < num ; ++i)
    {
        cvDrawCircle(im_show,samplearray[i], 3,CV_RGB( 255, 0, 0));
    }
    cvShowImage( "samplepoint",im_show);
     // 4 . 以抽样点的切线作为X轴正方向建立logr-theta 直方图
    
     // 5 . 计算const 找对应点
    free(samplearray);
    cvReleaseMemStorage( &storage);
    cvWaitKey( - 1);
     return 0;
}





转载于:https://www.cnblogs.com/xiaomaLV2/archive/2012/07/16/2593671.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值