我制作了一个使用序列化Opencv矩阵的类。它工作正常,并且Matrix已反序列化。如果我尝试使用imshow方法在类的方法中显示它,它将很好地工作,并且显示没有错误。但是,我正在将参数引用从我的主函数传递给Matrix指针,以便进一步处理此矩阵。当我尝试将其主要显示时,我遇到了分段错误。 怪异的部分是,如果我尝试在class方法和Main方法中都显示矩阵,则最终会出现两个窗口正常运行的情况(有时会出现分段错误,但大多数情况下它运行良好)。 如果我从方法中删除显示代码,在出现分割错误之前,我什至无法显示一帧。
我尝试使用shared_ptr,将指针传递给指针而不是引用,甚至只是返回值。 我的代码有点凌乱,但它的主要目的是测试。
这是该方法的代码:
void VideoConsumer::getVideoFrame(cv::Mat* &mat) {
Message msg = _consumer->poll();
mat = NULL;
if(!msg) {
cerr << "No message received" << endl;
return;
}
if(msg.get_error()) {
if(!msg.is_eof()) {
cerr << "[+] Received error notification: " << msg.get_error() << endl;
}
return;
}
Document document;
string jsonPayload = "";
for(auto i=msg.get_payload().begin(); i != msg.get_payload().end();i++) {
jsonPayload += *i;
}
document.Parse(jsonPayload.c_str());
if(document.HasMember("rows") && document.HasMember("cols") && document.HasMember("data")) {
int rows = document["rows"].GetInt();
int cols = document["cols"].GetInt();
int type = document["type"].GetInt();
string data = document["data"].GetString();
std::vector<BYTE> decodedBytes = base64_decode(data);
stringstream ss;
for(int i=0;i< decodedBytes.size(); i++) {
ss << decodedBytes[i];
}
string decoded_data = ss.str();
cout << "Constructed string" << endl;
mat = new cv::Mat(rows,cols,type,(void *)decoded_data.data());
/*cv::imshow("test",*mat);
while(cv::waitKey(10) != 27)*/ //This is where it is displayed
return;
} else {
return;
}
}
以及主代码:
...
if(parser.has("stream")) {
VideoConsumer consumer("localhost:9092","video-stream-topic","testId2");
consumer.setConsumer();
while(1) {
Mat *frame = NULL;
consumer.getVideoFrame(frame);
if(frame == NULL) {
cout << "Null frame" << endl;
continue;
}
if(!frame->empty() && frame->rows > 0 && frame->cols > 0) {
imshow("Test",*frame);
waitKey(10);
frame->release();
}
}
}
我完全没有想法,尝试过我在研究中知道或发现的每件事。
编辑:添加了frame-> release()以释放分配,仍然是同样的问题。
答案 0 :(得分:2)
您的矩阵初始化中有一个问题...具体在这里:
mat = new cv::Mat(rows,cols,type,(void *)decoded_data.data());
就是那个构造函数
垫子(整数行,整数列,整数类型,无效*数据,size_t步= AUTO_STEP)
在documentation中,有关* data参数的内容如下
数据指向用户数据的指针。接受数据和 步骤参数不分配矩阵数据。相反,他们只是 初始化指向指定数据的矩阵头, 表示没有数据被复制。此操作非常有效,可以 用于使用OpenCV函数处理外部数据。外部 数据不会自动释放,因此您应该注意这一点。
这意味着,一旦超出范围(函数退出),您创建的字符串(decoded_data)将退出,数据将被该字符串释放,然后您的cv :: Mat将引用不再有效的数据...
您始终可以使用
之类的东西来初始化矩阵。cv::Mat(rows,cols,type)
,然后使用类似std :: memcpy之类的东西将数据复制到mat.data
成员。实际上,AFAIK不需要将字节传递给字符串,然后传递给mat,后者先转换为void,再传递给uchar。...
尝试类似的东西:
mat = cv::Mat(rows,cols,type);
std::memcpy(&decodedBytes[0], mat.data, decodedBytes.size());
对于此解决方案而言,这只是一个小警告,您需要检查decodedBytes
是否不为空,并且mat.data
是否有足够的空间来容纳decodedBytes
的所有内容。要执行此检查,只需确保:
// size in bytes to copy == size of the allocated data of mat in bytes
decodedBytes.size() == (mat.elemSize() * mat.rows * mat.cols)
还有几句话可能现在不是问题,但稍后可能会咬你: