[英]converting QImage to cv::Mat by using raw data
我想将SVG图形转换为OpenCV Mat对象。 因此,SVG图形被加载到QSvgRenderer对象中,然后转换为QImage对象,我从该对象使用其原始数据来创建最终的Mat对象:
void scaleSvg(const cv::Mat &in, QSvgRenderer &svg, cv::Mat &out)
{
if (!svg.isValid())
{
return;
}
QImage image(in.cols, in.rows, QImage::Format_ARGB32);
// Get QPainter that paints to the image
QPainter painter(&image);
svg.render(&painter);
std::cout << "Image byte count: " << image.byteCount() << std::endl;
std::cout << "Image bits: " << (int*)image.constBits() << std::endl;
std::cout << "Image depth: " << image.depth() << std::endl;
uchar *data = new uchar[image.byteCount()];
memcpy(data, image.constBits(), image.byteCount());
out = cv::Mat(image.height(), image.width(), CV_8UC4, data, CV_AUTOSTEP);
std::cout << "New byte count: " << out.size() << std::endl;
std::cout << "New depth: " << out.depth() << std::endl;
std::cout << "First bit: " << out.data[0] << std::endl;
}
不幸的是,将生成的对象写入文件时,出现“内存访问冲突”错误:
std::cout << (int*)out.data << std::endl; // pointer can still be accessed without errors
cv::imwrite("scaled.png", out); // memory access error
正在写入的文件的大小不超过33字节(仅标头数据?)。 互联网上有一些有关cv :: Mat中指针所有权的解释,我认为它将在最后一次引用它之后发布,因为“ out”是一个引用,所以不应该发布。 顺便说一句。 总是欢迎将SVG转换为cv :: Mat的另一种方法。 由于OpenCV似乎不支持SVG,因此这似乎是完成此操作的一种简单方法。
由于constBits确实无法正常工作,并且假设每行的字节数相同是不总是安全的(它对我造成了段错误)。 我在StereoMatching的anwser中发现了以下建议:
cv::Mat(img.height(), img.width(), CV_8UC4, img.bits(), img.bytesPerLine()).clone()
Baradé对使用位的担心是有效的,但是由于您克隆了结果,因此Mat将复制位的数据,因此这不是问题。
通常,cv :: Mat被重新引用,但是这种情况很特殊。 如果您使用外部/借用的数据指针,则必须克隆()垫子以确保其拥有自己的像素副本,否则,一旦离开'scaleSvg()'的范围,垫子“出”拥有“悬空指针”。
遗憾的是,您试图“ 复制 ” 要复制的数据 ,但这并不能解决问题(您仅在此处添加了另一个问题)。
您还必须自己删除[] uchar *数据像素,而不必这样做,因此,您的代码目前结合了世界上最糟糕的情况。
相反,尝试:
out = cv::Mat(image.height(), image.width(), CV_8UC4, image.constBits(), CV_AUTOSTEP).clone();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.