数据加载类

在数据格式中,我们会区分维度等信息,那么什么是多维数据格式呢?
这里要求汇编知识:
普及:
段地址与偏移地址
自行了解
最常见的 |深度学习| 用到的维度,[1,3,224,224],代表一个batch,3个通道,图片大小为224x224,为了阐述的方便,这里以[1,2,3,4]为例,里面的值是自定义的,不必纠结值:
[
[
[ [1,2,3,4] ],
[ [1,2,3,4] ],
[ [1,2,3,4] ]
],
[
[ [1,2,3,4] ],
[ [1,2,3,4] ],
[ [1,2,3,4] ]
],
]

总共1x2x3x4=24 个数据

你没有看错,数据格式就是这么存储的,这是很多地方都这么写,都这么教学,但是,在计算机中,或者说,内存中的数据格式是怎样的呢?

这里举例说名:

我们所看到的数据类型,只是封装了显示方式,其实内部是这样的,

123412341234123412341234

可以数数是不是24个数

当然也有其他组合,实际上就是一维,至于怎么排列,私人定制也好,标准化也罢,都没有太大的影响

(降维打击)

有人会有疑惑,为什么这么去做,计算机又是做如何处理的,编译器与硬件是怎么做计算的,有兴趣可参见我的《计算机基础入门》

总之,我们知道数据本质上就是一个一维数组了,

是不是很令人惊叹,所有的矩阵数据计算就是一维数组在计算,也就是说数据流是一维数组的。

为什么要了解这个呢?

在vino推理框架中,有一种数据流blob,

我们来看看他的格式,这是一个很不完整的代码(参数值也没有解析),如果想看使用,请看案例部分,会有完整源码:

    ExecutableNetwork executableNetwork = ie.LoadNetwork(network, device);
    InferRequest inferRequest = executableNetwork.CreateInferRequest();
    inImg = cv::imread(img)
    Blob::Ptr imgBlob = inferRequest.GetBlob(inName);
    matU8ToBlob<unsigned char>(inImg, imgBlob, 0);
    inferRequest.SetBlob(inName, imgBlob);
    //inferRequest.SetBlob(inName, wrapMat2Blob(inImg));
    inferRequest.Infer();

从以上能看出一个叫做Blob的东西,ptr是指针(众所周知)
我们进去Blob::ptr 看看(ie_blob.h头文件):

// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

/**
 * @brief A header file for Blob and generic TBlob<>
 *
 * @file ie_blob.h
 */
#pragma once

#include <cstring>
#include <functional>
#include <map>
#include <memory>
#include <numeric>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

#include "details/ie_blob_iterator.hpp"
#include "details/ie_exception.hpp"
#include "details/ie_pre_allocator.hpp"
#include "ie_allocator.hpp"
#include "ie_common.h"
#include "ie_layouts.h"
#include "ie_locked_memory.hpp"
#include "ie_precision.hpp"

namespace InferenceEngine {
/**
 * @brief This class represents a universal container in the Inference Engine
 *
 * @note Each Blob implementation must be derived from this Blob class directly or indirectly
 */
class INFERENCE_ENGINE_API_CLASS(Blob) {
public:
    /**
     * @brief A smart pointer containing Blob object
     */
    using Ptr = std::shared_ptr<Blob>;

    /**
     * @brief A smart pointer to the const Blob object
     */
    using CPtr = std::shared_ptr<const Blob>;

    /**
     * @brief Creates a TBlob<> object from a Data node
     *
     * @param data A reference to a smart pointer of the Data node
     * @return Smart pointer to TBlob<> with the relevant C type to the precision of the data node
     */
    static Ptr CreateFromData(const DataPtr& data);

    /**
     * @brief Blob virtual destructor
     */
    virtual ~Blob();

    /**
     * @brief Checks if the Blob object can be cast to the type T*
     *
     * @tparam T Type to be checked. Must represent a class derived from the Blob
     * @return true if this object can be dynamically cast to the type T*. Otherwise, false
     */
    template <typename T,
              typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
              typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
    bool is() noexcept {
        return dynamic_cast<T*>(this) != nullptr;
    }

    /**
     * @brief Checks if the Blob object can be cast to the type const T*
     *
     * @tparam T Type to be checked. Must represent a class derived from the Blob
     * @return true if this object can be dynamically cast to the type const T*. Otherwise, false
     */
    template <typename T,
              typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
              typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
    bool is() const noexcept {
        return dynamic_cast<const T*>(this) != nullptr;
    }

    /**
     * @brief Casts this Blob object to the type T*.
     *
     * Use InferenceEngine::as() to operate with shared Blob objects instead of raw pointers
     *
     * @tparam T Type to cast to. Must represent a class derived from the Blob
     * @return Raw pointer to the object of the type T or nullptr on error
     */
    template <typename T,
              typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
              typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
    T* as() noexcept {
        return dynamic_cast<T*>(this);
    }

    /**
     * @brief Casts this Blob object to the type const T*.
     *
     * Use InferenceEngine::as() to operate with shared Blob objects instead of raw pointers
     *
     * @tparam T Type to cast to. Must represent a class derived from the Blob
     * @return Raw pointer to the object of the type const T or nullptr on error
     */
    template <typename T,
              typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
              typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
    const T* as() const noexcept {
        return dynamic_cast<const T*>(this);
    }

    /**
     * @brief Constructor. Creates an empty Blob object with the specified precision.
     *
     * @param tensorDesc Defines the layout and dims of the blob
     */
    explicit Blob(const TensorDesc& tensorDesc): tensorDesc(tensorDesc) {}

    /**
     * @brief Returns the tensor description
     */
    virtual const TensorDesc& getTensorDesc() const noexcept {
        return tensorDesc;
    }

    /**
     * @brief Returns the tensor description
     */
    virtual TensorDesc& getTensorDesc() noexcept {
        return tensorDesc;
    }

    /**
     * @brief By default, returns the total number of elements (a product of all the dims or 1 for scalar)
     *
     * Return value and its interpretation heavily depend on the blob type
     */
    virtual size_t size() const noexcept {
        if (tensorDesc.getLayout() == Layout::SCALAR) return 1;
        return product(tensorDesc.getDims());
    }

    /**
     * @brief Returns the size of the current Blob in bytes.
     */
    virtual size_t byteSize() const noexcept {
        return size() * element_size();
    }

    /**
     * @deprecated Cast to MemoryBlob and use its API instead.
     * Blob class can represent compound blob, which do not refer to the only solid memory.
     *
     * @brief Returns the number of bytes per element.
     *
     * The overall Blob capacity is size() * element_size(). Abstract method.
     */
    virtual size_t element_size() const noexcept = 0;

    /**
     * @brief Allocates memory to store the data.
     *
     * Abstract method.
     */
    virtual void allocate() noexcept = 0;

    /**
     * @brief Releases previously allocated data.
     *
     * Abstract method.
     */
    virtual bool deallocate() noexcept = 0;

    /**
     * @deprecated Cast to MemoryBlob and use new wlock/rwlock API instead.
     * Blob class can represent compound blob, which do not refer to the only solid memory.
     * @brief Gets access to the allocated memory.
     *
     * Abstract method.
     *
     * @return A LockedMemory object
     */
    virtual LockedMemory<void> buffer() noexcept = 0;

    /**
     * @deprecated Cast to MemoryBlob and use new MemoryBlob::rmap() function instead.
     * Blob class can represent compound blob, which do not refer to the only solid memory.
     * @brief Gets read-only access to the allocated memory.
     *
     * Abstract method.
     *
     * @return A LockedMemory object
     */
    virtual LockedMemory<const void> cbuffer() const noexcept = 0;

protected:
    /**
     * @brief The tensor descriptor of the given blob.
     */
    TensorDesc tensorDesc;

    /**
     * @deprecated Cast to MemoryBlob and use its API instead.
     * @brief Multiplies the dimension vector values.
     *
     * @param dims Reference to a vector with dimension values of type size_t
     * @return Result of multiplication
     */
    static size_t product(const SizeVector& dims) noexcept {
        if (dims.empty()) return 0;
        return std::accumulate(std::begin(dims), std::end(dims), (size_t)1, std::multiplies<size_t>());
    }

    /**
     * @brief Gets an allocator for allocator-based blobs
     *
     * @return The allocator for allocator-based blobs or nullptr if there is none
     */
    virtual const std::shared_ptr<IAllocator>& getAllocator() const noexcept = 0;

    /**
     * @brief Gets a handle to allocated memory
     *
     * @return The handle to allocated memory for allocator-based blobs or nullptr if there is none
     */
    virtual void* getHandle() const noexcept = 0;

    template <typename>
    friend class TBlobProxy;
};

/**
 * @brief Helper cast function to work with shared Blob objects
 *
 * @return shared_ptr to the type T. Returned shared_ptr shares ownership of the object with the
 *         input Blob::Ptr
 */
template <typename T,
          typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
          typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
std::shared_ptr<T> as(const Blob::Ptr& blob) noexcept {
    return std::dynamic_pointer_cast<T>(blob);
}

/**
 * @brief Helper cast function to work with shared Blob objects
 *
 * @return shared_ptr to the type const T. Returned shared_ptr shares ownership of the object with
 *         the input Blob::Ptr
 */
template <typename T,
          typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
          typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
std::shared_ptr<const T> as(const Blob::CPtr& blob) noexcept {
    return std::dynamic_pointer_cast<const T>(blob);
}

/**
 * @brief This class implements a container object that represents a tensor in memory (host and
 * remote/accelerated)
 *
 * @note Any Blob implementation that represents a concept of a tensor in memory (for example,
 * TBlob) must be a subclass of MemoryBlob instead of Blob
 */
class INFERENCE_ENGINE_API_CLASS(MemoryBlob): public Blob {
public:
    /**
     * @brief A smart pointer to the MemoryBlob object
     */
    using Ptr = std::shared_ptr<MemoryBlob>;

    /**
     * @brief A smart pointer to the const MemoryBlob object
     */
    using CPtr = std::shared_ptr<const MemoryBlob>;

    /**
     * @brief MemoryBlob virtual destructor
     */
    virtual ~MemoryBlob();

    /**
     * @brief Constructor. Creates an empty MemoryBlob object with the specified precision.
     *
     * @param tensorDesc Defines the layout and dims of the blob
     */
    explicit MemoryBlob(const TensorDesc& tensorDesc): Blob(tensorDesc) {}

    /**
     * @brief Returns the tensor description
     */
    const TensorDesc& getTensorDesc() const noexcept override {
        return tensorDesc;
    }

    /**
     * @brief Returns the tensor description
     */
    TensorDesc& getTensorDesc() noexcept override {
        return tensorDesc;
    }

    /**
     * @brief Returns the total number of elements, which is a product of all the dimensions
     */
    size_t size() const noexcept override {
        if (tensorDesc.getLayout() == Layout::SCALAR) return 1;
        return product(tensorDesc.getDims());
    }

    /**
     * @brief Returns the size of the current Blob in bytes calculated as `size() * element_size()`.
     * @return Blob's size in bytes
     */
    size_t byteSize() const noexcept override {
        return size() * element_size();
    }

    /**
     * @brief Provides the number of bytes per element.
     * Abstract method.
     * @return The number of bytes per element.
     */
    size_t element_size() const noexcept override = 0;

    /**
     * @brief Allocates memory to store the data.
     *
     * Abstract method.
     */
    void allocate() noexcept override = 0;

    /**
     * @brief Releases previously allocated data.
     *
     * Abstract method.
     * @return `True` if deallocation happens successfully, `false` otherwise.
     */
    bool deallocate() noexcept override = 0;

    /**
     * @deprecated Use wmap() or rwmap() API instead.
     * @brief Gets access to the allocated memory.
     *
     * Abstract method.
     *
     * @return A LockedMemory object
     */
    LockedMemory<void> buffer() noexcept override = 0;

    /**
     * @deprecated Use rmap() function instead.
     * @brief Gets read-only access to the allocated memory.
     *
     * Abstract method.
     *
     * @return A LockedMemory object
     */
    LockedMemory<const void> cbuffer() const noexcept override = 0;

    /**
     * @brief Gets read/write access to the memory in virtual space of the process.
     * The function returns object which retains mapped memory.
     * The memory been addressed in the MemoryBlob in general case can be allocated on remote device.
     * This function maps remote memory to the memory in the virtual process space and after destruction
     * of the LockedMemory will upload changed content to the accelerator.
     *
     * To avoid extra copy of data, you can use rmap() and wmap() functions.
     *
     * In case of memory originally allocated on the host, this function returns LockedMemory which will
     * transparently refer to original memory address. No extra copy will happen
     *
     * In general case, pointer received from that LockedMemory becomes invalid just after
     * destruction of LockedMemory instance. Keep Locked memory alive while you need to address memory
     * in the process on the host.
     *
     * Abstract method.
     *
     * @return A LockedMemory object
     */
    virtual LockedMemory<void> rwmap()noexcept = 0;

    /**
     * @brief Gets read only access to the memory in virtual space of the process.
     * The function returns object which retains mapped memory.
     *
     * The memory been addressed in the MemoryBlob in general case can be allocated on remote device.
     * This function copies remote memory to the memory in the virtual process space and after
     * destruction of the LockedMemory it will not upload host memory back, bacause it is expected that
     * content is not changed.
     *
     * To have an ability change content, you can use rwmap() and wmap() functions.
     *
     * In case of memory originally allocated on the host, this function returns LockedMemory which will
     * transparently refer to original memory address. No extra copy will happen
     *
     * In general case, pointer received from that LockedMemory becomes invalid just after destruction
     * of LockedMemory instance. Keep Locked memory alive while you need to address memory in the
     * process on the host.
     *
     * Abstract method.
     *
     * @return A LockedMemory object
     */
    virtual LockedMemory<const void> rmap()const noexcept = 0;

    /**
     * @brief Gets "write only direction" access to the memory in virtual space of the process.
     * The function returns object which retains memory to be uploaded on device.
     *
     * The memory been addressed in the MemoryBlob in general case can be allocated on remote device.
     * This function does not copy of the content from the device to the memory in the virtual process
     * space, the content of the memory just after calling of this functin is not specified. After
     * destruction of the LockedMemory, content will be upload host memory.
     * In the same time there is no abilities to restrict reading from the memory, you need to care of
     * reading from memory got by wmap(), it might have sence in some cases like filling of content and
     * before uploading to device
     *
     * To access data stored in the blob, you can use rwmap() and rmap() functions.
     *
     * In case of memory originally allocated on the host, this function returns LockedMemory which will
     * transparently refer to original memory address. No extra copy will happen
     *
     * In general case, pointer received from that LockedMemory becomes invalid just after destruction
     * of LockedMemory instance. Keep Locked memory alive while you need to address memory in the
     * process on the host.
     *
     * Abstract method.
     *
     * @return A LockedMemory object
     */
    virtual LockedMemory<void> wmap()noexcept = 0;



protected:
    /**
     * @brief Gets the allocator for allocator-based blobs.
     *
     * @return The allocator for allocator-based blobs or if there is none then a nullptr.
     */
    const std::shared_ptr<IAllocator>& getAllocator() const noexcept override = 0;

    /**
     * @brief Gets the handle to allocated memory.
     *
     * @return The handle to allocated memory for allocator-based blobs or if there is none then a nullptr.
     */
    void* getHandle() const noexcept override = 0;

    template <typename>
    friend class TBlobProxy;
};

/**
 * @brief This is a convenient type for working with a map containing pairs(string, pointer to a Blob instance).
 */
using BlobMap = std::map<std::string, Blob::Ptr>;

/**
 * @brief Represents real host memory allocated for a Tensor/Blob per C type.
 */
template <typename T, typename = std::enable_if<std::is_pod<T>::value>>
class TBlob : public MemoryBlob {
    template <typename, typename>
    friend class TBlob;

public:
    /**
     * @brief Smart Pointer to this TBlob object.
     */
    using Ptr = std::shared_ptr<TBlob<T>>;

    /**
     * @brief Creates a TBlob object with the specified dimensions and layout but does not allocate the memory.
     *
     * Use the allocate() method to allocate memory.
     *
     * @param tensorDesc Tensor description
     */
    explicit TBlob(const TensorDesc& tensorDesc): MemoryBlob(tensorDesc) {}

    /**
     * @brief The constructor creates a TBlob object with the specified dimensions and layout
     * on the pre-allocated memory.
     *
     * The allocate() call is not required.
     *
     * @param tensorDesc Tensor description
     * @param ptr Pointer to the pre-allocated memory
     * @param data_size Length of the pre-allocated array. If not set, size is assumed equal
     * to the dot product of dims.
     */
    TBlob(const TensorDesc& tensorDesc, T* ptr, size_t data_size = 0): MemoryBlob(tensorDesc) {
        if (data_size == 0) {
            data_size = size();
        }

        if (data_size != 0 && ptr == nullptr) {
            THROW_IE_EXCEPTION << "Using Blob on external nullptr memory";
        }

        _allocator = details::make_pre_allocator(ptr, data_size);
        // blob on attached memory is always allocated, so we are not forcing the user to call allocate()
        allocate();
    }

    /**
     * @brief Creates a TBlob object with the specified dimensions, layout and custom memory allocator but does not
     * allocate the memory.
     *
     * @param tensorDesc Tensor description
     * @param alloc An allocator
     */
    TBlob(const TensorDesc& tensorDesc, const std::shared_ptr<IAllocator>& alloc)
        : MemoryBlob(tensorDesc), _allocator(alloc) {
        if (_allocator == nullptr) THROW_IE_EXCEPTION << "TBlob allocator was not initialized.";
    }

    /**
     * @brief The copy constructor data is reallocated and copied from the source to the target blob.
     *
     * @param blob Source blob
     */
    TBlob(const TBlob<T>& blob): MemoryBlob(blob.getTensorDesc()) {
        copyFrom(blob);
    }

    /**
     * @brief A move constructor.
     *
     * @param blob rvalue to make a move from
     */
    TBlob(TBlob<T>&& blob): MemoryBlob(blob.getTensorDesc()) {
        moveFrom(blob);
    }

    /**
     * @brief Copy operator for the TBlob object.
     *
     * @param blob object reference to copy from
     * @return Newly copied object
     */
    TBlob& operator=(const TBlob& blob) {
        copyFrom(blob);
        return *this;
    }

    /**
     *@brief Virtual destructor.
     */
#ifdef __clang__
    virtual ~TBlob();
#else
    virtual ~TBlob() {
        free();
    }
#endif  // __clang__

    /**
     * @brief Gets the size of the given type.
     *
     * @return Size of the type
     */
    size_t element_size() const noexcept override {
        return sizeof(T);
    }

    /**
     * @brief Creates an new empty rvalue LockedMemory object.
     *
     * @return rvalue for the empty locked object of type T
     */
    virtual LockedMemory<T> data() noexcept {
        return std::move(lockme<T>());
    }

    /**
     * @brief Creates a new empty rvalue read-only LockedMemory object.
     *
     * @return rvalue for the empty locked const object of type T.
     */
    virtual LockedMemory<const T> readOnly() const noexcept {
        return std::move(lockme<const T>());
    }

    /**
     * @brief Allocates or reallocates memory
     */
    void allocate() noexcept override {
        if (_handle != nullptr) {
            getAllocator()->free(_handle);
        }
        _handle = getAllocator()->alloc(size() * sizeof(T));
    }

    /**
     * @brief Frees all allocated data
     */
    bool deallocate() noexcept override {
        return free();
    }

    /**
     * @brief Creates a new LockedMemory instance holding void pointer.
     *
     * @return LockedMemory instance holding void pointer
     */
    LockedMemory<void> buffer() noexcept override {
        return std::move(lockme<void>());
    }

    /**
     * @brief Creates a new LockedMemory instance holding constant void pointer.
     *
     * @return LockedMemory instance holding constant void pointer
     */
    LockedMemory<const void> cbuffer() const noexcept override {
        return std::move(lockme<const void>());
    }

    LockedMemory<void> rwmap()noexcept override {
        return std::move(lockme<void>());
    }

    LockedMemory<const void> rmap() const noexcept override {
        return std::move(lockme<const void>());
    }
    LockedMemory<void> wmap()noexcept override {
        return std::move(lockme<void>());
    }

    /**
     * @brief Gets BlobIterator for the data.
     *
     * Enables a ranged loop support for the TBlob object.
     *
     * @return BlobIterator object of type T
     */
    details::BlobIterator<T> begin() {
        return details::BlobIterator<T>(data());
    }

    /**
     * @brief Gets BlobIterator for the end of data.
     *
     * Enables a ranged loop support for the TBlob object.
     *
     * @return BlobIterator object of type T representing end of the data
     */
    details::BlobIterator<T> end() {
        return details::BlobIterator<T>(data(), size());
    }

    /**
     * @brief Gets a const BlobIterator for the read-only data.
     *
     * Enables a ranged loop support for the TBlob object.
     *
     * @return BlobIterator object of type const T
     */
    details::BlobIterator<const T> begin() const {
        return details::BlobIterator<const T>(readOnly());
    }

    /**
     * @brief Gets a const BlobIterator for the end of read-only data.
     *
     * Enables a ranged loop support for the TBlob object.
     *
     * @return BlobIterator object of type const T representing end of data
     */
    details::BlobIterator<const T> end() const {
        return details::BlobIterator<const T>(readOnly(), size());
    }

protected:
    /**
     * @brief Local instance of IAllocator to manipulate memory.
     */
    mutable std::shared_ptr<IAllocator> _allocator;

    /**
     * @brief A handle for the stored memory returned from _allocator.alloc().
     */
    void* _handle = nullptr;

    /**
     * @brief Copies dimensions and data from the TBlob object.
     *
     * @param blob object reference to copy from
     */
    void copyFrom(const TBlob<T>& blob) {
        tensorDesc = blob.tensorDesc;
        this->allocate();
        auto memptr = data();
        memcpy(memptr, blob.readOnly(), byteSize());
    }

    /**
     * @brief Swaps memory handlers between the current blob and the given one.
     *
     * @tparam U Type of the blob to move from
     * @param blob TBlob instance to move from
     */
    template <class U>
    void moveFrom(TBlob<U>& blob) {
        tensorDesc = blob.tensorDesc;
        this->_allocator = std::move(blob._allocator);
        std::swap(this->_handle, blob._handle);
    }

    /**
     * @brief Frees handler and cleans up the stored data.
     */
    virtual bool free() {
        bool bCanRelease = getAllocator()->free(_handle);
        _handle = nullptr;
        return bCanRelease;
    }

    /**
     * @brief Creates a LockedMemory instance.
     *
     * @tparam S Type of the LockedMemory to be created
     * @return A created instance of LockedMemory
     */
    template <class S>
    LockedMemory<S> lockme() const {
        return LockedMemory<S>(_allocator.get(), _handle, 0);
    }

    /**
     * @brief Gets an allocator or creates a default one.
     *
     * @return IAllocator instance
     */
    const std::shared_ptr<IAllocator>& getAllocator() const noexcept override {
        // in case when constructor without allocator was used
        if (!_allocator) {
            _allocator = shared_from_irelease(CreateDefaultAllocator());
        }

        return _allocator;
    }

    /**
     * @brief Returns handle to the stored data.
     */
    void* getHandle() const noexcept override {
        return _handle;
    }
};

#ifdef __clang__
extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<float>);
extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<double>);
extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<int16_t>);
extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<uint16_t>);
extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<int8_t>);
extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<uint8_t>);
extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<int>);
extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<long>);
extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<long long>);
extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<uint64_t>);
#endif  // __clang__

/**
 * @brief Creates a blob with the given tensor descriptor.
 *
 * @tparam Type Type of the shared pointer to be created
 * @param tensorDesc Tensor descriptor for Blob creation
 * @return A shared pointer to the newly created blob of the given type
 */
template <typename Type>
inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(const TensorDesc& tensorDesc) {
    if (!tensorDesc.getPrecision().hasStorageType<Type>())
        THROW_IE_EXCEPTION << "Cannot make shared blob! "
                           << "The blob type cannot be used to store objects of current precision";
    return std::make_shared<InferenceEngine::TBlob<Type>>(tensorDesc);
}

/**
 * @brief Creates a blob with the given tensor descriptor from the pointer to the pre-allocated memory.
 *
 * @tparam Type Type of the shared pointer to be created
 * @param tensorDesc TensorDesc for Blob creation
 * @param ptr Pointer to the pre-allocated memory
 * @param size Length of the pre-allocated array
 * @return A shared pointer to the newly created blob of the given type
 */
template <typename Type>
inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(const TensorDesc& tensorDesc, Type* ptr,
                                                                   size_t size = 0) {
    if (!tensorDesc.getPrecision().hasStorageType<Type>())
        THROW_IE_EXCEPTION << "Cannot make shared blob! "
                           << "The blob type cannot be used to store objects of current precision";
    return std::make_shared<InferenceEngine::TBlob<Type>>(tensorDesc, ptr, size);
}

/**
 * @brief Creates a blob with the given tensor descriptor and allocator.
 *
 * @tparam Type Type of the shared pointer to be created
 * @param tensorDesc Tensor descriptor for Blob creation
 * @param alloc Shared pointer to IAllocator to use in the blob
 * @return A shared pointer to the newly created blob of the given type
 */
template <typename Type>
inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(
    const TensorDesc& tensorDesc, const std::shared_ptr<InferenceEngine::IAllocator>& alloc) {
    if (!tensorDesc.getPrecision().hasStorageType<Type>())
        THROW_IE_EXCEPTION << "Cannot make shared blob! "
                           << "The blob type cannot be used to store objects of current precision";
    return std::make_shared<InferenceEngine::TBlob<Type>>(tensorDesc, alloc);
}

/**
 * @brief Creates a copy of given TBlob instance.
 *
 * @tparam TypeTo Type of the shared pointer to be created
 * @param arg given pointer to blob
 * @return A shared pointer to the newly created blob of the given type
 */
template <typename TypeTo>
inline typename InferenceEngine::TBlob<TypeTo>::Ptr make_shared_blob(const TBlob<TypeTo>& arg) {
    return std::make_shared<InferenceEngine::TBlob<TypeTo>>(arg);
}

/**
 * @brief Creates a Blob object of the specified type
 *
 * @param args Constructor arguments for the Blob object
 * @return A shared pointer to the newly created Blob object
 */
template <typename T, typename... Args, typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
std::shared_ptr<T> make_shared_blob(Args&&... args) {
    return std::make_shared<T>(std::forward<Args>(args)...);
}

/**
 * @brief This structure describes ROI data.
 */
struct ROI {
    size_t id;  //!< ID of a ROI
    size_t posX;  //!< W upper left coordinate of ROI
    size_t posY;  //!< H upper left coordinate of ROI
    size_t sizeX;  //!< W size of ROI
    size_t sizeY;  //!< H size of ROI
};

/**
 * @brief Creates a blob describing given ROI object based on the given blob with pre-allocated memory.
 *
 * @param inputBlob original blob with pre-allocated memory.
 * @param roi A ROI object inside of the original blob.
 * @return A shared pointer to the newly created blob.
 */
INFERENCE_ENGINE_API_CPP(Blob::Ptr) make_shared_blob(const Blob::Ptr& inputBlob, const ROI& roi);

}  // namespace InferenceEngine

头文件中有:


image.png

他是一个指向自己类的指针
再往下细分:
我们进入函数GetBlob:

    /**
     * @copybrief IInferRequest::GetBlob
     *
     * Wraps IInferRequest::GetBlob
     * @param name A name of Blob to get
     * @return A shared pointer to a Blob with a name @p name. If a blob is not found, an exception is thrown.
     */
    Blob::Ptr GetBlob(const std::string& name) {
        Blob::Ptr data;
        CALL_STATUS_FNC(GetBlob, name.c_str(), data);
        std::string error = "Internal error: blob with name `" + name + "` is not allocated!";
        auto blobPtr = data.get();
        if (blobPtr == nullptr) THROW_IE_EXCEPTION << error;
        if (blobPtr->buffer() == nullptr) THROW_IE_EXCEPTION << error;
        return data;
    }

先得到一个指针, data,再调用回调函数CALL_STATUS_FNC;

Blob::Ptr data;
CALL_STATUS_FNC(GetBlob, name.c_str(), data);

我们知道这里是给指针赋值:
指针类是怎么赋值的呢?或者说指针所谓的申请空间或者指向空间是怎么回事?请参照我的《北影之计算机入门》
进入回调函数:
在头文件中 ie_exception_conversion.hpp

#pragma once
#include <ie_common.h>

#define CALL_STATUS_FNC(function, ...)               \
    if (!actual)    THROW_IE_EXCEPTION << "Wrapper used in the CALL_STATUS_FNC was not initialized."; \
    ResponseDesc resp;                               \
    auto res = actual->function(__VA_ARGS__, &resp); \
    if (res != OK) InferenceEngine::details::extract_exception(res, resp.msg);

这是一个很简单的可变参函数(宏好像更合适),具体可参照《北影之计算机入门》
再细看

struct ResponseDesc {
    /**
     * @brief A character buffer that holds the detailed information for an error.
     */
    char msg[4096] = {};
};

也就是可变参函数中resp是一个结构体,占用4096个字节(41024),细节讲究,为什么是41024,解释起来也挺麻烦,参照《北影之计算机入门》,或者你自己百度也可以
返回可变函数部分:

 auto res = actual->function(__VA_ARGS__, &resp);
  if (res != OK) InferenceEngine::details::extract_exception(res, resp.msg);
//

actual是内存管理类中的auto,function是一个转移或者复制函数,语言新特性,这种基础问题,可查《北影之计算机入门》,或者自行百度
往下看会越来越简单
最终就是给某个结构体赋值


image.png

结构体系很简单,大部分都是和数据流打交道,慢慢看就行

针对图像数据类赋值可以通过以下方式,我们来研究下案例,其中的两个函数,

#include <chrono>
#include <iostream>
#include <string>
#include <vector>
#include <inference_engine.hpp>
#include <monitors/presenter.h>
#include <samples/common.hpp>
//#include <samples/ocv_common.hpp>
#include <opencv2/opencv.hpp>
#include <samples/slog.hpp>
#include <iostream>
template <typename T>
void matU8ToBlob(const cv::Mat& orig_image, InferenceEngine::Blob::Ptr& blob, int batchIndex = 0) {
    InferenceEngine::SizeVector blobSize = blob->getTensorDesc().getDims();
    const size_t width = blobSize[3];
    const size_t height = blobSize[2];
    const size_t channels = blobSize[1];
    if (static_cast<size_t>(orig_image.channels()) != channels) {
        THROW_IE_EXCEPTION << "The number of channels for net input and image must match";
    }
    InferenceEngine::LockedMemory<void> blobMapped = InferenceEngine::as<InferenceEngine::MemoryBlob>(blob)->wmap();
    T* blob_data = blobMapped.as<T*>();

    cv::Mat resized_image(orig_image);
    if (static_cast<int>(width) != orig_image.size().width ||
        static_cast<int>(height) != orig_image.size().height) {
        cv::resize(orig_image, resized_image, cv::Size(width, height));
    }

    int batchOffset = batchIndex * width * height * channels;

    
    if (channels == 1) {
        for (size_t h = 0; h < height; h++) {
            for (size_t w = 0; w < width; w++) {
                blob_data[batchOffset + h * width + w] = resized_image.at<uchar>(h, w);
            }
        }
    }
    else if (channels == 3) {
        for (size_t c = 0; c < channels; c++) {
            for (size_t h = 0; h < height; h++) {
                for (size_t w = 0; w < width; w++) {
                    blob_data[batchOffset + c * width * height + h * width + w] =
                        resized_image.at<cv::Vec3b>(h, w)[c];
                }
            }
        }
    }
    else {
        THROW_IE_EXCEPTION << "Unsupported number of channels";
    }
int main(){
     //只是为了看一个完整的函数
      return 0;
}

至于这个案例是基于我们对一系列Blob的研究,得知他就是某块内存的首地址,然后我们正常给他赋值就行,偏移其实很简单,
图像数据是怎么存的呢,简单介绍下,
很多场景是这样的,图像上看

1 2 3
4 5 6
7 8 9
....

【...
...


...

注释:【】代表通道,...代表数据
我们要转成blob的一维数据,怎么转,很简单,通道拉直继续计算
【1 2 3 4 5 6 7 8 9 .. .. . . . . . . . . ..】
通道拉直

此文不普及各种基础知识

[如果你还看不懂,支持手把手教学与原理讲解]

至于相关的图像处理,后续在增加或者修改

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352