OpenCV-2.4.8.2:imshow 与 imwrite 不同

Posted

技术标签:

【中文标题】OpenCV-2.4.8.2:imshow 与 imwrite 不同【英文标题】:OpenCV-2.4.8.2: imshow differs from imwrite 【发布时间】:2015-04-23 06:22:30 【问题描述】:

我在 Mac OS 10.9.5 上使用 OpenCV2.4.8.2。 我有以下 sn-p 代码:

static void compute_weights(const vector<Mat>& images, vector<Mat>& weights)

    weights.clear();
    for (int i = 0; i < images.size(); i++) 
        Mat image = images[i];
        Mat mask = Mat::zeros(image.size(), CV_32F);
        int x_start = (i == 0) ? 0 : image.cols/2;
        int y_start = 0;
        int width = image.cols/2;
        int height = image.rows;
        Mat roi  = mask(Rect(x_start,y_start,width,height)); // Set Roi
        roi.setTo(1);
        weights.push_back(mask);
    


static void blend(const vector<Mat>& inputImages, Mat& outputImage)

    int maxPyrIndex = 6;
    vector<Mat> weights;
    compute_weights(inputImages, weights);

    // Find the fused pyramid:
    vector<Mat> fused_pyramid;
    for (int i = 0; i < inputImages.size(); i++) 
        Mat image = inputImages[i];
        // Build Gaussian Pyramid for Weights
        vector<Mat> weight_gaussian_pyramid;
        buildPyramid(weights[i], weight_gaussian_pyramid, maxPyrIndex);

        // Build Laplacian Pyramid for original image
        Mat float_image;
        inputImages[i].convertTo(float_image, CV_32FC3, 1.0/255.0);
        vector<Mat> orig_guassian_pyramid;
        vector<Mat> orig_laplacian_pyramid;
        buildPyramid(float_image, orig_guassian_pyramid, maxPyrIndex);
        for (int j = 0; j < orig_guassian_pyramid.size() - 1; j++) 
            Mat sized_up;
            pyrUp(orig_guassian_pyramid[j+1], sized_up, Size(orig_guassian_pyramid[j].cols, orig_guassian_pyramid[j].rows));
            orig_laplacian_pyramid.push_back(orig_guassian_pyramid[j] - sized_up);
        
        // Last Lapalcian layer is the same as the Gaussian layer
           orig_laplacian_pyramid.push_back(orig_guassian_pyramid[orig_guassian_pyramid.size()-1]);

        // Convolve laplacian original with guassian weights
        vector<Mat> convolved;
        for (int j = 0; j < maxPyrIndex + 1; j++) 
            // Create 3 channels for weight gaussian pyramid as well
            vector<Mat> gaussian_3d_vec;
            for (int k = 0; k < 3; k++) 
                gaussian_3d_vec.push_back(weight_gaussian_pyramid[j]);
            
            Mat gaussian_3d;
            merge(gaussian_3d_vec, gaussian_3d);

            //Mat convolved_result = weight_gaussian_pyramid[j].clone();
            Mat convolved_result = gaussian_3d.clone();

            multiply(gaussian_3d, orig_laplacian_pyramid[j], convolved_result);
            convolved.push_back(convolved_result);
        

        if (i == 0) 
            fused_pyramid = convolved;
         else 
            for (int j = 0; j < maxPyrIndex + 1; j++) 
                fused_pyramid[j] += convolved[j];
            
        
    
    // Blending
    for (int i = (int)fused_pyramid.size()-1; i > 0; i--) 
        Mat sized_up;
        pyrUp(fused_pyramid[i], sized_up, Size(fused_pyramid[i-1].cols, fused_pyramid[i-1].rows));
        fused_pyramid[i-1] += sized_up;
    

    Mat final_color_bgr;
    fused_pyramid[0].convertTo(final_color_bgr, CV_32F, 255);
    final_color_bgr.copyTo(outputImage);

    imshow("final", outputImage);
    waitKey(0);
    imwrite(outputImagePath, outputImage);

此代码正在对 2 张图像进行一些基本的金字塔混合。关键问题与最后一行中的 imshow 和 imwrite 有关。他们给了我截然不同的结果。对于显示如此长/混乱的代码,我深表歉意,但我担心这种差异来自代码的其他部分,这些部分随后会影响 imshow 和 imwrite。

根据给定的代码,第一张图片显示了 imwrite 的结果,第二张图片显示了 imshow 的结果。我很困惑为什么会这样。

我还注意到,当我这样做时:

Mat float_image;
inputImages[i].convertTo(float_image, CV_32FC3, 1.0/255.0);
imshow("float image", float_image);
imshow("orig image", image);

它们显示的内容完全相同,即它们都在原始 rgb 图像(图像中)中显示相同的图片。

【问题讨论】:

浮点值的 imshow 表示 0 = 黑色和 1 = 白色,因此全白图像可能具有错误比例的强度值。 嗨米卡,感谢您的回复。但是为什么imwrite是好的?你对比例是正确的。如果我在接近尾声时将其缩放 1,则 imshow 是可以的,但 imwrite 是全黑的...... 可能,imwrite 和 imshow 对值范围使用不同的假设;)您写入的文件扩展名是什么?也许该文件扩展名甚至可以直接处理浮点数,或者只执行类型转换而不缩放值(而 imshow 将浮点值乘以 255!)。 OpenCV 文档对 imwrite 说: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 因此,如果您的值在 0 和 1 之间缩放,您的 imwrite 会将值转换为 8 位通道值中的 0 或 1,这是非常黑色的。见文档:docs.opencv.org/modules/highgui/doc/… 谢谢 Micka 和下面的帖子。它解决了这个问题。 :) 【参考方案1】:

IMWRITE 功能

默认情况下,imwrite 将输入图像转换为 仅 8 位(或在 PNG、JPEG 2000 和 TIFF 的情况下为 16 位无符号 (CV_16U))单通道或 3 通道(具有“BGR”通道顺序)图像可以使用此功能保存。 因此,无论您为 imwrite 输入什么格式,它都会盲目地转换为 CV_8U,范围为 0(黑色)- 255(白色),采用 BGR 格式。

IMSHOW - 问题

所以当注意到你的函数时,fused_pyramid[0].convertTo(final_color_bgr, CV_32F, 255); fused_pyramid 已经在垫类型 21(浮点 CV_32F)下。您尝试使用比例因子 255 转换为浮点数。这个比例因子 255 导致了@imshow 的问题。代替可视化,您可以直接输入 fused_pyramid 而无需转换,因为它已经缩放到 0.0(black) - 1.0(white) 之间的浮点数。

希望对您有所帮助。

【讨论】:

谢谢斯里拉姆。你的解释很有见地。我再也不会犯这个错误了。

以上是关于OpenCV-2.4.8.2:imshow 与 imwrite 不同的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB中如何将imshow后的图片保存成原始大小的?

opencv Java构建中imshow的等效方法

MATLAB中imshow()和image()

matlab imshow()函数显示白色图像问题

Matlab常用图像处理命令108例

Matplotlib imshow 和 kivy