【问题标题】:How to assign memory images to a DLIB array2d or image?如何将内存图像分配给 DLIB array2d 或图像?
【发布时间】:2017-06-18 21:37:08
【问题描述】:

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

所以在示例中,有:

array2d<bgr_pixel> img;

我可以这样做:

img.set_size(mywidth, myheight);

但是(假设数据 mypointer 是 bgr contiguous char * bytes):

img.data = mydatapointer;  

不起作用 - 没有 img.data,而且我不知道如何使用 image_view。

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

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

TIA

【问题讨论】:

  • 对不起,我不相信这是可能的。我浏览了 dlib 源,数据指针是私有的。似乎没有任何方法可以直接设置或检索它。
  • 我建议您自己挖掘源代码,或者联系 dlib 的开发者 Davis King。
  • Dlib 很容易支持这一点。如果你想这样做,你需要为你想使用的任何图像对象定义适当的通用图像接口。见:dlib.net/dlib/image_processing/generic_image.h.html
  • @Davis - 谢谢,我明白了,但细节超出了我的 C++ 技能。甚至不知道如何开始使用模板。我会在哪里放置这样的结构?我可以填写位以返回适当的值(例如,行数、指针等)。数据是标准像素特征之一(rgb、rgba 等)。对此的任何帮助表示赞赏。
  • 它甚至不需要是模板。无论如何,您需要先学习 C++,然后才能使用 C++。我们正在谈论的这件事是您可以想象的最基本的 C++ 编程任务之一。因此,如果您不能做到这一点,那么您需要获得一本 C++ 书籍并学习 C++,例如其中之一:dlib.net/books.html

标签: c++ dlib


【解决方案1】:

基于戴维斯·金的评论。

为避免将数据从您自己的图像结构复制到 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

【讨论】:

    【解决方案2】:

    我花更多时间在 DLIB 上找到了答案。与C++无关。我很少使用模板,所以一开始就不知所措。

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

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

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

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

    arrayEd.h:

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

    对于 serialize_pixel_overloads_arrayEd.h,只需将 array3d 替换为 arrayEd。

    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;
    };
    
    // ----------------------------------------------------------------------------------------
    

    }

    【讨论】:

    • 这根本不是一个合理的方法。您需要做的就是为您的图像类 CpwImage 定义通用图像全局函数。不要创建一个新类,尤其是复制粘贴另一个你不理解其实现的类。
    猜你喜欢
    • 2019-12-26
    • 2018-09-29
    • 2012-06-07
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多