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

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

opencv python 灰度 opencv读取灰度图像_计算机视觉


opencv python 灰度 opencv读取灰度图像_计算机视觉_02

直接读取灰度图像

图像本身就是灰度图像,直接使用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;
}

输出的信息如下:

opencv python 灰度 opencv读取灰度图像_图像处理_03

可以看到直接读取灰度图像的情况下,虽然是灰度图像,但是读取的矩阵是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;
}

打印信息如下:

opencv python 灰度 opencv读取灰度图像_图像处理_04

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

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

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

opencv python 灰度 opencv读取灰度图像_计算机视觉_05

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

opencv python 灰度 opencv读取灰度图像_图像处理_06

算了一下彩色的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;
}

打印的结果如下:

opencv python 灰度 opencv读取灰度图像_图像处理_07

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

同时,我还试验了将灰度图像通过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;
}

运行结果如下:

opencv python 灰度 opencv读取灰度图像_opencv_08

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

  1. 以灰度方式读取图像imread(img,0)
  2. 使用cvtColor()函数转换为灰度图像
  3. 3通道取均值