今天看了下xvid的搜索算法,总结一下。
xvid_me_AdvDiamondSearch,顾名思义是高级钻石搜索算法。它所使用的搜索模板是大钻石。
*
* *
* * *
* *
*
(图1)
如图1所示,大钻石搜索模板一共有8个方向:left , right, top, down, left-top, left-down, right-top, right-down
由于图像的坐标系如图2所示:
x -->
y
|
v
(图2)
xvid中将这8个方向分加用以下数字表示
Top(4)
TL(5) TR(6 )
Left(1) Right(2)
DL(9) DR(10)
Down(8)
而这个算法的主要思想是:
bDirection代表sad满足条件的方向,
算法在初始化时,bDirection被设为255,以确保先对left, right, top, down四个方向都进行一遍搜索。然后查看iDirection是否非零,非零则说明有更好的方向,将该方向记录到bDirection中,然后更新坐标(x,y), 再在(x,y)进行与bDirection方向正交的搜索。同样,如果搜到更好的方向,也相应更新bDirection和(x,y)。
如果*iDirection为0
那么说明已经搜索到了一个局部的最小点了。但这个点不一定是全局最小。
所以在退出之前还要在斜线方向上进行搜索(left-top, left-down, right-top, right-down)。
具体搜索哪些方向是要看情况的。
//xvid 高级钻石搜索算法
1 void
2 xvid_me_AdvDiamondSearch(int x, int y, SearchData * const data,
3 int bDirection, CheckFunc * const CheckCandidate)
4 {
5
6 /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
7
8 unsigned int * const iDirection = &data->dir;
9
10 for(;;) { /* forever */
11 *iDirection = 0;
12 if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1); //left
13 if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2); //right
14 if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4); //top
15 if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8); //down
16
17 /* now we're doing diagonal checks near our candidate */
18
19 if (*iDirection) { /* if anything found */
20 bDirection = *iDirection;
21 *iDirection = 0;
22 x = data->currentMV->x; y = data->currentMV->y;
23 if (bDirection & 3) { /* our candidate is left or right */
24 CHECK_CANDIDATE(x, y + iDiamondSize, 8);
25 CHECK_CANDIDATE(x, y - iDiamondSize, 4);
26 } else { /* what remains here is up or down */
27 CHECK_CANDIDATE(x + iDiamondSize, y, 2);
28 CHECK_CANDIDATE(x - iDiamondSize, y, 1);
29 }
30
31 if (*iDirection) {
32 bDirection += *iDirection;
33 x = data->currentMV->x; y = data->currentMV->y;
34 }
35 } else { /* about to quit, eh? not so fast.... */
36 switch (bDirection) { //HKY: bDirection: the best direction
37 case 2:
38 CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
39 CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
40 break;
41 case 1:
42 CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
43 CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
44 break;
45 case 2 + 4:
46 CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
47 CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
48 CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
49 break;
50 case 4:
51 CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
52 CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
53 break;
54 case 8:
55 CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
56 CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
57 break;
58 case 1 + 4:
59 CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
60 CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
61 CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
62 break;
63 case 2 + 8:
64 CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
65 CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
66 CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
67 break;
68 case 1 + 8:
69 CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
70 CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
71 CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
72 break;
73 default: /* 1+2+4+8 == we didn't find anything at all */
74 CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
75 CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
76 CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
77 CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
78 break;
79 }
80 if (!*iDirection) break; /* ok, the end. really */
81 bDirection = *iDirection;
82 x = data->currentMV->x; y = data->currentMV->y;
83 }
84 }
85 }
86