Opencv关于imread和imwrite研习-Qt打开图像判断图像类型

11 篇文章 4 订阅

今天要写一个判断是否为二值图,灰度图,彩色图的程序,本来逻辑没问题,但是Qt按钮始终在彩色图

于是单独读入图片,调试程序,发现,二值图和灰度图都是三通道,百思不得解,原来

我使用的opencv imread默认读取三通道彩色图

读图像的时候imread()函数的第二个参数使用的是默认值,那么这个时候都是以color形式读取的,所有就又变回3通道了;下面是第二个参数的介绍

flags – Flags specifying the color type of a loaded image:
– CV_LOAD_IMAGE_ANYDEPTH - If set, return 16-bit/32-bit image when the input hasthe corresponding depth, otherwise convert it to 8-bit.
– CV_LOAD_IMAGE_COLOR - If set, always convert image to the color one
– CV_LOAD_IMAGE_GRAYSCALE - If set, always convert image to the grayscale one

代码如下:

然后重新测试,发现依然总是选中那一个按钮,找错,发现,我的图像有问题,灰度图和二值图竟然是三通道,寻找问题,发现,我的图像为了测试方便,直接在opencv中变换后使用imwrite保存,但是imwrite保存会出现上述问题,寻找资料,发现

参考博客:

https://www.jianshu.com/p/fed6a8a99625

比如我有如下的一个233M的图片

经过下面的程序读进内存,再次保存后,图片容量就急剧变小了!

#include<opencv2\opencv.hpp>   
#include<opencv2\highgui\highgui.hpp>

using namespace std;
using namespace cv;


int main(int argc, char** argv)
{
    Mat img = imread("src1.jpg");
    imwrite("test.jpg", img);

    return 0;
}

保存后的图片,只剩下126M了!怎么回事!我什么都没做啊,图片大小怎么就大大缩水了呢?

通过翻阅一些资料才知道,原来是图片格式惹得祸。其实有些图片格式是自带压缩的,比如jpg格式,而bmp格式的图片是不带任何压缩,这就是每种图片的特点,如果对这些知识点不清楚的话,很容易踩坑!平时我们操作的图像大小大多数都以KB为单位,所以经过一番“隐形压缩”后我们很难发现图片大小变小了,但是,当我们操作大图的时候,这种压缩效果一下子就看出来了。

那么如果我们在使用imwrite保存图片时想提高保存图片的质量,该如何操作?

要改变保存的图片的质量,关键在于imwrite函数的第三个参数。

先看imwrite的声明
CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, const std::vector<int>& params = std::vector<int>());

第三个参数说明:const std::vector

•对于JPEG格式的图片,这个参数表示从0-100的图片质量(CV_IMWRITE_JPEG_QUALITY),默认值是95.

•对于PNG格式的图片,这个参数表示压缩级别(CV_IMWRITE_PNG_COMPRESSION)从0-9.较高的值意味着更小的尺寸和更长的压缩时间而默认值是3.

•对于PPM,PGM或PBM格式的图片,这个参数表示一个二进制格式标志(CV_IMWRITE_PXM_BINARY),取值为0或1,而默认值为1.

调整jpg图像格式的保存质量

opencv的imwrite默认存储的jpg图片质量为95,如果想进一步提高保存图片的质量,可以这么写

代码如下

#include<opencv2\opencv.hpp>   
#include<opencv2\highgui\highgui.hpp>

using namespace std;
using namespace cv;


int main(int argc, char** argv)
{
    Mat img = imread("src1.jpg");

    vector<int> compression_params;
    compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);  //选择jpeg
    compression_params.push_back(100); //在这个填入你要的图片质量

    imwrite("test2.jpg", img, compression_params);

    return 0;
}

可以看出,经过参数调整后,jpg格式保存的图片的大小有了很大的提升。

但是无论如何,以jpg格式保存图片还是不能百分百保存原图像的!

但是即使我们把图片质量写成100,图片质量跟原图还是右一定压缩的,比如原图233M,读入再保存为jpg格式容量就变为229M。

那当我们不断读入图片,又不断存储图片为jpg格式,图片的质量就会不断降低!

所以有以下总结:

第一,opencv的存储图片函数imwrite是可以通过第三个函数参数来调整保存图片的压缩比的,比如保存图片为jpg格式,我们如果我们写成

第二,jpg格式的图片读进内存,如果再保存为jpg格式后,容量会被压缩的,这是jpg格式的特性,怎么调整压缩比都避免不了失真(损失图片质量)。

此时,二值图的保存和灰度图的保存就没问题了

这里我选择的是jepg即jpg,如果你要选择其他格式保存,记得更改格式

enum
{
    CV_IMWRITE_JPEG_QUALITY =1,
    CV_IMWRITE_JPEG_PROGRESSIVE =2,
    CV_IMWRITE_JPEG_OPTIMIZE =3,
    CV_IMWRITE_JPEG_RST_INTERVAL =4,
    CV_IMWRITE_JPEG_LUMA_QUALITY =5,
    CV_IMWRITE_JPEG_CHROMA_QUALITY =6,
    CV_IMWRITE_PNG_COMPRESSION =16,
    CV_IMWRITE_PNG_STRATEGY =17,
    CV_IMWRITE_PNG_BILEVEL =18,
    CV_IMWRITE_PNG_STRATEGY_DEFAULT =0,
    CV_IMWRITE_PNG_STRATEGY_FILTERED =1,
    CV_IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY =2,
    CV_IMWRITE_PNG_STRATEGY_RLE =3,
    CV_IMWRITE_PNG_STRATEGY_FIXED =4,
    CV_IMWRITE_PXM_BINARY =32,
    CV_IMWRITE_WEBP_QUALITY =64,
    CV_IMWRITE_PAM_TUPLETYPE = 128,
    CV_IMWRITE_PAM_FORMAT_NULL = 0,
    CV_IMWRITE_PAM_FORMAT_BLACKANDWHITE = 1,
    CV_IMWRITE_PAM_FORMAT_GRAYSCALE = 2,
    CV_IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA = 3,
    CV_IMWRITE_PAM_FORMAT_RGB = 4,
    CV_IMWRITE_PAM_FORMAT_RGB_ALPHA = 5,
};

还有一点错误,打开二值图的时候,会跳到灰度图,我的判断是只有

255和0,但是我用的是大津法求阈值,好像不是只有255和0,偶尔还有1,254,之类的,查看了下阈值函数

/** Threshold types */
enum
{
    CV_THRESH_BINARY      =0,  /**< value = value > threshold ? max_value : 0       */
    CV_THRESH_BINARY_INV  =1,  /**< value = value > threshold ? 0 : max_value       */
    CV_THRESH_TRUNC       =2,  /**< value = value > threshold ? threshold : value   */
    CV_THRESH_TOZERO      =3,  /**< value = value > threshold ? value : 0           */
    CV_THRESH_TOZERO_INV  =4,  /**< value = value > threshold ? 0 : value           */
    CV_THRESH_MASK        =7,
    CV_THRESH_OTSU        =8, /**< use Otsu algorithm to choose the optimal threshold value;
                                 combine the flag with one of the above CV_THRESH_* values */
    CV_THRESH_TRIANGLE    =16  /**< use Triangle algorithm to choose the optimal threshold value;
                                 combine the flag with one of the above CV_THRESH_* values, but not
                                 with CV_THRESH_OTSU */
};

如果使用了大津法之类的,需要其他方法判断,但是使用别的方法,需要自己判断阈值

纠结

 

最后我向现实屈服,先草率解决问题,有时间看源代码,看看为啥会有1和254等接近最大值最小值的数

 

最后附上,判断彩色图二值图灰度图的程序

if (text.channels() == 3){
		int a = 3;
	}
	else if (text.channels() == 1)
	{
		
		int rowNumber = text.rows;                           //获取图像矩阵行数
		int colNumber = text.cols;    //三通道图像每行元素个数为列数x通道数
		int pixelCount = 0;

		for (int i = 0; i < rowNumber; i++)
		{
			uchar* pixelPtr = text.ptr<uchar>(i);            //获取矩阵每行首地址指针
			for (int j = 0; j < colNumber; j++)
			{
				if (pixelPtr[j] != 0 && pixelPtr[j] != 255)
				{
					pixelCount++;
				}
			}
		}

		if (pixelCount == 0) //二值图
		{
			int c = 3;
		}
		else{
			int b = 3; //灰度图

		}

	}
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值