我想将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,这看起来像是一种简单的方法来完成它。
答案 0 :(得分:2)
由于constBits确实不起作用,并且假设每行的字节数相同(它会导致我的段错误)并不总是安全的。我在StereoMatching's anwser中找到了以下建议:
cv::Mat(img.height(), img.width(), CV_8UC4, img.bits(), img.bytesPerLine()).clone()
Baradé关于使用位的问题是有效的,但是因为你克隆了结果,Mat将从位复制数据,所以它不会成为问题。
答案 1 :(得分:0)
通常,cv :: Mat被重新计算,但这种情况很特殊。如果你使用外部/借用数据指针,你必须克隆()垫子,以确保它拥有自己的像素副本,否则,只要你离开&#39; scaleSvg的范围()&#39;,Mat&#39; out&#39;拥有一个悬垂的指针&#39;。
你尝试过新的&#39;遗憾的是,要复制的数据无法解决(你只在那里添加了另一个问题)。你也必须自己删除[]你自己的uchar *数据像素,而你不会这样,所以你的代码目前结合了最糟糕的世界。
相反,请尝试:
out = cv::Mat(image.height(), image.width(), CV_8UC4, image.constBits(), CV_AUTOSTEP).clone();