Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving an image with imwrite in opencv writes all black but imshow shows correctly

Tags:

c++

opencv

Original Question

This example code will display the image created correctly, but will save a png with only black pixels. The Mat is in CV_32FC3 format, so 3 channels of floats.

The answered questions I've found deal with image manipulation issues or converting incorrectly or saving in jpeg with various compression.

#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;
}

What changes need to be made to make it save as expected?

Berriel's Solution

#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;
    }
like image 324
USERID_UNK Avatar asked May 04 '16 11:05

USERID_UNK


People also ask

How do you save pictures on cv2 Imwrite?

In this example, we will read an image, transform it and then save the image to persistent file storage using imwrite() method. import cv2 #read image as grey scale img = cv2. imread('D:/image-1. png') #do some transformations on img #save matrix/array as image file isWritten = cv2.

Where does cv2 Imwrite save the image?

cv2. imwrite() method is used to save an image to any storage device. This will save the image according to the specified format in current working directory.

Does cv2 Imwrite overwrite?

Does cv2 Imwrite overwrite Python? imwrite will overwrite existing files without outputting an error or asking for confirmation. Image of any format can be saved using this method.

Why is cv2 Imread not working?

If you are receiving a NoneType error and your code is calling cv2. imread , then the likely cause of the error is an invalid file path supplied to cv2. imread . The cv2.


1 Answers

As you can read in the 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.

You should use convertTo to convert from CV_32FC3 to CV_8UC3 to get the same result:

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

By the way, imshow() displays correctly because...

  • 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].

Basically, the same trick is what you need to do before writing.

like image 172
Berriel Avatar answered Sep 18 '22 13:09

Berriel