您的位置:首页 > 编程语言

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

2015-06-03 16:18 567 查看
本文为笔者读书笔记,欢迎转载,请注明本博,谢谢。如有不足,请大家多多指教。


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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: