c++ - 在 opencv 中使用 imwrite 保存图像写入全黑但 imshow 显示正确

标签 c++ opencv

原始问题

此示例代码将正确显示创建的图像,但将保存只有黑色像素的 png。垫子采用 CV_32FC3 格式,因此有 3 个 float channel 。

我发现的已回答问题涉及图像处理问题或转换不正确或以各种压缩格式保存为 jpeg。

#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    int i = 0;
    int j = 0;

    Vec3f intensity;
     cv::Mat imageF;
    imageF= cv::Mat::zeros(36,36,CV_32FC3);

    for(j=0;j<imageF.cols;++j){
    for(i=0;i<imageF.rows;++i){
        intensity = imageF.at<Vec3f>(j, i);
        intensity.val[2] = 0.789347;
        intensity.val[1] = 0.772673;
        intensity.val[0] = 0.692689;
        imageF.at<Vec3f>(j, i) = intensity;
    }}
    imshow("Output", imageF);  
    imwrite("test.png", imageF);

    waitKey(0);
    return 0;
}

需要进行哪些更改才能使其按预期保存?

Berriel 的解决方案

#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main() {
    int i = 0;
    int j = 0;

    Vec3f intensity;
    cv::Mat imageF;
    cv::Mat image;
    imageF= cv::Mat::zeros(36,36,CV_32FC3);

    for(j=0; j<imageF.cols; ++j) {
        for(i=0; i<imageF.rows; ++i) {
            intensity = imageF.at<Vec3f>(j, i);
            intensity.val[2] = 0.789347;
            intensity.val[1] = 0.772673;
            intensity.val[0] = 0.692689;
            imageF.at<Vec3f>(j, i) = intensity;
            }
        }

    imshow("Output", imageF);

    Mat3b imageF_8UC3;
    imageF.convertTo(imageF_8UC3, CV_8UC3, 255);
    imwrite("test.png", imageF_8UC3);

    waitKey(0);
    return 0;
    }

最佳答案

正如您在 documentation 中所读到的那样:

The function imwrite saves the image to the specified file. The image format is chosen based on the filename extension (see imread() for the list of extensions). Only 8-bit (or 16-bit unsigned (CV_16U) in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with ‘BGR’ channel order) images can be saved using this function. If the format, depth or channel order is different, use Mat::convertTo() , and cvtColor() to convert it before saving.

您应该使用 convertToCV_32FC3 转换为 CV_8UC3 以获得相同的结果:

Mat3b imageF_8UC3;
imageF.convertTo(imageF_8UC3, CV_8UC3, 255);
imwrite("test.png", imageF_8UC3);

顺便说一下,imshow() 显示正确是因为...

  • If the image is 8-bit unsigned, it is displayed as is.
  • If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That is, the value range [0,255*256] is mapped to [0,255].
  • If the image is 32-bit floating-point, the pixel values are multiplied by 255. That is, the value range [0,1] is mapped to [0,255].

基本上,同样的技巧是你在写作之前需要做的。

关于c++ - 在 opencv 中使用 imwrite 保存图像写入全黑但 imshow 显示正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37026582/

相关文章:

c++ - A 内的 Gumbo HTML 文本

c++ - opencv立体标定结果

c++ - 使用 waitKey() 时无法打印像素值

c++ - 当用户单击 Twig 时,如何逐步构建 Qt 树形小部件?

c++ - 如何使用 Poco::Data 获取多个结果集?

opencv - 图像中的目标检测

c++ - 使用 opencv 显示视频

opencv - OpenCV轮廓

c++ - 动态可调阵列和 OpenMP

c++ - 在自定义类中定义 vector