EPZS搜索过程

简介: EPZS(Enhance Predictive Zonal Search) 增强预测区域搜索,是一种整像素运动估计的搜索算法。EPZS采用的是相关性较高的预测方法。这里的相关性较高是指,更多地根据已有的条件,来进行运动向量的预测(如采用相邻块的mv作为当前搜索块的mv进行预测)。

EPZS(Enhance Predictive Zonal Search) 增强预测区域搜索,是一种整像素运动估计的搜索算法。

EPZS采用的是相关性较高的预测方法。这里的相关性较高是指,更多地根据已有的条件,来进行运动向量的预测(如采用相邻块的mv作为当前搜索块的mv进行预测)。

 

Search Set

在搜索范围内的所有mv,可以被归结为集合SS,EPZS会从SS中按照其算法的规律来选择特定的子集SS′。SS′可以包含以下几种搜索方式。

 

1.S1S1,mvp,(0, 0)

mvprev,mv(0,0)mvprev,mv(0,0)

 

 

 

2.S2S2,当前块的相邻块mv,包括ABCD四个mv,co-located块mv,做mv_scale,即对于POC的距离进行比例增减。

mva,mvb,mvc,mvd,mvcomva,mvb,mvc,mvd,mvco

 

 

3.S3S3,这种方式基于第0个参考图像的mv,当前参考图像的mv需要由ref0的mv以POC的距离做mv_scale后得到

mvrefn=mvref0POCcurPOCnPOCcurPOC0mvrefn=mvref0⋅POCcur−POCnPOCcur−POC0

 


 

4.S4S4,以mvp或者(0, 0)为中心,呈正方形窗口的mv集合

mvwindowmvwindow

 

 

5.S5S5,由于运动有可能不是匀速地运动,而是以相同加速度来进行,因此可以用前两张编码图像的mv计算出当前mv

mvcur=mvt1+(mvt1mvt2)mvcur=mvt−1+(mvt−1−mvt−2)

 

 

 

6.S6S6,co-located块的相邻mv,需做mv_scale

mvcola,mvcolb,mvcolc,mvcoldmvcola,mvcolb,mvcolc,mvcold

 

 

7.S7S7,Memory Prediction即采用同一块位置中,上一个块类型(Block type - 1)做预测得到的mv,采用其相邻mv,做mv_scale

mvpreva,mvprevb,mvprevc,mvprevdmvpreva,mvprevb,mvprevc,mvprevd

 

 

8.S8S8,如果采用的是HME(Hierarchical Motion Estimation)分层运动估计的编码方式,那么应该选择该次HME运动估计的参考图像,从参考图像中选择co-located块,以及co-located块周边的块(带col块共9个块)的mv作为候选mv

mvhme_co,mvhme_surround_of_comvhme_co,mvhme_surround_of_co

 

 

 

9.S9S9,上层块mv,做mv_scale

mv4×4=mv8×4,mv8×4=mv8×8,mv4×4=mv8×4,mv8×4=mv8×8,…

 

 

从如上的mv集合明显看出,基本上,如果当前mv是由参考图像已有mv预测出来的情况,都需要进行mv_scale,以此提高mv预测的准确性。

 

在预测完所有mv的可能位置后,得到mv集合SS,由于此处进行的是整像素预测,所以需要对mv求整。接下来需要在SS中求出mv_cost最小的mv,当然,mv需要在search range内。

 

Termination

Termination用于判断当前mv预测是否满足停止条件(mv_cost < stopCriterion),满足则代表当前mv预测已经足够准确,可以退出。

  1. 在求出第一个子集S1S1的mv_cost后,进行第一次Termination,记为T1T1。T1T1是由当前块类型的像素点个数(如16x16像素点个数为256)与lambda联合组成。JM18.6中T1T1,即stopCriterion的值为如下形式:
    stopCriterion=(Npixel×34)×2LAMBDA_ACCURACY_BITS+LAMBDA_DISTstopCriterion=(Npixel×34)×2LAMBDA_ACCURACY_BITS+LAMBDA_DIST
  2. 如果第一个停止条件不能满足,则接下来需要对所有的mv集合进行预测,从中选出mv_cost最小的mv。在得到最小mv后,进行第二次Termination,记为T2T2。T2T2由3块类型的相邻块中最小SAD,用stopCriterionT1stopCriterionT1修正计算得来。
    • 首先定义上界与下界:
      UpperLower=(Npixel×3)×2LAMBDA_ACCURACY_BITS+LAMBDA_DIST=(Npixel×14)×2LAMBDA_ACCURACY_BITS+LAMBDA_DISTUpper=(Npixel×3)×2LAMBDA_ACCURACY_BITS+LAMBDA_DISTLower=(Npixel×14)×2LAMBDA_ACCURACY_BITS+LAMBDA_DIST
    • 上下界修正:
      tmpStopCriterion=Mid(Min(SADA,SADB,SADC),Upper,Lower)tmpStopCriterion=Mid(Min(SADA,SADB,SADC),Upper,Lower)
    • StopCriterion修正:
      stopCriterion=(Max(tmpStopCriterion,stopCriterion)×8+stopCriterion)8+LAMBDA_DISTstopCriterion=(Max(tmpStopCriterion,stopCriterion)×8+stopCriterion)8+LAMBDA_DIST
  3. 如果第二个停止条件仍然不满足,接下来进行最后的小区域搜索,搜索方式有菱形,正方形,大菱形等。如果搜索得到最佳mv为菱形(或正方形)的中心点,则停止搜索,得到最终的最佳整数mv。可以参考http://www.cnblogs.com/TaigaCon/p/3788984.html

 

相对于UMHS,EPZS更多地考虑了运动的相关性,基本上采用的都是用已得到的mv预测当前mv,这种方式在规律运动图像的预测中会比UMHS更有效率。但是UMHS的预测更加考虑周全,对搜索范围进行了更细密的搜索,一旦碰上无规律运动图像,UMHS预测可以得到比EPZS更准确的预测效果。因此,根据图像性质来选择不同的搜索算法将能更好地提升编码质量。

 

jm18.6:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
/*!
***********************************************************************
* \brief
*    FAST Motion Estimation using EPZS
*    AMT/HYC
***********************************************************************
*/
distblk                                            //  ==> minimum motion cost after search
EPZS_motion_estimation (Macroblock * currMB,     // <--  current Macroblock
                           MotionVector * pred_mv,  // <--  motion vector predictor in sub-pel units
                           MEBlock * mv_block,      // <--  motion vector information
                           distblk min_mcost,       // <--  minimum motion cost (cost for center or huge value)
                           int  lambda_factor        // <--  lagrangian parameter for determining motion cost
                           )
{
   Slice *currSlice = currMB->p_Slice;
   VideoParameters *p_Vid = currMB->p_Vid;
   InputParameters *p_Inp = currMB->p_Inp;
   EPZSParameters *p_EPZS = currSlice->p_EPZS;
   PicMotionParams **motion = p_Vid->enc_picture->mv_info;
 
   int  blocktype = mv_block->blocktype;
 
   int  list = mv_block->list;
   int  cur_list = list + currMB->list_offset;
   short  ref = mv_block->ref_idx;
   MotionVector *mv = &mv_block->mv[list];
   SearchWindow *searchRange = &mv_block->searchRange;
   int  mapCenter_x = searchRange->max_x - mv->mv_x;
   int  mapCenter_y = searchRange->max_y - mv->mv_y;
   StorablePicture *ref_picture = currSlice->listX[cur_list][ref];
 
   distblk lambda_dist = weighted_cost(lambda_factor, 2);
   distblk stopCriterion = p_EPZS->medthres[blocktype] + lambda_dist;
   distblk *prevSad = &p_EPZS->distortion[cur_list][blocktype - 1][mv_block->pos_x2];
 
   MotionVector *p_motion = NULL; //only work for EPZSSpatialMem
 
   EPZSStructure *searchPatternF = p_EPZS->searchPattern;
   uint16 **EPZSMap = &p_EPZS->EPZSMap[mapCenter_y];
   uint16 *EPZSPoint = &p_EPZS->EPZSMap[searchRange->max_y][searchRange->max_x];
 
   MotionVector center = pad_MVs (*mv, mv_block);
   MotionVector pred = pad_MVs (*pred_mv, mv_block);
   MotionVector tmp = *mv, cand = center;
 
   ++p_EPZS->BlkCount;
   if  (p_EPZS->BlkCount == 0)
     ++p_EPZS->BlkCount;
 
   if  (p_Inp->EPZSSpatialMem)
   {
#if EPZSREF
     p_motion = &p_EPZS->p_motion[cur_list][ref][blocktype - 1][mv_block->block_y][mv_block->pos_x2];
#else
     p_motion = &p_EPZS->p_motion[cur_list][blocktype - 1][mv_block->block_y][mv_block->pos_x2];
#endif
   }
 
   // Clear EPZSMap
   // memset(EPZSMap[0],FALSE,searcharray*searcharray);
   // Check median candidate;
   //p_EPZS->EPZSMap[0][0] = p_EPZS->BlkCount;
   *EPZSPoint = p_EPZS->BlkCount;
 
   //--- initialize motion cost (cost for motion vector) and check ---
   //(0,0)作为mv
   min_mcost = mv_cost (p_Vid, lambda_factor, &cand, &pred);
 
   //--- add residual cost to motion cost ---
   min_mcost += mv_block->computePredFPel (ref_picture, mv_block, DISTBLK_MAX - min_mcost, &cand);
 
   // Additional threshold for ref>0
   if  ((ref > 0 && currSlice->structure == FRAME) && (*prevSad < distblkmin (p_EPZS->medthres[blocktype] + lambda_dist, min_mcost)))
   { //满足返回条件
#if EPZSREF
     if  (p_Inp->EPZSSpatialMem)
#else
     if  (p_Inp->EPZSSpatialMem && ref == 0)
#endif
     {
       *p_motion = tmp;
     }
     return  min_mcost;
   }
 
   //! If p_EPZS->medthres satisfied, then terminate, otherwise generate Predictors
   //! Condition could be strengthened by consideration distortion of adjacent partitions.
   if  (min_mcost > stopCriterion)
   {
     SPoint *p_EPZS_point = p_EPZS->predictor->point;
     Boolean checkMedian = FALSE;
     distblk second_mcost = DISTBLK_MAX;
     distblk mcost;
     int  prednum = 5;
     int  conditionEPZS;
     MotionVector tmp2 = {0, 0}, tmv;
     int  pos;
     short  invalid_refs = 0;
 
     stopCriterion = EPZSDetermineStopCriterion (p_EPZS, prevSad, mv_block, lambda_dist);
 
     if  (min_mcost < (stopCriterion >> 1))
     {
#if EPZSREF
       if  (p_Inp->EPZSSpatialMem)
#else
       if  (p_Inp->EPZSSpatialMem && ref == 0)
#endif
       {
         *p_motion = tmp;
       }
 
       return  min_mcost;
     }
 
     //! Add Spatial Predictors in predictor list.
     //! Scheme adds zero, left, top-left, top, top-right. Note that top-left adds very little
     //! in terms of performance and could be removed with little penalty if any.
     //当前块相邻mv,做mv_scale
     invalid_refs = EPZS_spatial_predictors (p_EPZS, mv_block,
       list, currMB->list_offset, ref, motion);
 
 
 
     //当前类型的block_type(8x4)的上一个block_type(8x8),相同位置留下来的mv,采用其相邻mv
     /*
      *     
      *   +--------+----+----+                
      *   |        |    B    |                
      *   |        |____A____|                
      *   |        |         |                
      *   |        |         |                
      *   |        +----+----+                
      *   |                  |                
      *   |                  |                
      *   |                  |                
      *   |                  |                
      *   +------------------+                
      *   
      *   B : 8x4    A 8x8
      *     macroblock                     
      *                                    
      *memory_mv_b = surrounding_of_mv_a
      *采用mv_a的相邻mv
      *
      */
     if  (p_Inp->EPZSSpatialMem)
       EPZS_spatial_memory_predictors (p_EPZS, mv_block, cur_list, &prednum, ref_picture->size_x >> 2);
    
     //if (p_Inp->HMEEnable == 1 && p_Inp->EPZSUseHMEPredictors == 1 && blocktype == 4)
     //if (p_Inp->HMEEnable == 1 && p_Inp->EPZSUseHMEPredictors == 1 && (currSlice->slice_type == P_SLICE || currSlice->slice_type == SP_SLICE || p_Inp->EnableReorderBslice) )
     //如果采用HME(Hierarchical Motion Estimate),即B帧的参考图像选择方式有所不同
     //选择此时的分层参考图像(Hierarchical ref pic)对应块的相邻mv
     if  (p_Inp->HMEEnable == 1 && p_Inp->EPZSUseHMEPredictors == 1)
       EPZS_hierarchical_predictors (p_EPZS, mv_block, &prednum, ref_picture, currSlice);
 
#if (MVC_EXTENSION_ENABLE)
     if  ( p_Inp->EPZSTemporal[currSlice->view_id] && blocktype < 5 )
#else
     // Temporal predictors
     //colocate块的相邻块mv
     if  (p_Inp->EPZSTemporal && blocktype < 5)
#endif
     {
       EPZS_temporal_predictors (currMB, ref_picture, p_EPZS, mv_block, &prednum, stopCriterion, min_mcost);
     }
 
     //! Window Size Based Predictors
     //! Basically replaces a Hierarchical ME concept and helps escaping local minima, or
     //! determining large motion variations.
     //! Following predictors can be adjusted further (i.e. removed, conditioned etc)
     //! based on distortion, correlation of adjacent MVs, complexity etc. These predictors
     //! and their conditioning could also be moved after all other predictors have been
     //! tested. Adaptation could also be based on type of material and coding mode (i.e.
     //! field/frame coding,MBAFF etc considering the higher dependency with opposite parity field
     //conditionEPZS = ((min_mcost > stopCriterion)
     // && (p_Inp->EPZSFixed > 1 || (p_Inp->EPZSFixed && currSlice->slice_type == P_SLICE)));
     //conditionEPZS = ((ref == 0) && (blocktype < 5) && (min_mcost > stopCriterion)
     //&& (p_Inp->EPZSFixed > 1 || (p_Inp->EPZSFixed && currSlice->slice_type == P_SLICE)));
     //conditionEPZS = ((min_mcost > stopCriterion) && ((ref < 2 && blocktype < 4)
     conditionEPZS = (p_Inp->EPZSFixed == 3 && (currMB->mb_x == 0 || currMB->mb_y == 0))
       || ((min_mcost > 3 * stopCriterion) && ((ref < 2 && blocktype < 4) || (ref < 1 && blocktype == 4)
       || ((currSlice->structure != FRAME || currMB->list_offset)
       && ref < 3))
       && (p_Inp->EPZSFixed > 1 || (p_Inp->EPZSFixed && currSlice->slice_type == P_SLICE)));
 
     //正方形窗口mv
     if  (conditionEPZS)
       EPZSWindowPredictors (mv, p_EPZS->predictor, &prednum,
       (p_Inp->EPZSAggressiveWindow != 0) || ((blocktype < 5) && (invalid_refs > 2) && (ref < 1 + (currSlice->structure != FRAME || currMB->list_offset)))
       ? p_EPZS->window_predictor_ext : p_EPZS->window_predictor);
 
     //! Blocktype/Reference dependent predictors.
     //! Since already mvs for other blocktypes/references have been computed, we can reuse
     //! them in order to easier determine the optimal point. Use of predictors could depend
     //! on cost,
     //conditionEPZS = (ref == 0 || (ref > 0 && min_mcost > stopCriterion) || currSlice->structure != FRAME || currMB->list_offset);
     conditionEPZS = (ref == 0 || (ref > 0 && min_mcost > 2 * stopCriterion));
 
     //上层宏块mv,做mv_scale
     if  (conditionEPZS && currMB->mbAddrX != 0 && p_Inp->EPZSBlockType)
       EPZSBlockTypePredictorsMB (currSlice, mv_block, p_EPZS_point, &prednum);
 
     //! Check all predictors
     
     //循环内,对所有的cand mv(S1,S2,S3,S4)做cost.取出最佳mv
     for  (pos = 0; pos < prednum; ++pos)
     {
       tmv = p_EPZS_point[pos].motion;
       set_integer_mv(&tmv);
 
       //if (((iabs (tmv.mv_x - mv->mv_x) > searchRange->max_x || iabs (tmv.mv_y - mv->mv_y) > searchRange->max_y)) && (tmv.mv_x || tmv.mv_y))
       if  ((iabs (tmv.mv_x - mv->mv_x) - searchRange->max_x <= 0) && (iabs (tmv.mv_y - mv->mv_y) - searchRange->max_y <= 0))
       {
         EPZSPoint = &EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x];
         if  (*EPZSPoint != p_EPZS->BlkCount)
         {
           *EPZSPoint = p_EPZS->BlkCount;
           cand = pad_MVs (tmv, mv_block);
 
           //--- set motion cost (cost for motion vector) and check ---
           mcost = mv_cost (p_Vid, lambda_factor, &cand, &pred);
 
           if  (mcost < second_mcost)
           {
             mcost += mv_block->computePredFPel (ref_picture, mv_block, second_mcost - mcost, &cand);
 
             //--- check if motion cost is less than minimum cost ---
             if  (mcost < min_mcost)
             {
               tmp2 = tmp;
               tmp = tmv;
               second_mcost = min_mcost;
               min_mcost = mcost;
               checkMedian = TRUE;
             }
             //else if (mcost < second_mcost && (tmp.mv_x != tmv.mv_x || tmp.mv_y != tmv.mv_y))
             else  if  (mcost < second_mcost)
             {
               tmp2 = tmv;
               second_mcost = mcost;
               checkMedian = TRUE;
             }
           }
         }
       }
     }
 
     //! Refine using EPZS pattern if needed
     //! Note that we are using a conservative threshold method. Threshold
     //! could be tested after checking only a certain number of predictors
     //! instead of the full set. Code could be easily modified for this task.
     if  (min_mcost > stopCriterion)
     {
       const  int  mv_range = 10;
       int  patternStop = 0, pointNumber = 0, checkPts, nextLast = 0;
       int  totalCheckPts = 0, motionDirection = 0;
 
       //! Adapt pattern based on different conditions.
       if  (p_Inp->EPZSPattern != 0)
       {
         if  ((min_mcost < stopCriterion + ((3 * p_EPZS->medthres[blocktype]) >> 1)))
         {
           if  ((tmp.mv_x == 0 && tmp.mv_y == 0)
             || (iabs (tmp.mv_x - mv->mv_x) < (mv_range) && iabs (tmp.mv_y - mv->mv_y) < (mv_range)))
             searchPatternF = p_Vid->sdiamond;
           else
             searchPatternF = p_Vid->square;
         }
         else  if  (blocktype > 4 || (ref > 0 && blocktype != 1))
           searchPatternF = p_Vid->square;
         else
           searchPatternF = p_EPZS->searchPattern;
       }
 
       //! center on best predictor
       center = tmp;
 
       for  (;;)
       {
         totalCheckPts = searchPatternF->searchPoints;
         do
         { //循环对得到的最佳mv是做小范围搜索:square,dimond,etc.
           checkPts = totalCheckPts;
           do
           { //循环对小范围进行各个像素点的搜索
             tmv = add_MVs (center, &(searchPatternF->point[pointNumber].motion));
 
             if  (((iabs (tmv.mv_x - mv->mv_x) - searchRange->max_x) <= 0) && ((iabs (tmv.mv_y - mv->mv_y) - searchRange->max_y) <= 0))
             {
               //EPZSMap用于记录当前点是否被搜索过,一旦搜索过,则不再搜索,这样的话就不会跟//! Check all predictors重复了
               EPZSPoint = &EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x];
               if  (*EPZSPoint != p_EPZS->BlkCount)
               {
                 *EPZSPoint = p_EPZS->BlkCount;
                 cand = pad_MVs (tmv, mv_block);
 
                 mcost = mv_cost (p_Vid, lambda_factor, &cand, &pred);
 
                 if  (mcost < min_mcost)
                 {
                   mcost += mv_block->computePredFPel (ref_picture, mv_block, min_mcost - mcost, &cand);
 
                   if  (mcost < min_mcost)
                   {
                     tmp = tmv;
                     min_mcost = mcost;
                     motionDirection = pointNumber;
                   }
                 }
               }
             }
             ++pointNumber;
             if  (pointNumber >= searchPatternF->searchPoints)
               pointNumber -= searchPatternF->searchPoints;
             checkPts--;
           }
           while  (checkPts > 0);
           
           //对得到的最佳mv,如果是center(第一次的center是mvp),则停止当前循环
           if  (nextLast || ((tmp.mv_x == center.mv_x) && (tmp.mv_y == center.mv_y)))
           {
             patternStop = searchPatternF->stopSearch;
             searchPatternF = searchPatternF->nextpattern;
             totalCheckPts = searchPatternF->searchPoints;
             nextLast = searchPatternF->nextLast;
             motionDirection = 0;
             pointNumber = 0;
           }
           else
           {
             totalCheckPts = searchPatternF->point[motionDirection].next_points;
             pointNumber = searchPatternF->point[motionDirection].start_nmbr;
             center = tmp;
           }
         }
         while  (patternStop != 1);
 
         if  ((ref > 0) && (currSlice->structure == FRAME)
           && ((4 * *prevSad < min_mcost) || ((3 * *prevSad < min_mcost) && (*prevSad <= stopCriterion))))
         {
           *mv = tmp;
#if EPZSREF
           if  (p_Inp->EPZSSpatialMem)
#else 
           if  (p_Inp->EPZSSpatialMem && ref == 0)
#endif 
           {
             *p_motion = tmp;
           }
 
           return  min_mcost;
         }
 
         //! Check Second best predictor with EPZS pattern
         conditionEPZS = (checkMedian == TRUE)
           && ((currSlice->slice_type == P_SLICE) || (blocktype < 5))
           && (min_mcost > stopCriterion) && (p_Inp->EPZSDual > 0);
 
         if  (!conditionEPZS)
           break ;
         //如果上方条件有多于0个不满足的,则退出循环
         //退出条件1:  EPZSDual = 0 ,即循环只需要执行一次
         //        2:  cost足够小了
         //        3:  blocktypc = 5,6,7
         //        4:  不为P_SLICE
         //        5:  checkMedian = false,即由于EPZSDual,而执行完了第二次
 
         pointNumber = 0;
         patternStop = 0;
         motionDirection = 0;
         nextLast = 0;
 
         if  ((tmp.mv_x == 0 && tmp.mv_y == 0) || (tmp.mv_x == mv->mv_x && tmp.mv_y == mv->mv_y))
         {
           if  (iabs (tmp.mv_x - mv->mv_x) < (mv_range) && iabs (tmp.mv_y - mv->mv_y) < (mv_range))
             searchPatternF = p_Vid->sdiamond;
           else
             searchPatternF = p_Vid->square;
         }
         else
           searchPatternF = p_EPZS->searchPatternD;
 
         //! Second best. Note that following code is identical as for best predictor.
         //由于EPZSDual > 0,开启第二次循环,以原点(当前mv_block所在坐标)为中心,开始搜索
         center = tmp2;
         checkMedian = FALSE;
       }
     }
   }
 
   if  ((ref == 0) || (*prevSad > min_mcost))
     *prevSad = min_mcost;
#if EPZSREF
   if  (p_Inp->EPZSSpatialMem)
#else 
   if  (p_Inp->EPZSSpatialMem && ref == 0)
#endif 
   {
     *p_motion = tmp;
     //printf("value %d %d %d %d\n", p_motion->mv_x, p_motion->mv_y, p_motion[cur_list][ref][0][0][0].mv_x, p_motion[list + list_offset][ref][0][0][0].mv_y);
     //printf("xxxxx %d %d %d %d\n", p_motion->mv_x, p_motion->mv_y, p_motion[cur_list][ref][blocktype - 1][mv_block->block_y][pic_pix_x2].mv_x, p_motion[cur_list][ref][blocktype - 1][mv_block->block_y][pic_pix_x2].mv_y);
   }
 
   *mv = tmp;
 
   return  min_mcost;
}

View Code

相关文章
|
2月前
|
存储 搜索推荐 安全
Onlyfans如何使用搜索功能?Onlyfans如何搜索博主?如何在OnlyFans搜索HongkongDoll
本文是一份全面的指南,旨在帮助读者了解如何在OnlyFans平台上有效使用搜索功能,尤其是如何找到特定的博主,比如HongkongDoll。我们深入探讨了OnlyFans的搜索机制,包括其对用户隐私的重视以及因此带来的搜索限制。文章详细介绍了三种主要的搜索方法:使用OnlyFans的官方搜索服务、通过社交媒体链接进行跳转、以及利用第三方搜索引擎如OnlySearch。
311 3
|
3月前
|
人工智能 开发工具 git
语义搜索测试
语义搜索测试
28 0
|
11月前
|
小程序 数据库
小程序搜索功能,云开发搜索,小程序云开发模糊搜索,同时搜索多个字段
小程序搜索功能,云开发搜索,小程序云开发模糊搜索,同时搜索多个字段
242 0
|
存储 并行计算 算法
秒懂算法 | 搜索基础
本篇介绍了BFS和DFS的概念、性质、模板代码。
114 0
秒懂算法 | 搜索基础
|
移动开发 算法
秒懂算法 | A*搜索
本篇内容包括了A*搜索算法的原理精解以及2个例题。
245 1
秒懂算法 | A*搜索
|
前端开发 小程序 关系型数据库
小程序中实现搜索功能
小程序中实现搜索功能
小程序中实现搜索功能
|
自然语言处理 小程序 搜索推荐
小程序搜索服务优化最佳实践
小程序的诞生大大缩短了操作步骤以及省去了APP之间的切换成本,如何提升用户体验,促使更多流量变现,是大部分开发者们不断探索优化的方向。本文透过小程序“搜索服务的优化”的角度,结合了阿里云开放搜索的最佳实践,解读如何2步实现一站式高质量搜索体验~
3276 0
小程序搜索服务优化最佳实践
|
人工智能 安全 关系型数据库
【技巧】我是如何 "搜索" 到想要的信息的
关于“搜索”资源的一些见解
770 0
EPZS搜索过程
EPZS(Enhance Predictive Zonal Search) 增强预测区域搜索,是一种整像素运动估计的搜索算法。 EPZS采用的是相关性较高的预测方法。这里的相关性较高是指,更多地根据已有的条件,来进行运动向量的预测(如采用相邻块的mv作为当前搜索块的mv进行预测)。
918 0

热门文章

最新文章