一直不是很理解檢測結果是怎麼出來的,學習最快的方法就是看原始碼啦,今天先從prior box層開始。
這層的作用就是對不同位置的每個特徵點產生不同大小的default box,這些box的大小、形狀由prototxt的prior_box_param來控制。隨便拿出乙個模型的prior box層來舉例:
name: "base_11_priorbox"
type: "priorbox"
bottom: "convndbackward91"
bottom: "data"
top: "base_11_priorbox"
prior_box_param }
然後就來看一下原始碼(caffe_root/src/caffe/layers/prior_box_layer.cpp):
#include
#include
#include
#include
#include "caffe/layers/prior_box_layer.hpp"
namespace caffe
aspect_ratios_.clear();
// 預設加入正方形框
aspect_ratios_.push_back(1.);
flip_ = prior_box_param.flip();
// 從prototxt中讀取長寬比
for (int i = 0; i < prior_box_param.aspect_ratio_size(); ++i)
}if (!already_exist)
}} // 每個畫素的default box的數量
num_priors_ = aspect_ratios_.size() * min_sizes_.size();
// 如果有設定max_size,則測試數值正確後計數,表示最大正方形邊長(sqrt(min_size*max_size))
if (prior_box_param.max_size_size() > 0)
} clip_ = prior_box_param.clip();
if (prior_box_param.variance_size() > 1)
} else
if (prior_box_param.variance_size() == 1) else
// 設定尺寸,一般在prototxt中都不指定,所以預設指定為0
if (prior_box_param.has_img_h() || prior_box_param.has_img_w()) else
if (prior_box_param.has_img_size()) else
// 指定x和y方向的步長,否則預設為0,下面用除法求出縮放比例
if (prior_box_param.has_step_h() || prior_box_param.has_step_w()) else
if (prior_box_param.has_step()) else
// 指定偏移量,一般為0.5,做四捨五入處理,可以看下面用法來理解
offset_ = prior_box_param.offset();
}// 統計一下top的尺寸
template
void priorboxlayer::reshape(const
vector
*>& bottom,
const
vector
*>& top)
template
void priorboxlayer::forward_cpu(const
vector
*>& bottom,
const
vector
*>& top) else
// 指feature map和原圖的比例關係
float step_w, step_h;
if (step_w_ == 0 || step_h_ == 0) else
dtype* top_data = top[0]->mutable_cpu_data();
int dim = layer_height * layer_width * num_priors_ * 4;
int idx = 0;
// 把feature map上的點對映到原圖
for (int h = 0; h < layer_height; ++h)
// 這裡就用到了aspect_ratio引數了,表示長方形的框,可以指定各種比例
// rest of priors
for (int r = 0; r < aspect_ratios_.size(); ++r)
box_width = min_size_ * sqrt(ar);
box_height = min_size_ / sqrt(ar);
// xmin
top_data[idx++] = (center_x - box_width / 2.) / img_width;
// ymin
top_data[idx++] = (center_y - box_height / 2.) / img_height;
// xmax
top_data[idx++] = (center_x + box_width / 2.) / img_width;
// ymax
top_data[idx++] = (center_y + box_height / 2.) / img_height;}}
}} // 對框進行剪裁,不能越影象邊界
// clip the prior's coordidate such that it is within [0, 1]
if (clip_)
} // 看了一些解釋還是不是很懂,先貼上個人感覺講的不錯的解釋
// set the variance.
// 這一句得到的是特徵圖的height*width
top_data += top[0]->offset(0, 1);
if (variance_.size() == 1) else }}
}}}
instantiate_class(priorboxlayer);
register_layer_class(priorbox);
} // namespace caffe
ssd原始碼解析
1 preprocess for eval image預處理 1 tf image whitend rgb通道分別減去影象集統計的畫素均值。2 tf image.resize image 影象縮放成 300,300,3 2 ssd net 1 ssdnet 初始化功能。定義引數 feat layer...
0 SSD演算法原始碼解讀 anchor是如何生成的
ssd演算法中預設框的好壞是非常重要的,好的anchor降低回歸的難度,更容易訓練出更好的模型,下面我們根據pytorch 講講預設框是怎麼生成的,非常簡單,我對 做出必要的說明,希望可以幫助大家理解anchor。注意,以下 所有引數針對 ssd 512 512,至於ssd 300 300等其他大小...
openTLD 原始碼解讀
首先是run tld 在其次就是tldexample 最後到了初始化函式tldinit 第乙個比較關鍵的函式 bb scan 將影象網格化,將首先 scale 1.2.10 10 21 個規格 在每個規格上打網格 這個函式有乙個比較重要的方法 ntuples 就是重複 因為網格上的點很多點有相同的x...