parent
09ffc43ce6
commit
eef4d1dda9
7 changed files with 364 additions and 22 deletions
@ -0,0 +1,39 @@ |
||||
#include "../precomp.hpp" |
||||
#include "layers_common.hpp" |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace dnn |
||||
{ |
||||
class BlankLayer : public Layer |
||||
{ |
||||
public: |
||||
|
||||
BlankLayer(LayerParams ¶ms) |
||||
{ |
||||
|
||||
} |
||||
|
||||
void allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs) |
||||
{ |
||||
outputs.resize(inputs.size()); |
||||
for (size_t i = 0; i < inputs.size(); i++) |
||||
outputs[i] = *inputs[i]; |
||||
} |
||||
|
||||
void forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs) |
||||
{ |
||||
for (size_t i = 0; i < inputs.size(); i++) |
||||
outputs[i] = *inputs[i]; |
||||
} |
||||
}; |
||||
|
||||
static Ptr<Layer> blankLayerRegisterer(LayerParams ¶ms) |
||||
{ |
||||
return Ptr<Layer>(new BlankLayer(params)); |
||||
} |
||||
|
||||
|
||||
REGISTER_LAYER_FUNC(Dropout, blankLayerRegisterer) |
||||
} |
||||
} |
@ -0,0 +1,138 @@ |
||||
#include "../precomp.hpp" |
||||
#include "layers_common.hpp" |
||||
#include <opencv2/imgproc.hpp> |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace dnn |
||||
{ |
||||
class LRNLayer : public Layer |
||||
{ |
||||
enum
|
||||
{ |
||||
CHANNEL_NRM, |
||||
SPATIAL_NRM, |
||||
SPATIAL_CONTRAST_NRM //cuda-convnet feature
|
||||
} type; |
||||
|
||||
int size; |
||||
double alpha, beta; |
||||
|
||||
Blob bufBlob; |
||||
|
||||
void channelNoramlization(Blob &src, Blob &dst); |
||||
void spatialNormalization(Blob &src, Blob &dst); |
||||
|
||||
public: |
||||
|
||||
LRNLayer(LayerParams ¶ms); |
||||
void allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs); |
||||
void forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs); |
||||
}; |
||||
|
||||
|
||||
REGISTER_LAYER_CLASS(LRN, LRNLayer) |
||||
|
||||
|
||||
LRNLayer::LRNLayer(LayerParams ¶ms) |
||||
{ |
||||
String nrmType = params.get<String>("norm_region", "ACROSS_CHANNELS"); |
||||
if (nrmType == "ACROSS_CHANNELS") |
||||
type = CHANNEL_NRM; |
||||
else if (nrmType == "WITHIN_CHANNEL") |
||||
type = SPATIAL_NRM; |
||||
else |
||||
CV_Error(cv::Error::StsBadArg, "Unknown region type \"" + nrmType + "\""); |
||||
|
||||
size = params.get<int>("local_size", 5); |
||||
if (size % 2 != 1) |
||||
CV_Error(cv::Error::StsBadArg, "LRN layer only supports odd values for local_size"); |
||||
|
||||
alpha = params.get<double>("alpha", 1); |
||||
beta = params.get<double>("beta", 0.75); |
||||
} |
||||
|
||||
void LRNLayer::allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs) |
||||
{ |
||||
CV_Assert(inputs.size() == 1); |
||||
outputs.resize(1); |
||||
|
||||
Vec4i shape = inputs[0]->shape(); |
||||
outputs[0].create(shape); |
||||
|
||||
shape[1] = 1; //maybe make shape[0] = 1 too
|
||||
bufBlob.create(shape); |
||||
} |
||||
|
||||
void LRNLayer::forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs) |
||||
{ |
||||
Blob &src = *inputs[0]; |
||||
Blob &dst = outputs[0]; |
||||
|
||||
switch (type) |
||||
{ |
||||
case CHANNEL_NRM: |
||||
channelNoramlization(src, dst); |
||||
break; |
||||
case SPATIAL_NRM: |
||||
spatialNormalization(src, dst); |
||||
break; |
||||
default: |
||||
CV_Error(cv::Error::StsNotImplemented, "Unimplemented mode of LRN layer"); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void LRNLayer::channelNoramlization(Blob &srcBlob, Blob &dstBlob) |
||||
{ |
||||
int num = srcBlob.num(); |
||||
int channels = srcBlob.channels(); |
||||
|
||||
for (int n = 0; n < num; n++) |
||||
{ |
||||
Mat buf = bufBlob.getMat(n, 0); |
||||
Mat accum = dstBlob.getMat(n, 0); //memory saving
|
||||
accum.setTo(0); |
||||
|
||||
for (int cn = 0; cn < channels; cn++) |
||||
{ |
||||
cv::accumulateSquare(srcBlob.getMat(), accum); |
||||
} |
||||
|
||||
accum.convertTo(accum, accum.type(), alpha/channels, 1); |
||||
cv::pow(accum, beta, accum); |
||||
|
||||
for (int cn = channels - 1; cn >= 0; cn--) |
||||
{ |
||||
cv::divide(srcBlob.getMat(n, cn), accum, dstBlob.getMat(n, cn)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void LRNLayer::spatialNormalization(Blob &srcBlob, Blob &dstBlob) |
||||
{ |
||||
int num = srcBlob.num(); |
||||
int channels = srcBlob.channels(); |
||||
|
||||
for (int n = 0; n < num; n++) |
||||
{ |
||||
for (int cn = 0; cn < channels; cn++) |
||||
{ |
||||
Mat src = srcBlob.getMat(n, cn); |
||||
Mat dst = dstBlob.getMat(n, cn); |
||||
uchar *dataDst0 = dst.data; |
||||
|
||||
cv::pow(srcBlob.getMat(n, cn), 2, dst); |
||||
//TODO: check border type
|
||||
cv::boxFilter(dst, dst, dst.depth(), cv::Size(size, size), cv::Point(-1, -1), false, cv::BORDER_CONSTANT); |
||||
dst.convertTo(dst, dst.type(), alpha/(size*size), 1); |
||||
cv::pow(dst, beta, dst); |
||||
cv::divide(src, dst, dst); |
||||
|
||||
CV_DbgAssert(dataDst0 == dst.data); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,116 @@ |
||||
#include "../precomp.hpp" |
||||
#include "layers_common.hpp" |
||||
#include <algorithm> |
||||
#include <stdlib.h> |
||||
using std::max; |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace dnn |
||||
{ |
||||
class SoftMaxLayer : public Layer |
||||
{ |
||||
int axis; |
||||
Blob maxAggregator; |
||||
|
||||
public: |
||||
SoftMaxLayer(LayerParams ¶ms); |
||||
void allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs); |
||||
void forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs); |
||||
}; |
||||
|
||||
|
||||
REGISTER_LAYER_CLASS(Softmax, SoftMaxLayer); |
||||
|
||||
|
||||
SoftMaxLayer::SoftMaxLayer(LayerParams ¶ms) |
||||
{ |
||||
axis = params.get<int>("axis", 1); |
||||
CV_Assert(0 <= axis && axis < 4); |
||||
} |
||||
|
||||
void SoftMaxLayer::allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &outputs) |
||||
{ |
||||
CV_Assert(inputs.size() == 1); |
||||
|
||||
Vec4i shape = inputs[0]->shape(); |
||||
outputs.resize(1); |
||||
outputs[0].create(shape); |
||||
|
||||
shape[axis] = 1; |
||||
maxAggregator.create(shape); |
||||
} |
||||
|
||||
void SoftMaxLayer::forward(std::vector<Blob*> &inputs, std::vector<Blob> &outputs) |
||||
{ |
||||
Blob &src = *inputs[0]; |
||||
Blob &dst = outputs[0]; |
||||
|
||||
float *srcPtr = src.ptr<float>(); |
||||
float *dstPtr = dst.ptr<float>(); |
||||
float *bufPtr = maxAggregator.ptr<float>(); |
||||
|
||||
size_t totalSize = src.total(); |
||||
size_t outerSize = src.total(0, axis); |
||||
size_t channels = src.size(axis); |
||||
size_t innerSize = src.total(axis + 1, -1); |
||||
|
||||
size_t outerStep = src.total(axis); |
||||
size_t cnStep = src.total(axis + 1); |
||||
|
||||
//compute max along axis
|
||||
for (size_t outerDim = 0; outerDim < outerSize; outerDim++) |
||||
{ |
||||
size_t srcOffset = outerDim * outerStep; |
||||
size_t bufOffset = outerDim * cnStep; |
||||
|
||||
memcpy(bufPtr + bufOffset, srcPtr + srcOffset, innerSize * sizeof(float)); |
||||
|
||||
for (size_t cnDim = 1; cnDim < channels; cnDim++) |
||||
{ |
||||
for (size_t i = 0; i < innerSize; i++) |
||||
bufPtr[bufOffset + i] = std::max(bufPtr[bufOffset + i], srcPtr[srcOffset + cnDim * cnStep + i]); |
||||
} |
||||
} |
||||
|
||||
//subtract max
|
||||
for (size_t outerDim = 0; outerDim < outerSize; outerDim++) |
||||
{ |
||||
size_t srcOffset = outerDim * outerStep; |
||||
size_t bufOffset = outerDim * cnStep; |
||||
|
||||
for (size_t cnDim = 0; cnDim < channels; cnDim++) |
||||
{ |
||||
for (size_t i = 0; i < innerSize; i++) |
||||
dstPtr[srcOffset + cnDim * cnStep + i] = srcPtr[srcOffset + cnDim * cnStep + i] - bufPtr[bufOffset + i]; |
||||
} |
||||
} |
||||
|
||||
cv::exp(dst.getMat(), dst.getMat()); |
||||
|
||||
for (size_t outerDim = 0; outerDim < outerSize; outerDim++) |
||||
{ |
||||
size_t srcOffset = outerDim * outerStep; |
||||
size_t bufOffset = outerDim * cnStep; |
||||
|
||||
//sum exp along axis
|
||||
for (size_t i = 0; i < innerSize; i++) |
||||
bufPtr[bufOffset + i] = 0.f; |
||||
|
||||
for (size_t cnDim = 0; cnDim < channels; cnDim++) |
||||
{ |
||||
for (size_t i = 0; i < innerSize; i++) |
||||
bufPtr[bufOffset + i] += dstPtr[srcOffset + cnDim * cnStep + i]; |
||||
} |
||||
|
||||
//divide by computed sum
|
||||
for (size_t cnDim = 0; cnDim < channels; cnDim++) |
||||
{ |
||||
for (size_t i = 0; i < innerSize; i++) |
||||
dstPtr[srcOffset + cnDim * cnStep + i] /= bufPtr[bufOffset + i]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
Loading…
Reference in new issue