opencv源码解读读书笔记:负样本的有关源代码

本文为笔者读书笔记,欢迎转载,请注明本博,谢谢。如有不足,请大家多多指教。大笑

1 CvBackgrounData和CvBackgroundReader

/*
 *存放负样本文件的结构体
 */
typedef struct CvBackgroundData
{
    int    count;              //负样本的数量
    char** filename;           //负样本的文件名包括绝对路径和扩展名
    int    last;
    int    round;
    CvSize winsize;            //大小
} CvBackgroundData;


/*
 *在训练过程中,由于负样本的大小不一定是等于正样本的(必须是大于等于正样本),
 *所以在训练过程中,需要抠出与正样本一样大的ROI区域,就是该结构体表示roi区域
 */
typedef struct CvBackgroundReader{ CvMat src; //未处理的负样本原图像
                                   CvMat img; //扣取的负样本 
                                   CvPoint offset; //扣取负样本的左上角的坐标 
                                   float scale; //代表了缩放的比例
                                   float scalefactor; //不知道为什么两个缩放因子 
                                   float stepfactor; 
                                   CvPoint point;
                                 } CvBackgroundReader

2 icvGetBackgroundImage


/* 
 *icvGetBackgroundImage获取负样本,训练的负样本可以比正样本大
 *但是该函数索取的负样本是在负样本中取得跟正样本一样大的区域
 */
static void icvGetBackgroundImage( CvBackgroundData* data, //如上所示
                                   CvBackgroundReader* reader, CvMat* img )
 { CvMat mat; 
assert( data != NULL && reader != NULL && img != NULL ); 
assert( CV_MAT_TYPE( img->type ) == CV_8UC1 ); 
assert( img->cols == data->winsize.width ); 
assert( img->rows == data->winsize.height ); 
/*在if中的reader->img.data.ptr 这个data与CvBackgroundData* data中的data是不一样的
*reader->img.data.ptr:这个data是个union(共同体),data中的ptr存储的是data数据的第一个元素。
*CvBackgroundData* data:如上所示
 */
 if( reader->img.data.ptr == NULL ) //含义是如果reader读入的图片的数据为空 
{
 icvGetNextFromBackgroundData( data, reader ); 
} mat = cvMat( data->winsize.height, data->winsize.width, CV_8UC1 );
 cvSetData(&mat, (void*) (reader->img.data.ptr + reader->point.y * reader->img.step + reader->point.x * sizeof( uchar )), reader->img.step ); cvCopy( &mat, img, 0 );
//若负样本图像很大,我们可以在一幅图中不断调整切割的位置
    //直至遍历完整个图像
    //沿x方向移动
    if( (int) ( reader->point.x + (1.0F + reader->stepfactor ) * data->winsize.width )
            < reader->img.cols )
    {
        reader->point.x += (int) (reader->stepfactor * data->winsize.width);
    }

    else
    {    //置为x.offset(相当于x方向移动不下去了,按y方向移动)
        reader->point.x = reader->offset.x;

        //延y方向移动
        if( (int) ( reader->point.y + (1.0F + reader->stepfactor ) * data->winsize.height )
                < reader->img.rows )
        {
            reader->point.y += (int) (reader->stepfactor * data->winsize.height);
        }
        else
        {
            reader->point.y = reader->offset.y;
            reader->scale *= reader->scalefactor;
            if( reader->scale <= 1.0F )
            {
                reader->img = cvMat( (int) (reader->scale * reader->src.rows),
                                     (int) (reader->scale * reader->src.cols),
                                      CV_8UC1, (void*) (reader->img.data.ptr) );
                cvResize( &(reader->src), &(reader->img) );
            }
            else
            {
                icvGetNextFromBackgroundData( data, reader );
            }
        }
    }
}





 3  icvGetNextFromBackgroundData 

有些代码我还没有看懂,不敢乱注释,以免误导大家,请友友们见谅哈

/*
 *icvGetNextFromBackgroundData
 *功能:将负样本的属性信息存放在reader中,属性信息有负样本的长,宽,数量等
 */ 
static
void icvGetNextFromBackgroundData( CvBackgroundData* data,
                                   CvBackgroundReader* reader )
{
    IplImage* img = NULL;
    char* filename = NULL;
    size_t datasize = 0;
    int round = 0;
    int i = 0;
    CvPoint offset = cvPoint(0,0);

    assert( data != NULL && reader != NULL );

    if( reader->src.data.ptr != NULL )
    {
        cvFree( &(reader->src.data.ptr) );
        reader->src.data.ptr = NULL;
    }
    if( reader->img.data.ptr != NULL )
    {
        cvFree( &(reader->img.data.ptr) );
        reader->img.data.ptr = NULL;
    }

#ifdef _OPENMP
    #pragma omp critical(c_background_data)
    #endif /* _OPENMP */
    {
        for( i = 0; i < data->count; i++ )
        {
            round = data->round;

//#ifdef CV_VERBOSE 
//           printf( "Open background image: %s\n", data->filename[data->last] );
//#endif /* CV_VERBOSE */
          
            img = cvLoadImage( data->filename[data->last++], 0 );
            if( !img )
                continue;
            data->round += data->last / data->count;
            data->round = data->round % (data->winsize.width * data->winsize.height);
            data->last %= data->count; 

            offset.x = round % data->winsize.width;
            offset.y = round / data->winsize.width;

            offset.x = MIN( offset.x, img->width - data->winsize.width );
            offset.y = MIN( offset.y, img->height - data->winsize.height );
            
            if( img != NULL && img->depth == IPL_DEPTH_8U && img->nChannels == 1 &&
                offset.x >= 0 && offset.y >= 0 )
            {
                break;
            }
            if( img != NULL )
                cvReleaseImage( &img );
            img = NULL;
        }
    }

  if( img == NULL )
    {
        /* no appropriate image */

#ifdef CV_VERBOSE
        printf( "Invalid background description file.\n" );
#endif /* CV_VERBOSE */

        assert( 0 );
        exit( 1 );
    }
    datasize = sizeof( uchar ) * img->width * img->height;
    reader->src = cvMat( img->height, img->width, CV_8UC1, (void*) cvAlloc( datasize ) );
    cvCopy( img, &reader->src, NULL );
    cvReleaseImage( &img );
    img = NULL;

    //reader->offset.x = round % data->winsize.width;
    //reader->offset.y = round / data->winsize.width;
    reader->offset = offset;
    reader->point = reader->offset;
    reader->scale = MAX(
        ((float) data->winsize.width + reader->point.x) / ((float) reader->src.cols),
        ((float) data->winsize.height + reader->point.y) / ((float) reader->src.rows) );
    
    //将负样本大小放缩到包含正样本大小的最小尺寸
    reader->img = cvMat( (int) (reader->scale * reader->src.rows + 0.5F),
                         (int) (reader->scale * reader->src.cols + 0.5F),
                          CV_8UC1, (void*) cvAlloc( datasize ) );
    cvResize( &(reader->src), &(reader->img) );
}



也有人说这是个抠图的过程,比如http://blog.csdn.net/longzaitianya1989/article/details/8174768

具体抠图过程为:
1)  确定抠图区域的左上角坐标(Point.x, Point.y)
2)  确定一个最小缩放比例,使得原负样本图像缩放后恰好包含选中负样本区域
3)  对原负样本图象按计算好的缩放比例进行缩放
4)  在缩放后的图像上抠出负样本

如图:

本图选自http://blog.csdn.net/lampqiu/article/details/40188763


 

 

参考内容:

1 《学习opencv》于仕琪

2  http://blog.csdn.net/lampqiu/article/details/40188763

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值