2017-02-01 7 views
1

Вероятно, это скорее вопрос C++, но он относится к DLIB. Я использую другую библиотеку для загрузки изображений в память (Leadtools). Я хочу заменить функцию load_image на присваивания, но мне трудно понять, как это сделать. У меня есть вся информация и память, выделенные мне из моей загрузки, такие как глубина пикселя, ширина, высота, width_step, rgb/bgr order и указатель на данные.Как назначить изображения памяти DLIB array2d или изображение?

Таким образом, в образце, есть:

array2d<bgr_pixel> img; 

Я могу это сделать:

img.set_size(mywidth, myheight); 

Но (при условии, mypointer данных является BGR смежный символ * байт):

img.data = mydatapointer; 

не работает - нет img.data, плюс я не могу понять, как использовать image_view.

Каков правильный способ установки этого указателя данных? Обратите внимание, что я НЕ хочу дублировать память :-)

Есть ли что-то еще, что необходимо для настройки имитации load_image и правильной структуры для использования в dlib?

ТИА

+0

К сожалению, я не считаю, что это возможно. Я просмотрел источник dlib, и указатель данных является приватным. Не похоже, что есть какой-либо способ установить его или получить его напрямую. – mascoj

+0

Я бы порекомендовал самостоятельно копать в источнике или связаться с разработчиком dlib, Davis King. – mascoj

+1

Dlib легко поддерживает это. Если вы хотите это сделать, вам нужно определить соответствующий общий интерфейс изображения для любого объекта изображения, который вы хотите использовать. См. Http: // dlib.net/dlib/image_processing/generic_image.h.html –

ответ

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, просто заменить array3d с Arrayed.

массивEd_kernel.h: (основная масса изменений). Добавлена ​​функция настройки и передана мне класс памяти, а также несколько переменных, чтобы отслеживать вещи.

#pragma once 
// Copyright (C) 2006 Davis E. King ([email protected]) 
// 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; 
}; 

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

}

+2

Это совсем не разумный способ сделать это. Все, что вам нужно сделать, это определить общие функции изображения для вашего класса изображений, CpwImage. Не создавайте новый класс, особенно тот, который является копией другой, чью реализацию вы не понимаете. –