转:http://www.cvchina.info/2011/09/25/orb-test/
之前介绍了ORB,一种具备旋转不变形的局部特征描述子。OpenCV2.3中提供了实现,但是缺少使用例程。下面是一个简单的样例程序。
随便拍了两张图片作为测试图像。
下面上下两图分别为模板图像和查询图像:
提取左右图特征:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Mat
Mat
//GaussianBlur(img1,
//GaussianBlur(img2,
<a
"http://www.cvchina.info/tag/orb/"
=
"st_tag
"tag"
"标签
>ORB</a>
"http://www.cvchina.info/tag/orb/"
=
"st_tag
"tag"
"标签
>ORB</a>::CommonParams(1.2,
<a
"http://www.cvchina.info/tag/orb/"
=
"st_tag
"tag"
"标签
>ORB</a>
"http://www.cvchina.info/tag/orb/"
=
"st_tag
"tag"
"标签
>ORB</a>::CommonParams(1.2,
vector
Mat
<a
"http://www.cvchina.info/tag/orb/"
=
"st_tag
"tag"
"标签
>orb</a>1(img1,
false
);
printf
(
"tem
,
int64
st
<a
"http://www.cvchina.info/tag/orb/"
=
"st_tag
"tag"
"标签
>orb</a>2(img2,
false
);
et
printf
(
"<a
http:
//www.cvchina.info/tag/orb/"
printf
(
"query
,
|
注:模板图像在多尺度提取特征,查询图像只在提取原始尺度上的特征。
做穷举式的最近邻检索:
1 2 3 4 5 6 7 8 9 10 11 |
//
vector
st
//for(int
naive_nn_search2(keys1,
//}
et
printf
(
"match
,
double
)cvGetTickFrequency()/1000.);
printf
(
"matchs
,
|
hamming距离测算通过查找表实现:
1 2 3 4 5 6 7 8 |
unsigned
int
char
*
char
*
size_t
{
HammingLUT
unsigned
int
result
return
}
|
绘图:
1 2 3 4 5 6 |
Mat
drawMatches(img2,
string
"Matches"
;
namedWindow(
imshow(
waitKey();
|
估计单应矩阵,计算重投影误差:
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 |
Mat
st
homo
et
printf
(
"ransac
,
double
)cvGetTickFrequency()/1000.);
printf
(
"homo\n"
"%f
"%f
"%f
,
homo.at(0,0),
homo.at(1,0),
homo.at(2,0),homo.at(2,1),homo.at(2,2));
vector
reproj;
reproj.resize(pt1.size());
perspectiveTransform(pt1,
Mat
diff
int
double
for
(
int
float
*
float
if
(err
inlier++;
err_sum
sqrt
(err);
}
}
printf
(
"inlier
,
printf
(
"ratio
,
float
)(diff.rows));
printf
(
"mean
,
|
结果分析:
tem feat num: 743
orb2 extraction time: 1.672435
query feat num: 100
match time: 3.698276
matchs num: 8
ransac time: 143.570586
homo
0.974942 0.410833 4.426035
-0.182418 0.828115 52.742661
0.001191 0.000144 1.000000
inlier num: 8
ratio 1.000000
mean reprojection error: 0.976777
可见最近邻检索是系统的瓶颈,(进行了743*100次hamming距离(32bytes)计算。)一个简单的优化如下,分段计算hamming距离,先计算前16byte的hamming距离,如超过某一阈值,则直接认为非候选,如小于某阈值,则继续进行后一半16bytes的距离计算。(粗略估计可以减少30%+的最近邻查询时间)。更复杂的办法是使用LSH,此处按下不提,有空再续。
完整代码如下:
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 |
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
using
char
*
"apple_vinegar_0.png"
;
char
*
"apple_vinegar_2.png"
;
unsigned
int
int
int
{
unsigned
int
//
while
(val)
{
++dist;
val
}
return
}
unsigned
int
char
*
char
*
size_t
{
HammingLUT
unsigned
int
result
return
}
void
vector&
vector&
{
for
(
int
int
)keys2.size();
unsigned
int
int
unsigned
char
*
for
(
int
int
)keys1.size();
unsigned
char
*
unsigned
int
if
(dist
min_dist
min_idx
}
}
//if(min_dist
if
(min_dist
matches.push_back(DMatch(i,
float
)min_dist));
}
}
}
void
vector&
vector&
{
for
(
int
int
)keys2.size();
unsigned
int
unsigned
int
int
unsigned
char
*
for
(
int
int
)keys1.size();
unsigned
char
*
unsigned
int
if
(dist
sec_dist
sec_idx
min_dist
min_idx
}
else
(dist
sec_dist
sec_idx
}
}
if
(min_dist
int
)(sec_dist
//if(min_dist
matches.push_back(DMatch(i,
float
)min_dist));
}
}
}
int
int
char
*
{
Mat
Mat
//GaussianBlur(img1,
//GaussianBlur(img2,
ORB
ORB
vector
Mat
orb1(img1,
false
);
printf
(
"tem
,
int64
st
orb2(img2,
false
);
et
printf
(
"orb2
,
double
)cvGetTickFrequency()/1000.);
printf
(
"query
,
//
vector
st
//for(int
naive_nn_search2(keys1,
//}
et
printf
(
"match
,
double
)cvGetTickFrequency()/1000.);
printf
(
"matchs
,
Mat
drawMatches(img2,
string
"Matches"
;
namedWindow(
imshow(
waitKey();
vector
pt1;
vector
pt2;
for
(
int
int
)matches.size();
pt1.push_back(Point2f(keys2[matches[i].queryIdx].pt.x,
pt2.push_back(Point2f(keys1[matches[i].trainIdx].pt.x,
}
Mat
st
homo
et
printf
(
"ransac
,
double
)cvGetTickFrequency()/1000.);
printf
(
"homo\n"
"%f
"%f
"%f
,
homo.at(0,0),
homo.at(1,0),
homo.at(2,0),homo.at(2,1),homo.at(2,2));
vector
reproj;
reproj.resize(pt1.size());
perspectiveTransform(pt1,
Mat
diff
int
double
for
(
int
float
*
float
if
(err
inlier++;
err_sum
sqrt
(err);
}
}
printf
(
"inlier
,
printf
(
"ratio
,
float
)(diff.rows));
printf
(
"mean
,
return
}
|