全搜索算法是最简单暴力的一种搜索算法,对搜索范围内的所有像素点都进行匹配对比,选出最合适的运动向量,以下就是一个搜索范围为4的全搜索范围(单个像素点)
/*! *********************************************************************** * \brief按照螺旋搜索顺序进行全搜索 * Full pixel block motion search * 目标是得到(mv_x,mv_y)和min_mcost,(mv_x,mv_y)指示从哪里开始做分像素搜索,search center * 后者用来跟分像素搜索结果做比较 *********************************************************************** */ int // ==> minimum motion cost after search FullPelBlockMotionSearch (pel_t** orig_pic, // <-- original pixel values for the AxB block int ref, // <-- reference frame (0... or -1 (backward)) int list, int pic_pix_x, // <-- absolute x-coordinate of regarded AxB blockAxB宏块原点在图像中的绝对坐标 int pic_pix_y, // <-- absolute y-coordinate of regarded AxB block int blocktype, // <-- block type (1-16x16 ... 7-4x4) int pred_mv_x, // <-- motion vector predictor (x) in sub-pel units int pred_mv_y, // <-- motion vector predictor (y) in sub-pel units int* mv_x, // <--> in: search center (x) / out: motion vector (x) - in pel units int* mv_y, // <--> in: search center (y) / out: motion vector (y) - in pel units int search_range, // <-- 1-d search range in pel units int min_mcost, // <-- minimum motion cost (cost for center or huge value) double lambda) // <-- lagrangian parameter for determining motion cost { int pos, cand_x, cand_y, y, x4, mcost; pel_t *orig_line, *ref_line; pel_t *(*get_ref_line)(int, pel_t*, int, int, int, int);// //参考帧偏移量 帧场自适应且宏块地址为偶数=4 帧场自适应宏块地址为奇数=2 非帧场自适应=0 int list_offset = ((img->MbaffFrameFlag)&&(img->mb_data[img->current_mb_nr].mb_field))? img->current_mb_nr%2 ? 4 : 2 : 0; pel_t *ref_pic = listX[list+list_offset][ref]->imgY_11; int img_width = listX[list+list_offset][ref]->size_x; int img_height = listX[list+list_offset][ref]->size_y; int best_pos = 0; // position with minimum motion cost //计算最大需要搜索的位置个数 int max_pos = (2*search_range+1)*(2*search_range+1); // number of search positions int lambda_factor = LAMBDA_FACTOR (lambda); // factor for determining lagragian motion cost int blocksize_y = input->blc_size[blocktype][1]; // vertical block size int blocksize_x = input->blc_size[blocktype][0]; // horizontal block size int blocksize_x4 = blocksize_x >> 2; // horizontal block size in 4-pel units int pred_x = (pic_pix_x << 2) + pred_mv_x; // predicted position x (in sub-pel units)1/4子像素为单位的预测MV int pred_y = (pic_pix_y << 2) + pred_mv_y; // predicted position y (in sub-pel units) int center_x = pic_pix_x + *mv_x; // center position x (in pel units) int center_y = pic_pix_y + *mv_y; // center position y (in pel units) int check_for_00 = (blocktype==1 && !input->rdopt && img->type!=B_SLICE && ref==0); //===== set function for getting reference picture lines ===== //通过判断搜索范围会不会出界,设置获取参考像素值的函数 if ((center_x > search_range) && (center_x < img->width -1-search_range-blocksize_x) && (center_y > search_range) && (center_y < img->height-1-search_range-blocksize_y) ) { get_ref_line = FastLineX;//未出界 } else { get_ref_line = UMVLineX;//出界 } //===== loop over all search positions ===== //max_pos是搜索位置的个数,计算见上面 for (pos=0; pos<max_pos; pos++) { //--- set candidate position (absolute position in pel units) --- /*(center_x,center_y)是由预测MV估计出来的搜索中心,在以它为中心的范围内, 对按照螺旋形顺序排列的候选点进行搜索, 每个候选点都是一个可能参考块的左上角起始点 */ cand_x = center_x + spiral_search_x[pos];//螺旋搜索 cand_y = center_y + spiral_search_y[pos]; //--- initialize motion cost (cost for motion vector) and check --- //计算MVD的代价,换算成四分之一像素(cand--candidate候选点) mcost = MV_COST (lambda_factor, 2, cand_x, cand_y, pred_x, pred_y); if (check_for_00 && cand_x==pic_pix_x && cand_y==pic_pix_y) {//螺旋搜索到的点为原点,不过为什么是减去16bit? mcost -= WEIGHTED_COST (lambda_factor, 16); } //如果只是MV的代价就已经大于现有的最小代价就舍弃 if (mcost >= min_mcost) continue; //--- add residual cost to motion cost --- //blocksize_y blocksize_x4 是分块大小16x16 16x8 8x16...... for (y=0; y<blocksize_y; y++) { //(cand_x,cand_y+y)是一行的起始坐标,y++ 遍历每一行 ref_line = get_ref_line (blocksize_x, ref_pic, cand_y+y, cand_x, img_height, img_width); orig_line = orig_pic [y]; //计算当前帧和参考帧的像素残差 for (x4=0; x4<blocksize_x4; x4++) //以4个为一组计算 { mcost += byte_abs[ *orig_line++ - *ref_line++ ]; mcost += byte_abs[ *orig_line++ - *ref_line++ ]; mcost += byte_abs[ *orig_line++ - *ref_line++ ]; mcost += byte_abs[ *orig_line++ - *ref_line++ ]; } if (mcost >= min_mcost) //如果已经比最小代价大,就没必要计算下面的行了 { break; } } //--- check if motion cost is less than minimum cost --- //记录下最小代价和最佳匹配位置 if (mcost < min_mcost) { best_pos = pos; min_mcost = mcost; } } //===== set best motion vector and return minimum motion cost ===== if (best_pos) { *mv_x += spiral_search_x[best_pos]; //因为螺旋搜索数组中记录的是该位置的点 *mv_y += spiral_search_y[best_pos]; //与(center_x,center_y)的差 } return min_mcost; //返回最小代价 }