全搜索算法是最简单暴力的一种搜索算法,对搜索范围内的所有像素点都进行匹配对比,选出最合适的运动向量,以下就是一个搜索范围为4的全搜索范围(单个像素点)

 h.264全搜索以及快速全搜索算法

/*!
 ***********************************************************************
 * \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;  //返回最小代价
}
View Code

相关文章:

  • 2022-12-23
  • 2021-07-12
  • 2021-11-16
  • 2021-04-10
  • 2022-02-07
  • 2021-12-15
  • 2021-04-07
猜你喜欢
  • 2022-12-23
  • 2021-09-19
  • 2021-06-09
  • 2021-08-21
  • 2022-02-08
  • 2021-09-03
  • 2021-12-01
相关资源
相似解决方案