轮廓随机均匀采样

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;
}





posted @ 2012-07-16 15:17  小马_xiaoLV2  阅读(1581)  评论(0编辑  收藏  举报