创建垫子后从字节向量将图像加载到垫子上

Posted

技术标签:

【中文标题】创建垫子后从字节向量将图像加载到垫子上【英文标题】:Loading an image on a mat from a vector of bytes after the mat is created 【发布时间】:2013-08-04 16:03:24 【问题描述】:

接下来是我的情况:我正在开发一个多线程应用程序,其中 不同线程 从套接字以字节的形式接收图像,将它们存储在 vector<char> 中,并且应该生成cv::Mat 以便能够使用 OpenCV 进行处理。嗯,复杂性主要是因为为了将 每个线程的私有数据 与其他线程分开,我使用了一个 结构数组,我用所有的每个线程可能需要的数据结构。因此,我还必须在其中声明vector<char>cv::Mat,一旦向量接收到所有图像字节,我必须找到一种方法在cv::Mat 中适当地“加载它们”创建任何额外的,因为为每个线程保留的内存空间是固定的。


到目前为止我尝试过的:

struct thread_data                    //private data for threads
     std::vector<char> buf_img;
     Mat img_scene;
     Mat img_temp;
     //...

     thread_data()  
          buf_img.reserve(65000),      // initialization with enough space
      img_scene.create(700,500, CV_8U),
      img_temp.create(700,500, CV_8U);
          
    ;


thread_data *tdata;
// declare array of structs
tdata = (thread_data * ) calloc(nthreads, sizeof(thread_data));

//...

// And the thread function, once received the image:

private_tm->img_temp = cv::Mat(private_tm->buf_img,true).clone(); //from vector to Mat

if( !private_tm->img_temp.data )  
      std::cout<< " --(!) Image could not be read " << std::endl; 
      private_tm->answer = "error";

else 
    // decode image and call the function passing the pointer to the struct:
    private_tm->img_scene = cv::Mat(cv::imdecode(private_tm->temp,1)).clone();
private_tm->answer = OCV_func((void*)private_tm); 
 

接收一张图片后的结果:

> Thread 2:
> ==12142== Invalid write of size 4
> ==12142==    at 0x804B869: cv::Mat::release() (mat.hpp:369)
> ==12142==    by 0x804EEDD: cv::Mat::operator=(cv::Mat const&) (mat.hpp:287)
> ==12142==    by 0x804E8A2: thread_main(void*) (threads.cpp:408)
> ==12142==    by 0x45A4D4B: start_thread (pthread_create.c:308)
> ==12142==    by 0x46A7DDD: clone (clone.S:130)
> ==12142==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
> ==12142== 
> ==12142== 
> ==12142== Process terminating with default action of signal 11 (SIGSEGV)
> ==12142==  Access not within mapped region at address 0x0
> ==12142==    at 0x804B869: cv::Mat::release() (mat.hpp:369)
> ==12142==    by 0x804EEDD: cv::Mat::operator=(cv::Mat const&) (mat.hpp:287)
> ==12142==    by 0x804E8A2: thread_main(void*) (threads.cpp:408)
> ==12142==    by 0x45A4D4B: start_thread (pthread_create.c:308)
> ==12142==    by 0x46A7DDD: clone (clone.S:130)

我真的需要帮助,因为我觉得可能存在一个我看不到的简单解决方案。


一些研究:

-我在 OpenCV 文档中的 cv::Mat 声明中搜索了一个可以解决问题的函数,但我没有运气。我找不到不创建新 Mat 可能会获取图像(来自矢量、char* 或文件)的函数。 mat documentation

-这是我需要的类似问题(答案非常不满意):link

提前致谢。

【问题讨论】:

【参考方案1】:

你不能像现在这样使用calloc。它只会为thread_data 对象分配内存,但不会调用其构造函数或其子对象的构造函数。

更改以下内容...

thread_data *tdata;
// declare array of structs
tdata = (thread_data * ) calloc(nthreads, sizeof(thread_data));

到...

thread_data *tdata = new thread_data();

我强烈建议使用智能指针,例如std::unique_ptr,这样您就不必担心调用delete

std::unique_ptr<thread_data> tdata(new thread_data());

【讨论】:

感谢您的回答,但现在我收到了很多与 new 运算符的使用相关的 Conditional jump or move depends on uninitialised value(s)Invalid write of size 4。我想这可能是因为我在循环内创建每个线程之前做了tdata[i].thread_id= (pthread_t)i; tdata[i].thread_num=i;,但我不确定。

以上是关于创建垫子后从字节向量将图像加载到垫子上的主要内容,如果未能解决你的问题,请参考以下文章

将 cv::mat 转换为 QImage

iplimage 图像大小与垫子大小相同吗?

向量构造函数和垫子

如何将 2D 垫子组合成 3D 垫子?

如何使用 OpenCV 从垫子上裁剪任意形状?

c ++ opencv在窗口上显示图像