Update doc, small changes in Blob methods

pull/265/head
Vitaliy Lyudvichenko 10 years ago
parent f8715f39e7
commit 945094bc58
  1. 143
      modules/dnn/include/opencv2/dnn/blob.hpp
  2. 21
      modules/dnn/include/opencv2/dnn/blob.inl.hpp
  3. 4
      modules/dnn/include/opencv2/dnn/dnn.hpp
  4. 4
      modules/dnn/src/blob.cpp
  5. 4
      modules/dnn/src/layers/elementwise_layers.hpp
  6. 18
      modules/dnn/src/layers/lrn_layer.cpp
  7. 2
      modules/dnn/src/layers/softmax_layer.cpp

@ -49,30 +49,50 @@ namespace cv
{ {
namespace dnn namespace dnn
{ {
/** @brief Lightweight class for storing and processing a shape of blob (or anything else).
*/
struct BlobShape struct BlobShape
{ {
explicit BlobShape(int ndims = 4, int fill = 1); explicit BlobShape(int ndims = 4, int fill = 1); //!< Creates n-dim shape and fill its by @p fill
BlobShape(int num, int cn, int rows, int cols); BlobShape(int num, int cn, int rows, int cols); //!< Creates 4-dim shape [@p num, @p cn, @p rows, @p cols]
BlobShape(int ndims, const int *sizes); BlobShape(int ndims, const int *sizes); //!< Creates n-dim shape from the @p sizes array
BlobShape(const std::vector<int> &sizes); BlobShape(const std::vector<int> &sizes); //!< Creates n-dim shape from the @p sizes vector
template<int n> template<int n>
BlobShape(const Vec<int, n> &shape); BlobShape(const Vec<int, n> &shape); //!< Creates n-dim shape from @ref cv::Vec
/** @brief Returns number of dimensions. */
int dims() const; int dims() const;
int size(int axis) const;
/** @brief Returns reference to the size of the specified @p axis.
*
* Negative @p axis is supported, in this case a counting starts from the last axis,
* i. e. -1 corresponds to last axis.
* If non-existing axis was passed then an error will be generated.
*/
int &size(int axis); int &size(int axis);
//do the same as size() /** @brief Returns the size of the specified @p axis.
int operator[](int axis) const; * @see size()
int &operator[](int axis); */
int size(int axis) const;
int operator[](int axis) const; //!< Does the same thing as size(axis).
int &operator[](int axis); //!< Does the same thing as size(int) const.
//same as size(), but size of non-existing dimensions equal to 1 /** @brief Returns the size of the specified @p axis.
*
* Does the same thing as size(int) const, but if non-existing axis will be passed then 1 will be returned,
* therefore this function always finishes successfuly.
*/
int xsize(int axis) const; int xsize(int axis) const;
/** @brief Returns the product of all sizes of axes. */
ptrdiff_t total(); ptrdiff_t total();
/** @brief Returns pointer to the first element of continuous size array. */
const int *ptr() const; const int *ptr() const;
/** @brief Checks equality of two shapes. */
bool equal(const BlobShape &other) const; bool equal(const BlobShape &other) const;
private: private:
@ -94,14 +114,16 @@ namespace dnn
public: public:
explicit Blob(); explicit Blob();
/** @brief Constructs blob with specified @p shape and @p type. */
explicit Blob(const BlobShape &shape, int type = CV_32F); explicit Blob(const BlobShape &shape, int type = CV_32F);
/** @brief constucts 4-dimensional blob from input /** @brief Constucts 4-dimensional blob from image or array of images.
* @param in 2-dimensional or 3-dimensional single-channel image (or vector from them) * @param image 2-dimensional multi-channel or 3-dimensional single-channel image (or array of images)
* @param dstCn if specified force size of ouptut blob channel-dimension * @param dstCn if specified force size of ouptut blob channel-dimension
*/ */
explicit Blob(InputArray in, int dstCn = -1); explicit Blob(InputArray image, int dstCn = -1);
/** @brief Creates blob with specified @p shape and @p type. */
void create(const BlobShape &shape, int type = CV_32F); void create(const BlobShape &shape, int type = CV_32F);
void fill(InputArray in); void fill(InputArray in);
@ -110,74 +132,85 @@ namespace dnn
Mat& getMatRef(); Mat& getMatRef();
const Mat& getMatRef() const; const Mat& getMatRef() const;
//TODO: add UMat get methods //TODO: add UMat get methods
Mat getMat(int n, int cn);
//shape getters /** @brief Returns number of blob dimensions. */
///returns real count of blob dimensions
int dims() const; int dims() const;
/** @brief returns size of corresponding dimension (axis) /** @brief Returns the size of the specified @p axis.
@param axis dimension index *
Python-like indexing is supported, so @p axis can be negative, i. e. -1 is last dimension. * Negative @p axis is supported, in this case a counting starts from the last axis,
Supposed that size of non-existing dimensions equal to 1, so the method always finished. * i. e. -1 corresponds to last axis.
*/ * If non-existing axis was passed then an error will be generated.
int xsize(int axis) const; */
/** @brief returns size of corresponding dimension (axis)
@param axis dimension index
Python-like indexing is supported, so @p axis can be negative, i. e. -1 is last dimension.
@note Unlike xsize(), if @p axis points to non-existing dimension then an error will be generated.
*/
int size(int axis) const; int size(int axis) const;
/** @brief returns number of elements /** @brief Returns the size of the specified @p axis.
@param startAxis starting axis (inverse indexing can be used) *
@param endAxis ending (excluded) axis * Does the same thing as size(int) const, but if non-existing axis will be passed then 1 will be returned,
@see canonicalAxis() * therefore this function always finishes successfuly.
*/ */
size_t total(int startAxis = 0, int endAxis = -1) const; int xsize(int axis) const;
/** @brief converts axis index to canonical format (where 0 <= axis < dims()) /** @brief Computes the product of sizes of axes among the specified axes range [@p startAxis; @p endAxis).
* @param startAxis the first axis to include in the range.
* @param endAxis the first axis to exclude from the range.
* @details Negative axis indexing can be used.
* @see canonicalAxis()
*/
size_t total(int startAxis = 0, int endAxis = INT_MAX) const;
/** @brief converts @p axis index to canonical format (where 0 <= axis < dims())
*/ */
int canonicalAxis(int axis) const; int canonicalAxis(int axis) const;
/** @brief returns shape of the blob /** @brief Returns shape of the blob. */
*/
BlobShape shape() const; BlobShape shape() const;
/** @brief Checks equality of two blobs shapes. */
bool equalShape(const Blob &other) const; bool equalShape(const Blob &other) const;
//shape getters for 4-dim Blobs processing /** @brief Returns sclice of first two dimensions.
int cols() const; * @details The behavior is similar to the following numpy code: blob[n, cn, ...]
int rows() const; */
int channels() const; Mat getPlane(int n, int cn);
int num() const;
Size size2() const; /** @addtogroup Shape getters of 4-dimensional blobs.
Vec4i shape4() const; * @{
*/
//CPU data pointer functions int cols() const; //!< Returns size of the fourth blob axis.
int rows() const; //!< Returns size of the thrid blob axis.
int channels() const; //!< Returns size of the second blob axis.
int num() const; //!< Returns size of the first blob axis.
Size size2() const; //!< Returns cv::Size(cols(), rows())
Vec4i shape4() const; //!< Returns shape of firt four blob axes.
/** @}*/
/** @addtogroup CPU pointer getters
* @{
*/
template<int n> template<int n>
size_t offset(const Vec<int, n> &pos) const; size_t offset(const Vec<int, n> &pos) const;
size_t offset(int n = 0, int cn = 0, int row = 0, int col = 0) const; size_t offset(int n = 0, int cn = 0, int row = 0, int col = 0) const;
uchar *ptr(int n = 0, int cn = 0, int row = 0, int col = 0); uchar *ptr(int n = 0, int cn = 0, int row = 0, int col = 0);
template<typename TFloat> template<typename TFloat>
TFloat *ptr(int n = 0, int cn = 0, int row = 0, int col = 0); TFloat *ptr(int n = 0, int cn = 0, int row = 0, int col = 0);
/** Returns (float*) ptr() */
float *ptrf(int n = 0, int cn = 0, int row = 0, int col = 0); float *ptrf(int n = 0, int cn = 0, int row = 0, int col = 0);
//TODO: add const ptr methods //TODO: add const ptr methods
/** @}*/
/** @brief Share data with other blob. /** @brief Shares data from other @p blob.
@returns *this * @returns *this
*/ */
Blob &shareFrom(const Blob &blob); Blob &shareFrom(const Blob &blob);
/** @brief Adjust blob shape to required (data reallocated if needed). /** @brief Changes shape of the blob without copying the data.
@returns *this * @returns *this
*/ */
Blob &reshape(const BlobShape &shape); Blob &reshape(const BlobShape &shape);
/** @brief Returns type of the blob. */
int type() const; int type() const;
bool isFloat() const;
bool isDouble() const;
private: private:
const int *sizes() const; const int *sizes() const;

@ -187,12 +187,14 @@ inline size_t Blob::total(int startAxis, int endAxis) const
if (startAxis < 0) if (startAxis < 0)
startAxis += dims(); startAxis += dims();
if (endAxis == -1) if (endAxis == INT_MAX)
endAxis = dims(); endAxis = dims();
else if (endAxis < 0)
endAxis += dims();
CV_Assert(0 <= startAxis && startAxis <= endAxis && endAxis <= dims()); CV_Assert(0 <= startAxis && startAxis <= endAxis && endAxis <= dims());
size_t size = 1; //assume that blob isn't empty size_t size = 1; //fix: assume that slice isn't empty
for (int i = startAxis; i < endAxis; i++) for (int i = startAxis; i < endAxis; i++)
size *= (size_t)sizes()[i]; size *= (size_t)sizes()[i];
@ -266,9 +268,10 @@ inline const Mat& Blob::getMatRef() const
return m; return m;
} }
inline Mat Blob::getMat(int n, int cn) inline Mat Blob::getPlane(int n, int cn)
{ {
return Mat(rows(), cols(), m.type(), this->ptr(n, cn)); CV_Assert(dims() > 2);
return Mat(dims() - 2, sizes() + 2, type(), ptr(n, cn));
} }
inline int Blob::cols() const inline int Blob::cols() const
@ -301,16 +304,6 @@ inline int Blob::type() const
return m.depth(); return m.depth();
} }
inline bool Blob::isFloat() const
{
return (type() == CV_32F);
}
inline bool Blob::isDouble() const
{
return (type() == CV_32F);
}
inline const int * Blob::sizes() const inline const int * Blob::sizes() const
{ {
return &m.size[0]; return &m.size[0];

@ -78,8 +78,8 @@ namespace dnn
std::vector<Blob> blobs; std::vector<Blob> blobs;
/** @brief Allocates internal buffers and output blobs with respect to the shape of inputs. /** @brief Allocates internal buffers and output blobs with respect to the shape of inputs.
* @param[in] inputs vector of already allocated input blobs * @param[in] input vector of already allocated input blobs
* @param[out] outputs vector of output blobs, which must be allocated * @param[out] output vector of output blobs, which must be allocated
* *
* This method must create each produced blob according to shape of @p input blobs and internal layer params. * This method must create each produced blob according to shape of @p input blobs and internal layer params.
* If this method is called first time then @p output vector consists from empty blobs and its size determined by number of output connections. * If this method is called first time then @p output vector consists from empty blobs and its size determined by number of output connections.

@ -119,10 +119,10 @@ namespace dnn
} }
} }
Blob::Blob(InputArray in, int dstCn) Blob::Blob(InputArray image, int dstCn)
{ {
CV_Assert(dstCn == -1 || dstCn > 0); CV_Assert(dstCn == -1 || dstCn > 0);
std::vector<Mat> inMats = extractMatVector(in); std::vector<Mat> inMats = extractMatVector(image);
BlobShape dstShape = getBlobShpae(inMats, dstCn); BlobShape dstShape = getBlobShpae(inMats, dstCn);
m.create(dstShape.dims(), dstShape.ptr(), CV_32F); m.create(dstShape.dims(), dstShape.ptr(), CV_32F);

@ -78,13 +78,13 @@ using std::pow;
size_t size = outputs[i].total(); size_t size = outputs[i].total();
if (outputs[i].isFloat()) if (outputs[i].type() == CV_32F)
{ {
float *data = outputs[i].ptrf(); float *data = outputs[i].ptrf();
for (size_t j = 0; j < size; j++) for (size_t j = 0; j < size; j++)
data[j] = func(data[j]); data[j] = func(data[j]);
} }
else if (outputs[i].isDouble()) else if (outputs[i].type() == CV_64F)
{ {
double *data = outputs[i].ptr<double>(); double *data = outputs[i].ptr<double>();
for (size_t j = 0; j < size; j++) for (size_t j = 0; j < size; j++)

@ -108,29 +108,29 @@ namespace dnn
for (int n = 0; n < num; n++) for (int n = 0; n < num; n++)
{ {
Mat accum = dstBlob.getMat(n, channels-1); //trick for memory saving Mat accum = dstBlob.getPlane(n, channels-1); //trick for memory saving
accum.setTo(0); accum.setTo(0);
for (int cn = 0; cn < std::min(ksize, channels); cn++) for (int cn = 0; cn < std::min(ksize, channels); cn++)
cv::accumulateSquare(srcBlob.getMat(n, cn), accum); cv::accumulateSquare(srcBlob.getPlane(n, cn), accum);
for (int cn = 0; cn < channels; cn++) for (int cn = 0; cn < channels; cn++)
{ {
if (cn + ksize < channels) if (cn + ksize < channels)
{ {
cv::accumulateSquare(srcBlob.getMat(n, cn + ksize), accum); cv::accumulateSquare(srcBlob.getPlane(n, cn + ksize), accum);
} }
if (cn - ksize - 1 >= 0) if (cn - ksize - 1 >= 0)
{ {
Mat left = srcBlob.getMat(n, cn - ksize - 1); Mat left = srcBlob.getPlane(n, cn - ksize - 1);
cv::subtract(accum, left.mul(left), accum); //subtractSquare cv::subtract(accum, left.mul(left), accum); //subtractSquare
} }
Mat dst = dstBlob.getMat(n, cn); Mat dst = dstBlob.getPlane(n, cn);
accum.convertTo(dst, dst.type(), alpha/size, 1); accum.convertTo(dst, dst.type(), alpha/size, 1);
cv::pow(dst, beta, dst); cv::pow(dst, beta, dst);
cv::divide(srcBlob.getMat(n, cn), dst, dst); cv::divide(srcBlob.getPlane(n, cn), dst, dst);
} }
} }
} }
@ -144,11 +144,11 @@ namespace dnn
{ {
for (int cn = 0; cn < channels; cn++) for (int cn = 0; cn < channels; cn++)
{ {
Mat src = srcBlob.getMat(n, cn); Mat src = srcBlob.getPlane(n, cn);
Mat dst = dstBlob.getMat(n, cn); Mat dst = dstBlob.getPlane(n, cn);
uchar *dataDst0 = dst.data; uchar *dataDst0 = dst.data;
cv::pow(srcBlob.getMat(n, cn), 2, dst); cv::pow(srcBlob.getPlane(n, cn), 2, dst);
//TODO: check border type //TODO: check border type
cv::boxFilter(dst, dst, dst.depth(), cv::Size(size, size), cv::Point(-1, -1), false, cv::BORDER_CONSTANT); 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); dst.convertTo(dst, dst.type(), alpha/(size*size), 1);

@ -81,7 +81,7 @@ namespace dnn
size_t outerSize = src.total(0, axis); size_t outerSize = src.total(0, axis);
size_t channels = src.size(axis); size_t channels = src.size(axis);
size_t innerSize = src.total(axis + 1, -1); size_t innerSize = src.total(axis + 1);
size_t outerStep = src.total(axis); size_t outerStep = src.total(axis);
size_t cnStep = src.total(axis + 1); size_t cnStep = src.total(axis + 1);

Loading…
Cancel
Save