2014-05-17 397 views
1

我想將SVG圖形轉換爲OpenCV Mat對象。因此,SVG圖形被加載到QSvgRenderer對象,之後轉換成從我使用它的原始數據創建我最終墊目標一個QImage的對象:通過使用原始數據將QImage轉換爲cv :: 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,這看起來像是一個簡單的方法來完成它。

回答

2

由於constBits確實沒有工作,它並不總是安全的假設,每行的字節數是一樣的(它會導致一個段錯誤對我來說)。我發現下面的建議中StereoMatching's anwser

cv::Mat(img.height(), img.width(), CV_8UC4, img.bits(), img.bytesPerLine()).clone() 

Baradé的有關使用位值得關注的是有效的,但因爲你克隆的結果,墊將從位複製數據,所以它不會是一個問題。

0

通常,cv :: Mat被引用,但這種情況很特殊。如果使用外部/借用數據指針,則必須克隆該墊,以確保它擁有其自己的像素副本,否則,只要您離開「scaleSvg()」的作用域, Mat'out'擁有'懸掛指針'。

你試圖'新'數據被複制,不幸的是,這並沒有解決它(你只是在那裏增加了另一個問題)。

您還必須自己刪除[] uchar *數據像素,而且您不需要,因此您的代碼當前將所有世界中最糟糕的結合起來。

相反,嘗試:

out = cv::Mat(image.height(), image.width(), CV_8UC4, image.constBits(), CV_AUTOSTEP).clone(); 
+0

感謝您的答案,但它不這樣工作。 constBits()不能被使用,因爲它返回一個const指針。當我使用bits()這似乎是錯誤的,因爲cv :: Mat的銷燬可能會釋放bits(),如果它使用引用計數機制(也許我錯了),即使在您發佈的語句中也會出現內存映射錯誤,而不是之後。 –