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