如何将内存映像分配给DLIB阵列2d或映像

How to assign memory images to a DLIB array2d or image?

本文关键字:映像 DLIB 阵列 2d 分配 内存      更新时间:2023-10-16

这可能更像是一个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-

基于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

我花了更多时间在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:VStudioProjectsdlib-masterdlib/algs.h"
#include "C:VStudioProjectsdlib-masterdlib/interfaces/enumerable.h"
#include "C:VStudioProjectsdlib-masterdlib/serialize.h"
#include "C:VStudioProjectsdlib-masterdlib/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"
<< "ntThe column index given must be less than the number of columns."
<< "ntthis:    " << this
<< "ntcolumn:  " << column
<< "ntnc(): " << 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)"
<< "ntThe column index given must be less than the number of columns."
<< "ntthis:    " << this
<< "ntcolumn:  " << column
<< "ntnc(): " << 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)"
<< "nt The arrayEd can't have negative rows or columns."
<< "nt this: " << this
<< "nt cols: " << cols
<< "nt 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_)"
<< "ntThe row index given must be less than the number of rows."
<< "ntthis:     " << this
<< "ntrow_:      " << row_
<< "ntnr(): " << 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"
<< "ntThe row index given must be less than the number of rows."
<< "ntthis:     " << this
<< "ntrow_:      " << row_
<< "ntnr(): " << 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()()"
<< "ntYou can only call element() when you are at a valid one."
<< "ntthis:    " << this
);
return *cur;
}
T& element(
)
{
// make sure requires clause is not broken
DLIB_ASSERT(current_element_valid() == true,
"tT& arrayEd::element()()"
<< "ntYou can only call element() when you are at a valid one."
<< "ntthis:    " << 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)"
<< "ntThe arrayEd can't have negative rows or columns."
<< "ntthis: " << this
<< "ntcols: " << cols
<< "ntrows: " << 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;
};
// ----------------------------------------------------------------------------------------

}