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
{
/** @brief Lightweight class for storing and processing a shape of blob (or anything else).
*/
struct BlobShape
{
explicit BlobShape(int ndims = 4, int fill = 1);
BlobShape(int num, int cn, int rows, int cols);
BlobShape(int ndims, const int *sizes);
BlobShape(const std::vector<int> &sizes);
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); //!< Creates 4-dim shape [@p num, @p cn, @p rows, @p cols]
BlobShape(int ndims, const int *sizes); //!< Creates n-dim shape from the @p sizes array
BlobShape(const std::vector<int> &sizes); //!< Creates n-dim shape from the @p sizes vector
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 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);
//do the same as size()
int operator[](int axis) const;
int &operator[](int axis);
/** @brief Returns the size of the specified @p axis.
* @see size()
*/
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;
/** @brief Returns the product of all sizes of axes. */
ptrdiff_t total();
/** @brief Returns pointer to the first element of continuous size array. */
const int *ptr() const;
/** @brief Checks equality of two shapes. */
bool equal(const BlobShape &other) const;
private:
@ -94,14 +114,16 @@ namespace dnn
public:
explicit Blob();
/** @brief Constructs blob with specified @p shape and @p type. */
explicit Blob(const BlobShape &shape, int type = CV_32F);
/** @brief constucts 4-dimensional blob from input
* @param in 2-dimensional or 3-dimensional single-channel image (or vector from them)
* @param dstCn if specified force size of ouptut blob channel-dimension
/** @brief Constucts 4-dimensional blob from image or array of images.
* @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
*/
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 fill(InputArray in);
@ -110,74 +132,85 @@ namespace dnn
Mat& getMatRef();
const Mat& getMatRef() const;
//TODO: add UMat get methods
Mat getMat(int n, int cn);
//shape getters
///returns real count of blob dimensions
/** @brief Returns number of blob dimensions. */
int dims() 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.
Supposed that size of non-existing dimensions equal to 1, so the method always finished.
*/
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.
*/
/** @brief Returns 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) const;
/** @brief returns number of elements
@param startAxis starting axis (inverse indexing can be used)
@param endAxis ending (excluded) axis
@see canonicalAxis()
*/
size_t total(int startAxis = 0, int endAxis = -1) const;
/** @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;
/** @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;
/** @brief returns shape of the blob
*/
/** @brief Returns shape of the blob. */
BlobShape shape() const;
/** @brief Checks equality of two blobs shapes. */
bool equalShape(const Blob &other) const;
//shape getters for 4-dim Blobs processing
int cols() const;
int rows() const;
int channels() const;
int num() const;
Size size2() const;
Vec4i shape4() const;
//CPU data pointer functions
/** @brief Returns sclice of first two dimensions.
* @details The behavior is similar to the following numpy code: blob[n, cn, ...]
*/
Mat getPlane(int n, int cn);
/** @addtogroup Shape getters of 4-dimensional blobs.
* @{
*/
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>
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;
uchar *ptr(int n = 0, int cn = 0, int row = 0, int col = 0);
template<typename TFloat>
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);
//TODO: add const ptr methods
/** @}*/
/** @brief Share data with other blob.
@returns *this
*/
/** @brief Shares data from other @p blob.
* @returns *this
*/
Blob &shareFrom(const Blob &blob);
/** @brief Adjust blob shape to required (data reallocated if needed).
@returns *this
*/
/** @brief Changes shape of the blob without copying the data.
* @returns *this
*/
Blob &reshape(const BlobShape &shape);
/** @brief Returns type of the blob. */
int type() const;
bool isFloat() const;
bool isDouble() const;
private:
const int *sizes() const;

@ -187,12 +187,14 @@ inline size_t Blob::total(int startAxis, int endAxis) const
if (startAxis < 0)
startAxis += dims();
if (endAxis == -1)
if (endAxis == INT_MAX)
endAxis = dims();
else if (endAxis < 0)
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++)
size *= (size_t)sizes()[i];
@ -266,9 +268,10 @@ inline const Mat& Blob::getMatRef() const
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
@ -301,16 +304,6 @@ inline int Blob::type() const
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
{
return &m.size[0];

@ -78,8 +78,8 @@ namespace dnn
std::vector<Blob> blobs;
/** @brief Allocates internal buffers and output blobs with respect to the shape of inputs.
* @param[in] inputs vector of already allocated input blobs
* @param[out] outputs vector of output blobs, which must be allocated
* @param[in] input vector of already allocated input blobs
* @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.
* 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);
std::vector<Mat> inMats = extractMatVector(in);
std::vector<Mat> inMats = extractMatVector(image);
BlobShape dstShape = getBlobShpae(inMats, dstCn);
m.create(dstShape.dims(), dstShape.ptr(), CV_32F);

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

@ -108,29 +108,29 @@ namespace dnn
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);
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++)
{
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)
{
Mat left = srcBlob.getMat(n, cn - ksize - 1);
Mat left = srcBlob.getPlane(n, cn - ksize - 1);
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);
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++)
{
Mat src = srcBlob.getMat(n, cn);
Mat dst = dstBlob.getMat(n, cn);
Mat src = srcBlob.getPlane(n, cn);
Mat dst = dstBlob.getPlane(n, cn);
uchar *dataDst0 = dst.data;
cv::pow(srcBlob.getMat(n, cn), 2, dst);
cv::pow(srcBlob.getPlane(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);

@ -81,7 +81,7 @@ namespace dnn
size_t outerSize = src.total(0, 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 cnStep = src.total(axis + 1);

Loading…
Cancel
Save