标签:
由于之前介绍过一次关于实现自己的网络层的文章,但是那篇文章偏难,这次我以最简单的对图像进行缩放的层为例进行实现。
在进行讲解之前,有一些必要条件你需要掌握,那就是你已经很了解怎么安装caffe,并且知道caffe里头的各个目录。
message ImageScaleParameter {
// Specify the output height and width
optional uint32 out_height = 1;
optional uint32 out_width = 2;
// for debug you can see the source images and scaled images
optional bool visualize = 3 [default = false];
}optional HingeLossParameter hinge_loss_param = 114; optional ImageDataParameter image_data_param = 115; optional ImageScaleParameter image_scale_param = 147; optional InfogainLossParameter infogain_loss_param = 116; optional InnerProductParameter inner_product_param = 117;
#ifndef CAFFE_IMAGE_SCALE_LAYER_HPP_ #define CAFFE_IMAGE_SCALE_LAYER_HPP_
#include "caffe/blob.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/layer.hpp"
virtual inline const char* type() const { return "ImageScale"; }virtual inline int ExactNumBottomBlobs() const { return 1; }
virtual inline int ExactNumTopBlobs() const { return 1; }virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {};int out_height_; int out_width_; int height_; int width_; bool visualize_; int num_images_; int num_channels_;
#endif // CAFFE_IMAGE_SCALE_LAYER_HPP_
#ifndef CAFFE_IMAGE_SCALE_LAYER_HPP_
#define CAFFE_IMAGE_SCALE_LAYER_HPP_
#include "caffe/blob.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/layer.hpp"
namespace caffe {
// written by xizero00 2016/9/13
template <typename Dtype>
class ImageScaleLayer : public Layer<Dtype> {
public:
explicit ImageScaleLayer(const LayerParameter& param)
: Layer<Dtype>(param) {}
virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);
virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);
virtual inline const char* type() const { return "ImageScale"; }
virtual inline int ExactNumBottomBlobs() const { return 1; }
virtual inline int ExactNumTopBlobs() const { return 1; }
protected:
/// @copydoc ImageScaleLayer
virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);
virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {};
int out_height_;
int out_width_;
int height_;
int width_;
bool visualize_;
int num_images_;
int num_channels_;
};
} // namespace caffe
#endif // CAFFE_IMAGE_SCALE_LAYER_HPP_#include "caffe/layers/image_scale_layer.hpp" #include "caffe/util/math_functions.hpp" #include <opencv2/opencv.hpp>
template <typename Dtype>
void ImageScaleLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
// get parameters
const ImageScaleParameter& param = this->layer_param_.image_scale_param();
// get the output size
out_height_ = param.out_height();
out_width_ = param.out_width();
visualize_ = param.visualize();
// get the input size
num_images_ = bottom[0]->num();
height_ = bottom[0]->height();
width_ = bottom[0]->width();
num_channels_ = bottom[0]->channels();
// check the channels must be images
// channel must be 1 or 3, gray image or color image
CHECK_EQ( (num_channels_==3) || (num_channels_ == 1), true);
// check the output size
CHECK_GT(out_height_, 0);
CHECK_GT(out_height_, 0);
}template <typename Dtype>
void ImageScaleLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
// reshape the outputs
top[0]->Reshape(num_images_, num_channels_, out_height_, out_width_);
}template <typename Dtype>
void ImageScaleLayer<Dtype>::Forward_cpu(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
const Dtype* bottom_data = bottom[0]->cpu_data();
Dtype * top_data = top[0]->mutable_cpu_data();
cv::Mat srcimage, dstimage;
// precompurte the index
const int srcimagesize = width_ * height_;
const int dstimagesize = out_width_ * out_height_;
const int srcchimagesize = srcimagesize * num_channels_;
const int dstchimagesize = dstimagesize * num_channels_;
for ( int idx_img = 0; idx_img < num_images_; idx_img++ )
{
// zeros source images and scaled images
srcimage = cv::Mat::zeros(height_, width_, CV_32FC1);
dstimage = cv::Mat::zeros(out_height_, out_width_, CV_32FC1);
// read from bottom[0]
for ( int idx_ch = 0; idx_ch < num_channels_; idx_ch++ )
{
for (int i = 0; i < height_; i++)
{
for ( int j=0; j < width_; j++ )
{
int image_idx = idx_img * srcchimagesize + srcimagesize * idx_ch + height_ *i + j;
srcimage.at<float>(i,j) = (float)bottom_data[image_idx];
}
}
}
// resize to specified size
// here we use linear interpolation
cv::resize(srcimage, dstimage, dstimage.size());
// store the resized image to top[0]
for (int idx_ch = 0; idx_ch < num_channels_; idx_ch++)
{
for (int i = 0; i < out_height_; i++)
{
for (int j = 0; j < out_width_; j++)
{
int image_idx = idx_img * dstchimagesize + dstimagesize * idx_ch + out_height_*i + j;
top_data[image_idx] = dstimage.at<float>(i,j);
}
}
}
if (visualize_)
{
cv::namedWindow("src image", CV_WINDOW_AUTOSIZE);
cv::namedWindow("dst image", CV_WINDOW_AUTOSIZE);
cv::imshow("src image", srcimage);
cv::imshow("dst image", dstimage);
cv::waitKey(0);
}
}
}#include "caffe/layers/image_scale_layer.hpp"
#include "caffe/util/math_functions.hpp"
#include <opencv2/opencv.hpp>
namespace caffe {
template <typename Dtype>
void ImageScaleLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
// get parameters
const ImageScaleParameter& param = this->layer_param_.image_scale_param();
// get the output size
out_height_ = param.out_height();
out_width_ = param.out_width();
visualize_ = param.visualize();
// get the input size
num_images_ = bottom[0]->num();
height_ = bottom[0]->height();
width_ = bottom[0]->width();
num_channels_ = bottom[0]->channels();
// check the channels must be images
// channel must be 1 or 3, gray image or color image
CHECK_EQ( (num_channels_==3) || (num_channels_ == 1), true);
// check the output size
CHECK_GT(out_height_, 0);
CHECK_GT(out_height_, 0);
}
template <typename Dtype>
void ImageScaleLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
// reshape the outputs
top[0]->Reshape(num_images_, num_channels_, out_height_, out_width_);
}
template <typename Dtype>
void ImageScaleLayer<Dtype>::Forward_cpu(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
const Dtype* bottom_data = bottom[0]->cpu_data();
Dtype * top_data = top[0]->mutable_cpu_data();
cv::Mat srcimage, dstimage;
// precompurte the index
const int srcimagesize = width_ * height_;
const int dstimagesize = out_width_ * out_height_;
const int srcchimagesize = srcimagesize * num_channels_;
const int dstchimagesize = dstimagesize * num_channels_;
for ( int idx_img = 0; idx_img < num_images_; idx_img++ )
{
// zeros source images and scaled images
srcimage = cv::Mat::zeros(height_, width_, CV_32FC1);
dstimage = cv::Mat::zeros(out_height_, out_width_, CV_32FC1);
// read from bottom[0]
for ( int idx_ch = 0; idx_ch < num_channels_; idx_ch++ )
{
for (int i = 0; i < height_; i++)
{
for ( int j=0; j < width_; j++ )
{
int image_idx = idx_img * srcchimagesize + srcimagesize * idx_ch + height_ *i + j;
srcimage.at<float>(i,j) = (float)bottom_data[image_idx];
}
}
}
// resize to specified size
// here we use linear interpolation
cv::resize(srcimage, dstimage, dstimage.size());
// store the resized image to top[0]
for (int idx_ch = 0; idx_ch < num_channels_; idx_ch++)
{
for (int i = 0; i < out_height_; i++)
{
for (int j = 0; j < out_width_; j++)
{
int image_idx = idx_img * dstchimagesize + dstimagesize * idx_ch + out_height_*i + j;
top_data[image_idx] = dstimage.at<float>(i,j);
}
}
}
if (visualize_)
{
cv::namedWindow("src image", CV_WINDOW_AUTOSIZE);
cv::namedWindow("dst image", CV_WINDOW_AUTOSIZE);
cv::imshow("src image", srcimage);
cv::imshow("dst image", dstimage);
cv::waitKey(0);
}
}
}
#ifdef CPU_ONLY
STUB_GPU(ImageScaleLayer);
#endif
INSTANTIATE_CLASS(ImageScaleLayer);
REGISTER_LAYER_CLASS(ImageScale);
} // namespace caffe
layer {
name: "imagescaled"
type: "ImageScale"
bottom: "data"
top: "imagescaled"
image_scale_param {
out_height: 128
out_width: 128
visualize: true
}
}# Simple single-layer network to showcase editing model parameters.
name: "sample"
layer {
name: "data"
type: "Data"
top: "data"
include {
phase: TRAIN
}
transform_param {
scale: 0.0039215684
}
data_param {
source: "examples/mnist/mnist_train_lmdb"
batch_size: 10
backend: LMDB
}
}
layer {
name: "imagescaled"
type: "ImageScale"
bottom: "data"
top: "imagescaled"
image_scale_param {
out_height: 128
out_width: 128
visualize: true
}
}
net: "examples/imagescale/sample.prototxt" base_lr: 0.01 lr_policy: "step" gamma: 0.1 stepsize: 10000 display: 1 max_iter: 1 weight_decay: 0.0005 snapshot: 1 snapshot_prefix: "examples/imagescale/sample" momentum: 0.9 # solver mode: CPU or GPU solver_mode: GPU
#!/usr/bin/env sh set -e snap_dir="examples/imagescale/snapshots" mkdir -p $snap_dir TOOLS=./build/tools $TOOLS/caffe train --solver=examples/imagescale/solver.prototxt 2>&1 | tee -a $snap_dir/train.log
标签:
原文地址:http://blog.csdn.net/xizero00/article/details/52529341