opencv读取灰度图像

2 篇文章 0 订阅

本文档创建于2023年3月10日

本文记录了C++版opencv读取灰度图像的不同方式及区别

作者:RobotFreak

C++版的opencv读取灰度图像可以有不同的方法,这里列出几种方法,并简述它们的区别。

这里用到的两张图片为lena.jpg(彩色)和lena.bmp(灰度)
在这里插入图片描述
在这里插入图片描述

直接读取灰度图像

图像本身就是灰度图像,直接使用imread()读取图像:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("../lena.bmp"); //读取图片
	cout << "图片通道数: " << img.channels() << endl;
	cout << "图片行数: " << img.rows << " 图片列数: " << img.cols << endl;
    cout << img << endl;
	system("pause");

	return 0;
}

输出的信息如下:
在这里插入图片描述

可以看到直接读取灰度图像的情况下,虽然是灰度图像,但是读取的矩阵是3通道。这与灰度图像本身像素处只有灰度值一个值是不符合的。

图像读取时使用0或者IMREAD_GRAYSCALE,以灰度方式读取图图像

在调用imread时传入参数0或者IMREAD_GRAYSCALE:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("../lena.bmp",0); //读取图片
    //Mat img = imread("../lena.bmp",IMREAD_GRAYSCALE);
	cout << "图片通道数: " << img.channels() << endl;
	cout << "图片行数: " << img.rows << " 图片列数: " << img.cols << endl;
	cout << img << endl;
	system("pause");

	return 0;
}

打印信息如下:

在这里插入图片描述

可以看到,以灰度方式读取图像的结果,存储图像的矩阵是1通道。与上面对比,推测可能是默认按彩色3通道读取,需要指明用灰度方式读取才可以得到1通道的矩阵。而且与上方的矩阵对比发现,以默认3通道方式读取灰度图像,得到的每个像素的3个通道的值均是该像素处灰度值,把一份灰度值复制了3份。

下方是彩色图像按照默认3通道方式读取与按照灰度方式读取的打印信息对比:

  1. 彩色图像,默认3通道

在这里插入图片描述

  1. 彩色图像,灰度方式读取

在这里插入图片描述

算了一下彩色的3通道的均值,发现与imread按照灰度方式读取得到的矩阵结果不同,可能imread这个函数按照灰度方式读取内部并不是按照均值的方式处理的。

使用cvtColor()函数将图像转换为灰度图像

opencv内有cvtColor()函数用于颜色转换:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("../lena.jpg"); //读取图片
	cvtColor(img, img, COLOR_BGR2GRAY);
	cout << "图片通道数: " << img.channels() << endl;
	cout << "图片行数: " << img.rows << " 图片列数: " << img.cols << endl;
	cout << img << endl;
	system("pause");

	return 0;
}

打印的结果如下:

在这里插入图片描述

这个结果与使用灰度方式读取彩色图像的结果相同。

同时,我还试验了将灰度图像通过cvtColor转换为灰度图像。发现在以默认3通道方式读取后使用cvtColor也没问题,转换完之后变为了1通道;但是以灰度方式读取灰度图像后转换颜色报错。推测能够进行转换的条件是图像是3通道,而不是图像必须是彩色。

3通道取均值

将3通道图像的单个像素的3通道均值赋给另一个矩阵,得到灰度图像:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("../lena.jpg"); //读取图片
	Mat grayImg(img.rows, img.cols, CV_8UC1, Scalar(0)); //初始化目标矩阵
	for (int i = 0; i < img.rows; i++)
	{
		for (int j = 0; j < img.cols; j++)
		{
			grayImg.at<uchar>(i, j) = (img.at<Vec3b>(i, j)[0] + img.at<Vec3b>(i, j)[1] + img.at<Vec3b>(i, j)[2]) / 3;
		}
	}
	imshow("lena", img);
	imshow("lena-gray", grayImg);
	waitKey(0);

	return 0;
}

运行结果如下:

在这里插入图片描述

总结来说,我们想要的灰度图像为单通道的。不管原始图像是灰度图像还是彩色图像,我们都需要通过以下3中方法之一得到1通道的灰度图像:

  1. 以灰度方式读取图像imread(img,0)
  2. 使用cvtColor()函数转换为灰度图像
  3. 3通道取均值
  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RobotFreak

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值