你好,没有看懂整个匹配原理和流程,楼主能否讲讲?期待。。
你是指加速的原理吗?大概来讲主要利用了降采样、方向量化、预计算得分、内存重新布局、SIMD加速。具体的话我也不会比linemod论文里讲的更好了。 如果是看不太懂论文,建议可以想想用普通的滑动窗口会怎么做;每一个加速方式可以说就是加速普通流程中的一个环节,大思路都是一样的。
经过测试,模板中有的边缘梯度,测试图像中除有模板有的,还有多余的东西,实际应该是NG,但是判定为OK,对于多余的,应该如何考虑?
不管多余的正是这个方法抗干扰的原因。如果必须没有多余的,由于位置已经确定,后面自己加一个筛选过程就行了
金字塔层数不对应,Detector默认是金字塔层数为2,步长[4,8],在match过程中, for (int l = 0; l < pyramid_levels; ++l) { int T = T_at_level[l]; std::vector<LinearMemories> &lm_level = lm_pyramid[l]; if (l > 0) //l>0应该去除,i=0代表金字塔层1,i=1代表金字塔层2,以此类推 { for(int i = 0; i < (int)quantizers.size(); ++i) quantizers[i]->pyrDown(); } ....... }
这里是降采样,第一层不用,所以需要 l>0
matchClass()函数中关于int offset = lowest_T / 2 + (lowest_T % 2 - 1);中心点吗? (x / T - 8 + best_c) * T + offset如何得来的?
是的,都是中心点。-8是因为第二层金字塔search的范围是16Tx16T,T是stride
第二层不是int lowest_T = T_at_level.back(); //8? SIMILARITY_LUT是如何得到?
我说的第二层是T那个。 LUT就是把每种情况都算一遍。8位的LUT opencv只有结果,具体怎么得到的没有。不过我写过一个16位的: 16位LUT计算参考代码
static void spread(const Mat &src, Mat &dst, int T)中Fill in spread gradient image (section 2.3)是哪部分内容?对这部分不明白
对应论文3.3 就是方向扩散。一个地方可以最多容纳8个方向,预计算的时候找最近的方向比较作为得分
for (int c = 0; c < src.cols; ++c)
{
// Least significant 4 bits of spread image pixel
lsb4_r[c] = src_r[c] & 15; //左四位字节
// Most significant 4 bits, right-shifted to be in [0, 16)
msb4_r[c] = (src_r[c] & 240) >> 4; //右四位字节
}
为什么要这样分?
SIMD指令的限制,_mm_shuffle_epi8一次只能重排16个,所以只能4个字节一段来(2^4=16)
你好,请问下加上icp之后,怎样来计算模型是偏移了多少x/y呢? 比如之前可以用模板去和初始图匹配,得到一个match.x/y,然后再和目标图片匹配得到一个match.x/y,做差得到目标图偏移了多少的结果。 现在icp的结果是要把特征点算到图片位置上,再旋转+平移RegistrationResult的值。结果的角度确实可以直接用RegistrationResult给的,但是平移该怎么去计算修正值呢?谢谢
@oUp2Uo 跟初始图match不太合适,信息已经存在template里了。其实用transform矩阵来看很清楚,整个过程有3步,每一步对于一个transform。第一步是旋转缩放,第二步是crop切黑边(相当于平移),第三步是icp精调,三步的矩阵乘起来角度、平移都有了。 我看这个大家问的比较多,这几天我写个文档说明下吧。
//src:1,2,4,8,16,32,64,128
static void spread(const Mat &src, Mat &dst, int T)
{
dst = Mat::zeros(src.size(), CV_8U);
/*
T={4,8}
以T=4为例
dst[0][0]=src[0][0]|src[0][1]|src[0][2]|src[0][3]|
src[1][0]|src[1][1]|src[1][2]|src[1][3]|
src[2][0]|src[2][1]|src[2][2]|src[2][3]|
src[3][0]|src[3][1]|src[3][2]|src[3][3]|
/
for (int r = 0; r < T; ++r)
for (int c = 0; c < T; ++c)
{
//src.step1():colschannels
orUnaligned8u(&src.at
dst.ptr(),static_cast
SIMILARITY_LUT怎么的出?能说说每个元素的意义吗?
这个很好理解,你可以反过来看src在dst的分布,比如src[0][0]在且仅在dst[0:4][0:4]有,这不就是想要的spread效果吗?(有一个2x2的小平移,不影响) SIMILARITY_LUT在16位方向参考代码里写的很清楚了。 比如用8位方向来注释第24行:
for(int i=0; i<8; i++){ // 8 ori
for(int m=0; m<2; m++){ // 2 seg (2 segment of 4 bits)
for(int n=0; n<16; n++){ // 16 index (2^4(4bits) = 16)
// 8*2*16 = 256, that is SIMILARITY_LUT[256]
@oUp2Uo 跟初始图match不太合适,信息已经存在template里了。其实用transform矩阵来看很清楚,整个过程有3步,每一步对于一个transform。第一步是旋转缩放,第二步是crop切黑边(相当于平移),第三步是icp精调,三步的矩阵乘起来角度、平移都有了。 我看这个大家问的比较多,这几天我写个文档说明下吧。
嗯谢谢楼主。 我按照我前面说的那种方式(就是拿模板和初始图匹配得到一个初始偏移位置,再拿目标图去匹配的结果,求差得到结果),在加了icp之后,基本分值排名1-5的,其实角度差就在0.1范围内,证明icp效果很好……就是平移的那块,不知道怎么算了……
@oUp2Uo 文档写好了
icp不在cuda上运行可以吗?在cpu上运行的效率
@longzeyilang 可以的,默认就是不开cuda。说不定cpu还快点,因为数据量很少,运行时间可能比传到gpu的overhead小。
@meiqua
我设置8个方向的代码,但是得到结果值与SIMILARITY_LUT[256]不一样,代码如下:
#include
- */ const int ORI=8; //8个方向 const int SEG=2; //2个分割 const int INDEX=16; //16索引 struct Node { int value; int prev; int next; };
int main() { std::vector<Node> nodes(ORI); for(int i=0; i<ORI; i++){ nodes[i].value = (1 << i); nodes[i].prev = i-1; nodes[i].next = i+1; } nodes[0].prev = ORI-1; nodes[ORI-1].next = 0;
uint8_t LUT[ORI*SEG*INDEX] = {0};
for(int i=0; i<ORI; i++){ // 16 ori
for(int m=0; m<SEG; m++){ // 4 seg
for(int n=0; n<INDEX; n++){ // 16 index
if(n==0){ // no ori
LUT[n+m*INDEX+i*ORI*SEG] = 0;
continue;
}
int res = (n << (m*SEG));
auto current_node_go_forward = nodes[i];
auto current_node_go_back = nodes[i];
int angle_diff = 0;
while(1){
if((current_node_go_forward.value & res) > 0 ||
(current_node_go_back.value & res) > 0){
break;
}else{
current_node_go_back = nodes[current_node_go_back.prev];
current_node_go_forward = nodes[current_node_go_forward.next];
angle_diff ++;
}
}
LUT[n+m*ORI+i*ORI*SEG] = 4 - angle_diff;
}
}
}
for(int i=0; i<ORI; i++){
for(int m=0; m<SEG*INDEX; m++){
cout << int(LUT[i*SEG*INDEX + m]) << ", ";
}
cout << "\n";
}
return 0;
}
能帮我看看什么原因吗?
简单跑了下,LUT8_gen.cpp
KinectFusion: Real-time 3D Reconstruction and Interaction Using a Moving Depth Camera 搜索不到全文,能上传下吗?
楼主,我发现模板的宽度或者高度小于200,都训练失败,感觉训练成功根模板图像的尺寸有很大关系
@longzeyilang 图像小了点数少选点就行了
如果单纯基于物体边缘轮廓进行定位匹配,能否给点意见?
@longzeyilang 有什么问题吗?