如何将内存映像分配给DLIB array2d或image?

时间:2017-02-01 23:19:13

标签: c++ dlib

这可能更像是一个c ++问题,但它与DLIB有关。我正在使用另一个库将图像加载到内存(Leadtools)。我想替换" load_image"功能与作业,但我无法弄清楚如何这样做。我拥有从负载中分配的所有信息和内存,例如像素位深度,宽度,高度,width_step,rgb / bgr顺序和指向数据的指针。

所以在样本中,有:

array2d<bgr_pixel> img;

我可以这样做:

img.set_size(mywidth, myheight);

但是(假设数据mypointer是bgr连续的char *字节):

img.data = mydatapointer;  

不起作用 - 没有img.data,而且我无法弄清楚如何使用image_view。

设置数据指针的正确方法是什么?请注意,我不想复制内存: - )

还有什么需要设置才能模拟load_image并在dlib中使用正确的结构吗?

TIA

2 个答案:

答案 0 :(得分:0)

我通过花费更多时间在DLIB上找到答案。与C ++无关。我很少使用模板,所以一开始就是压倒性的。

需要做的是按照建议创建一些遵循通用图像模型的标题。我选择使用array2d作为指南。通过创建类似的标题,以及添加一个函数来映射到我在内存中的图像,我能够使用图像数据而不重复它。

顺便说一句,请注意width_step(每行的字节数)。我必须设置它,因为我有很多图像填充。请参阅下面的代码。

为了节省很多时间,这就是我所做的,命名新结构arrayEd。刚刚使用了arrayEd而不是array3d。

如果有人对此代码有任何意见,欢迎: - )

arrayEd.h:

#pragma once
#include "arrayEd_kernel.h"
#include "serialize_pixel_overloads_arrayEd.h"
#include "arrayEd_generic_image.h"

对于serialize_pixel_overloads_arrayEd.h,刚刚用arrayEd替换了array3d。

arrayEd_kernel.h :(大部分更改)。添加了函数设置并将其传递给我的内存图像类,以及一些变量来跟踪事物。

#pragma once
// Copyright (C) 2006  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.

#include "C:\VStudioProjects\dlib-master\dlib/algs.h"
#include "C:\VStudioProjects\dlib-master\dlib/interfaces/enumerable.h"
#include "C:\VStudioProjects\dlib-master\dlib/serialize.h"
#include "C:\VStudioProjects\dlib-master\dlib/geometry/rectangle.h"

namespace dlib
{
template <
    typename T,
    typename mem_manager = default_memory_manager
>
    class arrayEd : public enumerable<T>
{

    /*!
    INITIAL VALUE
    - nc_ == 0
    - nr_ == 0
    - data == 0
    - at_start_ == true
    - cur == 0
    - last == 0

    CONVENTION
    - nc_ == nc()
    - nr_ == nc()
    - if (data != 0) then
    - last == a pointer to the last element in the data array
    - data == pointer to an array of nc_*nr_ T objects
    - else
    - nc_ == 0
    - nr_ == 0
    - data == 0
    - last == 0


    - nr_ * nc_ == size()
    - if (cur == 0) then
    - current_element_valid() == false
    - else
    - current_element_valid() == true
    - *cur == element()

    - at_start_ == at_start()
    !*/


    class row_helper;
public:

    // These typedefs are here for backwards compatibility with older versions of dlib.
    typedef arrayEd kernel_1a;
    typedef arrayEd kernel_1a_c;

    typedef T type;
    typedef mem_manager mem_manager_type;

    // -----------------------------------
    bool bIsAllocatedHere;  //ec this is used to tell whether or not the memory came from here - if so, we clean it up.
    long lWidthStep;   // number of bytes in a row. This comes from leadtools and is set when we setup the image in setup()

    class row
    {
        /*!
        CONVENTION
        - nc_ == nc()
        - for all x < nc_:
        - (*this)[x] == data[x]
        !*/

        friend class arrayEd<T, mem_manager>;
        friend class row_helper;

    public:
        long nc(
        ) const {
            return nc_;
        }

        const T& operator[] (
            long column
            ) const
        {
            // make sure requires clause is not broken
            DLIB_ASSERT(column < nc() && column >= 0,
                "\tconst T& arrayEd::operator[](long column) const"
                << "\n\tThe column index given must be less than the number of columns."
                << "\n\tthis:    " << this
                << "\n\tcolumn:  " << column
                << "\n\tnc(): " << nc()
            );

            return data[column];
        }

        T& operator[] (
            long column
            )
        {
            // make sure requires clause is not broken
            DLIB_ASSERT(column < nc() && column >= 0,
                "\tT& arrayEd::operator[](long column)"
                << "\n\tThe column index given must be less than the number of columns."
                << "\n\tthis:    " << this
                << "\n\tcolumn:  " << column
                << "\n\tnc(): " << nc()
            );

            return data[column];
        }

    private:

        row(T* data_, long cols) : data(data_), nc_(cols) {}

        T* data;
        long nc_;


        // restricted functions
        row() {}
        row& operator=(row&);
    };

    // -----------------------------------

    arrayEd(
    ) :
        data(0),
        nc_(0),
        nr_(0),
        cur(0),
        last(0),
        at_start_(true),
        bIsAllocatedHere(false),
        lWidthStep(0)
    {
    }

    arrayEd(
        long rows,
        long cols
    ) :
        data(0),
        nc_(0),
        nr_(0),
        cur(0),
        last(0),
        at_start_(true),
        bIsAllocatedHere(false),
        lWidthStep(0)
    {
        // make sure requires clause is not broken
        DLIB_ASSERT((cols >= 0 && rows >= 0),
            "\t arrayEd::arrayEd(long rows, long cols)"
            << "\n\t The arrayEd can't have negative rows or columns."
            << "\n\t this: " << this
            << "\n\t cols: " << cols
            << "\n\t rows: " << rows
        );

        set_size(rows, cols);
    }

#ifdef DLIB_HAS_RVALUE_REFERENCES
    arrayEd(arrayEd&& item) : arrayEd()
    {
        swap(item);
    }

    arrayEd& operator= (
        arrayEd&& rhs
        )
    {
        swap(rhs);
        return *this;
    }
#endif

    virtual ~arrayEd(
    ) {
        clear();
    }

    long nc(
    ) const {
        return nc_;
    }

    long nr(
    ) const {
        return nr_;
    }

    row operator[] (
        long row_
        )
    {
        // make sure requires clause is not broken
        DLIB_ASSERT(row_ < nr() && row_ >= 0,
            "\trow arrayEd::operator[](long row_)"
            << "\n\tThe row index given must be less than the number of rows."
            << "\n\tthis:     " << this
            << "\n\trow_:      " << row_
            << "\n\tnr(): " << nr()
        );

        return row(data + row_*nc_, nc_);
    }

    const row operator[] (
        long row_
        ) const
    {
        // make sure requires clause is not broken
        DLIB_ASSERT(row_ < nr() && row_ >= 0,
            "\tconst row arrayEd::operator[](long row_) const"
            << "\n\tThe row index given must be less than the number of rows."
            << "\n\tthis:     " << this
            << "\n\trow_:      " << row_
            << "\n\tnr(): " << nr()
        );

        return row(data + row_*nc_, nc_);
    }

    void swap(
        arrayEd& item
    )
    {
        exchange(data, item.data);
        exchange(nr_, item.nr_);
        exchange(nc_, item.nc_);
        exchange(at_start_, item.at_start_);
        exchange(cur, item.cur);
        exchange(last, item.last);
        pool.swap(item.pool);
    }

    void clear(
    )
    {
        if (data != 0)
        {
            // ec we might manage this memory at the leadtools level 
            if (bIsAllocatedHere)
                pool.deallocate_array(data);
            nc_ = 0;
            nr_ = 0;
            data = 0;
            at_start_ = true;
            cur = 0;
            last = 0;
            bIsAllocatedHere = false;
        }
    }

    void set_size(
        long rows,
        long cols
    );

    bool at_start(
    ) const {
        return at_start_;
    }

    void reset(
    ) const {
        at_start_ = true; cur = 0;
    }

    bool current_element_valid(
    ) const {
        return (cur != 0);
    }

    const T& element(
    ) const
    {
        // make sure requires clause is not broken
        DLIB_ASSERT(current_element_valid() == true,
            "\tconst T& arrayEd::element()()"
            << "\n\tYou can only call element() when you are at a valid one."
            << "\n\tthis:    " << this
        );

        return *cur;
    }

    T& element(
    )
    {
        // make sure requires clause is not broken
        DLIB_ASSERT(current_element_valid() == true,
            "\tT& arrayEd::element()()"
            << "\n\tYou can only call element() when you are at a valid one."
            << "\n\tthis:    " << this
        );

        return *cur;
    }

    bool move_next(
    ) const
    {
        if (cur != 0)
        {
            if (cur != last)
            {
                ++cur;
                return true;
            }
            cur = 0;
            return false;
        }
        else if (at_start_)
        {
            cur = data;
            at_start_ = false;
            return (data != 0);
        }
        else
        {
            return false;
        }
    }

    unsigned long size(
    ) const {
        return static_cast<unsigned long>(nc_ * nr_);
    }

    long width_step(
    ) const
    {
        if (lWidthStep == 0)  // inc ase image not allocated by leadtools
            return nc_ * sizeof(T);
        else
            return lWidthStep;
    }

    // eds setup fcn
    int setup(CpwImage& img)
    {
        data = (T *)img.AccessBitmap();
        nc_ = img.GetWidth();
        nr_ = img.GetHeight();
        cur = last = 0;
        at_start_ = (true);
        lWidthStep = img.GetBytesPerLine();
        if (data != 0)
            return 1;
        return 0;
    }

private:


    T* data;
    long nc_;
    long nr_;

    typename mem_manager::template rebind<T>::other pool;
    mutable T* cur;
    T* last;
    mutable bool at_start_;

    // restricted functions
    arrayEd(arrayEd&);        // copy constructor
    arrayEd& operator=(arrayEd&);    // assignment operator

};

// ----------------------------------------------------------------------------------------

template <
    typename T,
    typename mem_manager
>
    inline void swap(
        arrayEd<T, mem_manager>& a,
        arrayEd<T, mem_manager>& b
    ) {
    a.swap(b);
}


template <
    typename T,
    typename mem_manager
>
    void serialize(
        const arrayEd<T, mem_manager>& item,
        std::ostream& out
    )
{
    try
    {
        // The reason the serialization is a little funny is because we are trying to
        // maintain backwards compatibility with an older serialization format used by
        // dlib while also encoding things in a way that lets the arrayEd and matrix
        // objects have compatible serialization formats.
        serialize(-item.nr(), out);
        serialize(-item.nc(), out);

        item.reset();
        while (item.move_next())
            serialize(item.element(), out);
        item.reset();
    }
    catch (serialization_error e)
    {
        throw serialization_error(e.info + "\n   while serializing object of type arrayEd");
    }
}

template <
    typename T,
    typename mem_manager
>
    void deserialize(
        arrayEd<T, mem_manager>& item,
        std::istream& in
    )
{
    try
    {
        long nr, nc;
        deserialize(nr, in);
        deserialize(nc, in);

        // this is the newer serialization format
        if (nr < 0 || nc < 0)
        {
            nr *= -1;
            nc *= -1;
        }
        else
        {
            std::swap(nr, nc);
        }

        item.set_size(nr, nc);

        while (item.move_next())
            deserialize(item.element(), in);
        item.reset();
    }
    catch (serialization_error e)
    {
        item.clear();
        throw serialization_error(e.info + "\n   while deserializing object of type arrayEd");
    }
}

// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------

template <
    typename T,
    typename mem_manager
>
    void arrayEd<T, mem_manager>::
    set_size(
        long rows,
        long cols
    )
{
    // make sure requires clause is not broken
    DLIB_ASSERT((cols >= 0 && rows >= 0),
        "\tvoid arrayEd::set_size(long rows, long cols)"
        << "\n\tThe arrayEd can't have negative rows or columns."
        << "\n\tthis: " << this
        << "\n\tcols: " << cols
        << "\n\trows: " << rows
    );

    // set the enumerator back at the start
    at_start_ = true;
    cur = 0;

    // don't do anything if we are already the right size.
    if (nc_ == cols && nr_ == rows)
    {
        return;
    }

    if (data != 0)
    {
        DLIB_ASSERT(0, "Something wrong - this csoi image type should not be REsetting size");
        return;
    }

    nc_ = cols;
    nr_ = rows;

    // free any existing memory
    if (data != 0)
    {
        pool.deallocate_array(data);
        data = 0;
    }

    // now setup this object to have the new size
    try
    {
        if (nr_ > 0)
        {
            data = pool.allocate_array(nr_*nc_);
            last = data + nr_*nc_ - 1;
            bIsAllocatedHere = true;
        }
    }
    catch (...)
    {
        if (data)
            pool.deallocate_array(data);

        data = 0;
        nc_ = 0;
        nr_ = 0;
        last = 0;
        throw;
    }
}
// ----------------------------------------------------------------------------------------

template <typename T>
struct is_arrayEd : public default_is_kind_value
{
    /*!
    - if (T is an implementation of array2d/array2d_kernel_abstract.h) then
    - is_array2d<T>::value == true
    - else
    - is_array2d<T>::value == false
    !*/
};

// ----------------------------------------------------------------------------------------

template <typename T, typename MM>
struct is_arrayEd <arrayEd<T, MM> >
{
    const static bool value = true;
};

// ----------------------------------------------------------------------------------------

}

答案 1 :(得分:0)

基于戴维斯·金(Davis King)的评论。

为避免将数据从您自己的图像结构复制到dlib内部格式,dlib允许您实现一个通用的图像接口,该接口将允许dlib直接使用您的图像。需要实现的接口如下:

    In dlib, an "image" is any object that implements the generic image interface.  In
    particular, this simply means that an image type (let's refer to it as image_type
    from here on) has the following seven global functions defined for it:
        - long        num_rows      (const image_type& img)
        - long        num_columns   (const image_type& img)
        - void        set_image_size(      image_type& img, long rows, long cols)
        - void*       image_data    (      image_type& img)
        - const void* image_data    (const image_type& img)
        - long        width_step    (const image_type& img)
        - void        swap          (      image_type& a, image_type& b)
     And also provides a specialization of the image_traits template that looks like:
        namespace dlib
        {
            template <> 
            struct image_traits<image_type>
            {
                typedef the_type_of_pixel_used_in_image_type pixel_type;
            };
        }

您可以在此处找到更多详细信息: http://dlib.net/dlib/image_processing/generic_image.h.html