簡體   English   中英

OpenCV 保存 CV_32FC1 圖像

[英]OpenCV save CV_32FC1 images

我正在使用的一個程序正在讀取一些位圖,並且需要 32FC1 圖像。

我正在嘗試創建這些圖像

cv::Mat M1(255, 255, CV_32FC1, cv::Scalar(0,0,0));
cv::imwrite( "my_bitmap.bmp", M1 );

但是當我檢查深度時 - 它總是 CV_8U

如何創建文件以便它們包含正確的信息?

更新:如果我使用不同的文件擴展名沒有區別 - 例如 tif 或 png

我正在閱讀它 - 使用已經實現的代碼 - 與cvLoadImage

我正在嘗試創建現有代碼(檢查圖像類型)可以使用的文件。

我無法轉換現有代碼中的文件。 現有代碼不會嘗試讀取隨機圖像類型並將其轉換為所需類型,而是檢查文件是否為所需類型。

我發現 - 謝謝你的回答 - cv::imwrite 只寫整數類型的圖像。

是否有另一種方法 - 使用 OpenCV 或其他方式 - 編寫圖像以便我最終得到 CV_32F 類型?

再次更新:讀取圖像的代碼...如果進入 cv::Mat:

cv::Mat x = cv::imread(x_files, CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR);

現有代碼:

IplImage *I = cvLoadImage(x_files.c_str(), CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR);

cv::imwrite() .bmp 編碼器假定 8 位通道。

如果你只需要用 OpenCV 編寫 .bmp 文件,你可以將你的 32FC1 圖像轉換為 8UC4,然后使用cv::imwrite()來編寫它,你將得到一個 32bits per pixel 的 .bmp 文件。 我猜你讀取文件的程序會將 32 位像素解釋為 32FC1。 .bmp 格式沒有明確的通道結構,只有每個像素的位數。 因此,您應該能夠在 OpenCV 中將 32 位像素寫為 4 個 8 位通道,並在另一個程序中將它們作為單通道 32 位像素讀取 - 如果您這樣做,您需要了解讀者的字節序假設。 像下面這樣的應該工作:

cv::Mat m1(rows, cols, CV_32FC1);
...  // fill m1
cv::Mat m2(rows, cols, CV_8UC4, m1.data); // provide different view of m1 data
// depending on endianess of reader, you may need to swap byte order of m2 pixels
cv::imwrite("my_bitmap.bmp", m2);

您將無法正確讀取在 OpenCV 中創建的文件,因為 OpenCV 中的 .bmp 解碼器假定文件是 1 或 3 通道的 8 位數據(即它無法讀取 32 位像素)。


編輯

可能更好的選擇是使用OpenEXR格式,OpenCV 有一個編解碼器。 我假設您只需要使用 .exr 擴展名保存文件。

您的問題是位圖在內部將數據存儲為整數而不是浮點數。 如果您的問題是保存時的舍入錯誤,您將需要使用不同的文件格式或在保存前放大數據,然后在保存后縮小。 如果您只想將讀取文件后獲得的矩陣轉換為浮點數,您可以使用 cv::convertto

我正在努力解決同樣的問題。 最后,我決定編寫一個可以編寫和加載任意 CV Mat 的自定義函數會更容易。

bool writeRawImage(const cv::Mat& image, const std::string& filename)
{
    ofstream file;
    file.open (filename, ios::out|ios::binary);
    if (!file.is_open())
        return false;
    file.write(reinterpret_cast<const char *>(&image.rows), sizeof(int));
    file.write(reinterpret_cast<const char *>(&image.cols), sizeof(int));
    const int depth = image.depth();
    const int type  = image.type();
    const int channels = image.channels();
    file.write(reinterpret_cast<const char *>(&depth), sizeof(depth));
    file.write(reinterpret_cast<const char *>(&type), sizeof(type));
    file.write(reinterpret_cast<const char *>(&channels), sizeof(channels));
    int sizeInBytes = image.step[0] * image.rows;
    file.write(reinterpret_cast<const char *>(&sizeInBytes), sizeof(int));
    file.write(reinterpret_cast<const char *>(image.data), sizeInBytes);
    file.close();
    return true;
}

bool readRawImage(cv::Mat& image, const std::string& filename)
{
    int rows, cols, data, depth, type, channels;
    ifstream file (filename, ios::in|ios::binary);
    if (!file.is_open())
        return false;
    try {
        file.read(reinterpret_cast<char *>(&rows), sizeof(rows));
        file.read(reinterpret_cast<char *>(&cols), sizeof(cols));
        file.read(reinterpret_cast<char *>(&depth), sizeof(depth));
        file.read(reinterpret_cast<char *>(&type), sizeof(type));
        file.read(reinterpret_cast<char *>(&channels), sizeof(channels));
        file.read(reinterpret_cast<char *>(&data), sizeof(data));
        image = cv::Mat(rows, cols, type);
        file.read(reinterpret_cast<char *>(image.data), data);
    } catch (...) {
        file.close();
        return false;
    }

    file.close();
    return true;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM