語義分割學習筆記(三)——SegNet Upsample層解析
1 引數設定
可設定引數為:message UpsampleParameter { // DEPRECATED. No need to specify upsampling scale factors when // exact output shape is given by upsample_h, upsample_w parameters. optional uint32 scale = 1 [default = 2]; // DEPRECATED. No need to specify upsampling scale factors when // exact output shape is given by upsample_h, upsample_w parameters. optional uint32 scale_h = 2; // DEPRECATED. No need to specify upsampling scale factors when // exact output shape is given by upsample_h, upsample_w parameters. optional uint32 scale_w = 3; // DEPRECATED. Specify exact output height using upsample_h. This // parameter only works when scale is 2 optional bool pad_out_h = 4 [default = false]; // DEPRECATED. Specify exact output width using upsample_w. This // parameter only works when scale is 2 optional bool pad_out_w = 5 [default = false]; optional uint32 upsample_h = 6; optional uint32 upsample_w = 7; }
scale
scale_h scale_w
pad_out_hpad_out_w
upsample_hupsample_w
2 top層特徵圖大小計算
(1)先判斷是否指定 upsample_hupsample_w,如果指定,大小為指定大小,否則(2)
(2)判斷是否指定 scale_h, 如果未指定, scale_h_ = scale_w_ = scale,否則(3)
(3)scale_h_ = scale_h scale_w_=scale_w
只有scale_h_ = scale_w_ =2時,才可以指定pad_out_h,pad_out_w,否則錯誤,如果是(2)(3)則top特徵圖大小為:
upsample_h_ = bottom[0]->height() * scale_h_ - int(pad_out_h)
upsample_w_ = bottom[0]->width() * scale_w_ - int(pad_out_w)
注:
(1)如果輸入影象的高和寬不是32的整數倍,需要指定upsample_h, upsample_w的大小,不然會出現維度不一致的錯誤,原因是upsample需要藉助編碼過程中pool層的位置資訊,例如: pool前特徵圖大小為45, pool後為23,如果直接對23 unsample, 其大小為46, 而pool產生的位置圖大小為45,造成upsample時大小不一致;
(2)指定upsample_h upsample_w的大小時,需要根據編碼過程中對應pool特徵圖的大小,來設定upsample的大小,例如樣例proto中輸入影象大小為480*360, 以360分析:360—pool1(180)—pool2 (90)—pool3 (45)—pool4(23)—pool5(12), upsample5需要藉助pool4位置資訊,需要與pool4大小一致,因此upsamle_h=23 ~
3 原始碼
#include <algorithm>
#include <cfloat>
#include <vector>
#include <iostream>
#include "caffe/layers/upsample_layer.hpp"
namespace caffe {
template <typename Dtype>
void UpsampleLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
UpsampleParameter upsample_param = this->layer_param_.upsample_param();
CHECK((upsample_param.has_upsample_h() && upsample_param.has_upsample_w())
|| (!upsample_param.has_scale() && upsample_param.has_scale_h()
&& upsample_param.has_scale_w())
|| (!upsample_param.has_scale_h() && !upsample_param.has_scale_w()))
<< "upsample_h & upsample_w are required, else (DEPRECATED) "
<< "scale OR scale_h & scale_w are required.";
if (upsample_param.has_upsample_h() && upsample_param.has_upsample_w()) {
upsample_h_ = upsample_param.upsample_h(); //根據upsample_h upsample_w引數設定
upsample_w_ = upsample_param.upsample_w();
CHECK_GT(upsample_h_, 1);
CHECK_GT(upsample_w_, 1);
} else {
LOG(INFO) << "Params 'pad_out_{}_' are deprecated. Please declare upsample"
<< " height and width useing the upsample_h, upsample_w parameters.";
if (!upsample_param.has_scale_h()) { //根據scale設定 沒有scale_h直接根據scale設定
scale_h_ = scale_w_ = upsample_param.scale();
CHECK_GT(scale_h_, 1);
} else {
scale_h_ = upsample_param.scale_h();
scale_w_ = upsample_param.scale_w();
CHECK_GT(scale_h_, 1);
CHECK_GT(scale_w_, 1);
}
pad_out_h_ = upsample_param.pad_out_h();
pad_out_w_ = upsample_param.pad_out_w();
CHECK(!pad_out_h_ || scale_h_ == 2) //只有scale_h scale_w=2時,才可以指定
<< "Output height padding compensation requires scale_h == 2, otherwise "
<< "the output size is ill-defined.";
CHECK(!pad_out_w_ || scale_w_ == 2)
<< "Output width padding compensation requires scale_w == 2, otherwise "
<< "the output size is ill-defined.";
upsample_h_ = upsample_w_ = -1; // flag to calculate in Reshape
}
}
template <typename Dtype>
void UpsampleLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
CHECK_EQ(4, bottom[0]->num_axes()) << "Input must have 4 axes, "
<< "corresponding to (num, channels, height, width)";
CHECK_EQ(4, bottom[1]->num_axes()) << "Input mask must have 4 axes, "
<< "corresponding to (num, channels, height, width)";
CHECK_EQ(bottom[0]->num(), bottom[1]->num());
CHECK_EQ(bottom[0]->channels(), bottom[1]->channels());
CHECK_EQ(bottom[0]->height(), bottom[1]->height());
CHECK_EQ(bottom[0]->width(), bottom[1]->width());
if (upsample_h_ <= 0 || upsample_w_ <= 0) {
upsample_h_ = bottom[0]->height() * scale_h_ - int(pad_out_h_); // upsample_h_ = height*scale-pad_out
upsample_w_ = bottom[0]->width() * scale_w_ - int(pad_out_w_);
}
top[0]->Reshape(bottom[0]->num(), bottom[0]->channels(), upsample_h_,
upsample_w_);
channels_ = bottom[0]->channels();
height_ = bottom[0]->height();
width_ = bottom[0]->width();
}
template <typename Dtype>
void UpsampleLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
const Dtype* bottom_data = bottom[0]->cpu_data();
const Dtype* bottom_mask_data = bottom[1]->cpu_data();
Dtype* top_data = top[0]->mutable_cpu_data();
// Initialize
const int top_count = top[0]->count();
caffe_set(top_count, Dtype(0), top_data);
// The main loop
for (int n = 0; n < bottom[0]->num(); ++n) {
for (int c = 0; c < channels_; ++c) {
for (int i = 0; i < height_ * width_; ++i) {
const int idx = static_cast<int>(bottom_mask_data[i]);
if (idx >= upsample_h_ * upsample_w_) {
// this can happen if the pooling layer that created the input mask
// had an input with different size to top[0]
LOG(FATAL) << "upsample top index " << idx << " out of range - "
<< "check scale settings match input pooling layer's "
<< "downsample setup";
}
top_data[idx] = bottom_data[i];
}
// compute offset
bottom_data += bottom[0]->offset(0, 1);
bottom_mask_data += bottom[1]->offset(0, 1);
top_data += top[0]->offset(0, 1);
}
}
}
template <typename Dtype>
void UpsampleLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
if (propagate_down[0]) {
const Dtype* top_diff = top[0]->cpu_diff();
const Dtype* bottom_mask_data = bottom[1]->cpu_data();
Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
const int bottom_count = bottom[0]->count();
caffe_set(bottom_count, Dtype(0), bottom_diff);
// The main loop
for (int n = 0; n < bottom[0]->num(); ++n) {
for (int c = 0; c < channels_; ++c) {
for (int i = 0; i < height_ * width_; ++i) {
const int idx = static_cast<int>(bottom_mask_data[i]);
if (idx >= height_ * width_ * scale_h_ * scale_w_) {
// this can happen if the pooling layer that created
// the input mask had an input with different size to top[0]
LOG(FATAL) << "upsample top index " << idx << " out of range - "
<< "check scale settings match input pooling layer's downsample setup";
}
bottom_diff[i] = top_diff[idx];
}
// compute offset
bottom_diff += bottom[0]->offset(0, 1);
bottom_mask_data += bottom[1]->offset(0, 1);
top_diff += top[0]->offset(0, 1);
}
}
}
}
#ifdef CPU_ONLY
STUB_GPU(UpsampleLayer);
#endif
INSTANTIATE_CLASS(UpsampleLayer);
REGISTER_LAYER_CLASS(Upsample);
} // namespace caffe
相關推薦
語義分割學習筆記(三)——SegNet Upsample層解析
1 引數設定 message UpsampleParameter { // DEPRECATED. No need to specify upsampling scale factors when // exact output shape is given by
Cesium學習筆記(三): 影象層(Imagery Layers)和地形(Terrain)
Cesium支援多個高解析度的混合使用圖層,每層的亮度,對比度,伽瑪,色調和飽和度都可以動態地改變 首先我們來建立一個圖層試試 var viewer = new Cesium.Viewer('cesiumContainer', { image
JAVA學習筆記(三)
byte repl efi ber 時間 clas 區分大小寫 增強for size @SuppressWarnings("resource")是用來壓制資源泄露警告的。比如使用io類,最後沒有關閉。Set集合特點:1)無序,不隨機2)元素唯一3)沒下標註意:Collect
thinkphp5.0學習筆記(三)獲取信息,變量,綁定參數
名稱 自動識別 參數順序 query images 報錯 oca nds arc 1.構造函數: 控制器類必須繼承了\think\Controller類,才能使用: 方法_initialize 代碼: <?php namespace app\lian\control
最優化學習筆記(三)最速下降法
tex track enter water pos 最優 content 分享 clas 最優化學習筆記(三)最速下降法
python學習筆記(三)
list 內存 寫入 odin move 列表 付出 open ada 文件的操作一般分三步: 1、打開文件,獲取文件的指針(句柄) 2、通過指針(句柄)操作文件 3、關閉文件 現在有以下文件: 我們為愛還在學 學溝通的語言
Redis學習筆記(三)常用命令整理
mes ember nbsp end 插入 學習筆記 頻道 hash value Redis 常用命令 1.DEL key 刪除key2.EXISTS key 檢查key是否存在3.KEYS * 查看所有的key4.EXPIRE key seconds 設置key的過期時
Django 學習筆記(三)模板導入
文件 文件中 訪問 from lang sts class rom 網頁 本章內容是將一個html網頁放進模板中,並運行服務器將其展現出來。 平臺:windows平臺下Liunx子系統 目前的目錄: hello ├── manage.py ├── hello │ ├─
Git學習筆記(三)遠程庫(GitHub)協同開發,fork和忽略特殊文件
tex 情況 learn 多人 版本管理 獲得 logs 秘鑰 多個 遠程庫 遠程庫,通俗的講就是不再本地的git倉庫!他的工作方式和我們本地的一樣,但是要使用他就需要先建立連接! 遠程庫有兩種,一個是自己搭建的git服務器;另一種就是使用GitHub,這個網站就是
jQuery學習筆記(三)
對象 idt 命名空間 goto div hid 右鍵 func 切換 jQuery中的事件和動畫 jquery中的事件 加載DOM 兩者等價但有細微區別 $(document).ready(function(){//編寫代碼}) 在DOM完全就緒時就可以被調用。
《EFFECTIVEC++》學習筆記(三)
ict lsp alq list dict baidu vsr .com 學習筆記 REDIS%E6%BA%90%E7%A0%81%E5%89%96%E6%9E%90-DICT%E9%81%8D%E5%8E%86%E7%AE%97%E6%B3%95 http://mp3.
學習筆記(三)——數據庫命令的應用
cal 名稱 nbsp ges bsp tex 密碼 連接字符串 集合 學習筆記(三)——數據庫命令的應用 一、存儲過程 (一)基本概念 存儲過程就是固化SQL數據庫系統內部的SQL語句,這樣做的好處是可以提高執行效率,提高數據庫的安全性,減
Hibernate學習筆記(三) --- 映射枚舉類型
enume rto 希望 enum 類名 賦值 rom cart org 對於枚舉類型,不能通過org.hibernate.annotations.Type註解來簡單的映射對應的數據庫字段類型(除非自定義類型)。對此,Hibernate提供了javax.persis
C#可擴展編程之MEF學習筆記(三):導出類的方法和屬性(轉)
學習 說了 如何 mod ati dem ont num imp 前面說完了導入和導出的幾種方法,如果大家細心的話會註意到前面我們導出的都是類,那麽方法和屬性能不能導出呢???答案是肯定的,下面就來說下MEF是如何導出方法和屬性的。 還是前面的代碼,第二篇中已經提供了下
【轉載】.NET Remoting學習筆記(三)信道
star fig cati 服務端 pro net string spa 處理類型 目錄 .NET Remoting學習筆記(一)概念 .NET Remoting學習筆記(二)激活方式 .NET Remoting學習筆記(三)信道 參考:♂風車車.Net .NET Fra
python3學習筆記(三)多線程與多進程
ttr pid make start lee close gif 自己 oops 線程thread,庫threading 進程process,庫Process 使用起來方法跟其他語言相似,也不需要下載其他的庫,語言自帶的庫裏就有 1.多線程的例子 1 #coding=
Linux學習筆記(三) putty、xshell運用
mage puttygen init for 下載 mkdir shell org c11 上一節學習了centos7的靜態ip配置,今天學習使用putty和xshell遠程連接centos7一.首先來學習使用putty1.下載putty包 https://www.chi
Asp.net core 2.0.1 Razor 的使用學習筆記(三)
post 應用程序 新的 entity gin start 密碼強度 ice httponly ASP.net core 2.0.1 中 asp.net identity 2.0.1 的基本使用(二)—用戶賬戶及cookie配置 修改用戶賬戶及cookie配置
Redis深入學習筆記(三)RDB及AOF流程
del 每秒調用 查看 單個 一個 重寫 use 物理內存 深入學習 RDB是Redis持久化數據的一種方式,是執行時間點的Redis內存快照,redis數據還原時加載rdb文件,Redis的主從數據同步也是基於RDB實現的。 RDB流程:
MySQL學習筆記(三)
集中 外鍵 部分 進行 drop 非空約束 類型 級聯操作 space 1 數據約束 1.1什麽數據約束 對用戶操作表的數據進行約束 1.2 默認值 作用: 當用戶對使用默認值的字段不插入值的時候,就使用默認值。 註意: 1)對默認值字段插入null是可以的。 2)對默認值