opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]

灰度图转伪彩色图

数字图像处理的作业,利用opencv实现通过灰度隐射将灰度图转化为伪彩色图。

效果大概如下,在最后附带opencv自带函数处理的方法

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第1张图片

原图

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第2张图片

遍历图

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第3张图片

opencv的 applyColorMap 函数处理图像

1. 原理

根据色彩学方面的研究结果,将灰度图像对应到red , green , blue三个通道上,最后将三个通道的颜色值合成为需要显示的RGB颜色值即可。灰度值与三个通道的映射关系如下

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第4张图片

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第5张图片

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第6张图片

粗略的分为四个区间,分别对rgb三种颜色对应的灰度进行映射。再简单的调一下参数使其更加接近真实彩图的样子。

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第7张图片

RGB=1:1:1

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第8张图片

RGB=1:0.1:-1

具体的映射参数参照和后期的RGB参数调整一定会有更优的选择,主要是掌握方法。

接下来就是具体的实现过程

2. 实现过程

2.1 使用到的方法/函数

2.1.1 imread与imshow

opencv里面读图和现实图像经常会用到的 imread()和imshow()函数

这里只有一点要注意,在读入图像的时候imread的flag参数要为0或者是CV_LOAD_IMAGE_GRAYSCALE

在这里也逼逼一下参数的区别,flag<0是以原图读入 flag=0 是灰度图 flag>0是RGB读入

虽然这是一张灰度图,而且我也只需要单通道图像的参数。opencv读入的灰度图是单通道的,这个可以使用img.channels()返回的参数来验证,当你没有设置imread()参数的时候,虽然看起来是灰度图,但实际上却是3通道的图像

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第9张图片

2.1.2 split剥离通道方法

如果是三通道的图像,那么可以使用split()函数提取单通道图像

Mat img = imread("lenna_gray.bmp", 0);
	namedWindow("原图", WINDOW_AUTOSIZE);
	cv::imshow("原图", img);
	vector dst(3);//构造容器,用于储存提取的通道
	split(img, dst);//使用split()函数提取
	Mat grayImage = dst[0];//容器的储存顺序按照BGR的顺序
	imshow("gray", grayImage);//查看单通道图像是否成功提取
	cout<

2.1.3 图片容器

创建图片容器的方法

Mat imgBlue = Mat(grayImage.rows, grayImage.cols, CV_8UC3);

2.1.4 通道读写与遍历

创建一个名字为imgBlue的Mat类型,长宽与grayImage相同的8位(0-255)三通道Mat类型变量

int rows = grayImage.rows;;
int cols = grayImage.cols;

这两个int类型是获取Mat类型变量的行数和列数,用于稍后的遍历操作

接着就是重头戏了,是对于单通道和三通道Mat类型的像素遍历,方法又很多种,我这边选择较为简单的at方法。

2.1.4.1 单通道图像反色

附上一个简单的单通道图像反色方法

for (int row = 0; row < rows; row++) {
		for (int col = 0; col < cols; col++) {
			grayImg.at<uchar>(row, col) = 255 - grayImg.at<uchar>(row, col);
		}
	}//grayImg是CV_8UC1类型
2.1.4.2 多通道遍历
Mat imgs;
img.copyTo(imgs);//将img的内容复制到imgs
for (int row = 0; row < rows; row++) {
		for (int col = 0; col < cols; col++) {//对BGR三通道遍历读写
			imgs.at<Vec3b>(row, col)[2] = imgBlue.at<Vec3b>(row, col)[2];
			imgs.at<Vec3b>(row, col)[1] = imgGreen.at<Vec3b>(row, col)[1];
			imgs.at<Vec3b>(row, col)[0] = imgRed.at<Vec3b>(row, col)[0];

		}
	}//imgRed/Green/Blue都是CV_8UC3类型

单通道和三通道图像的遍历操作大概就是这样。多用几次就熟悉了。

2.1.5 加运算

最后我选择的是加运算,大致原理以一个像素点来演示

point1 =[128,128,128] point2 =[1 ,1 ,1 ]

对point1和point2进行加运算 输出到point3 = [129,129,129]

在opencv里面使用add函数实现加运算

add(imgRed, imgGreen, result);

演示一下两张图像的加运算结果

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第10张图片

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第11张图片

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第12张图片

2.2 通道读写与遍历简单的思路小结

首先是提取出一个单通道的Mat,然后参考三张RGB对应gray的映射图计算出RGB三色的参数

然后将其写入到三通道的Mat对象中。输出即可

3. 源码

以下是全部代码,需要opencv运行库

#include
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
//RGB通道参数,目前效果较好的为
//0.5 0.15 -0.9 
#define REDCOLOR_POINT 0.5
#define GREENCOLOR_POINT 0.15
#define BLUECOLOR_POINT -0.9
//通道
#define RED_CHANNELS 2
#define GREEN_CHANNEL 1
#define BLUE_CHANNEL 0
int main() {
	cout << "第八周图像处理实验" << endl;
	Mat img = imread("lenna_gray.bmp", 0);
	namedWindow("原图", WINDOW_AUTOSIZE);
	cv::imshow("原图", img);
	cout <<  "img的通道数为" << img.channels() << endl;;
	Mat result;
	//开始提取通道
	vector<Mat> dst(3);
	split(img, dst);
	Mat grayImage = dst[0];
	imshow("gray", grayImage);//单通道图像
	Mat imgBlue = Mat(grayImage.rows, grayImage.cols, CV_8UC3);
	Mat imgRed = Mat(grayImage.rows, grayImage.cols, CV_8UC3);
	Mat imgGreen = Mat(grayImage.rows, grayImage.cols, CV_8UC3);
	int rows = grayImage.rows;;
	int cols = grayImage.cols;
	for (int row = 0; row < rows; row++) {
		for (int col = 0; col < cols; col++) {
			//grayImg.at(row, col) = 255 - grayImg.at(row, col);
			int grayColor = grayImage.at<uchar>(row, col);
			int redColor = 0, greenColor = 0, blueColor = 0;
			if (grayColor >= 0 && grayColor < 64)//区间1-green
			{//r=0/g->up/b=255
				redColor = 0;
				blueColor = 255;
				//greenColor = grayColor * GRAY2RGB_POINT;
				greenColor = 255 / 64 * grayColor;
				//greenColor = 0;
			}
			else if (grayColor >= 64 && grayColor < 128)//区间2-blue
			{//r=0/g=255/b->down
				redColor = 0;
				greenColor = 255;
				//blueColor = 255 - (grayColor - 64) * GRAY2RGB_POINT;
				blueColor = -255 / 63 * (grayColor - 192) + 255;
			}
			else if (grayColor >= 128 && grayColor < 192)//区间3-red
			{//r->up/g=255/b=0
				greenColor = 255;
				blueColor = 0;
				//redColor = (grayColor - 128) * GRAY2RGB_POINT;
				redColor = 255 / 64 * (grayColor - 128);
			}
			else if (grayColor >= 192 && grayColor < 255)//区间4-green
			{//r=255/b=0/g->down
				redColor = 255;
				blueColor = 0;
				//greenColor = 255 - ((grayColor - 192) * GRAY2RGB_POINT);
				greenColor = -255 / 63 * (grayColor - 192) + 255;
			}
			//写入部分
			imgRed.at<Vec3b>(row, col)[RED_CHANNELS] = redColor*REDCOLOR_POINT;
			imgRed.at<Vec3b>(row, col)[GREEN_CHANNEL] = 0;
			imgRed.at<Vec3b>(row, col)[BLUE_CHANNEL] = 0;
			imgGreen.at<Vec3b>(row, col)[RED_CHANNELS] = 0;
			imgGreen.at<Vec3b>(row, col)[GREEN_CHANNEL] = greenColor*GREENCOLOR_POINT;
			imgGreen.at<Vec3b>(row, col)[BLUE_CHANNEL] = 0;
			imgBlue.at<Vec3b>(row, col)[RED_CHANNELS] = 0;
			imgBlue.at<Vec3b>(row, col)[GREEN_CHANNEL] = 0;
			imgBlue.at<Vec3b>(row, col)[BLUE_CHANNEL] = blueColor* BLUECOLOR_POINT;
		}
	}
	cv::imshow("red", imgRed);
	cv::imshow("green", imgGreen);
	cv::imshow("blue", imgBlue);
	//图像遍历
	Mat rgbImg = Mat(grayImage.rows, grayImage.cols, CV_8UC3);
	cout << "rgbImg的通道数为"<<rgbImg.channels();
		}
	}
	add(imgRed, imgGreen, result);
	add(result, imgBlue, result);
	imshow("rgbImg", result);
	waitKey(0);
	return 0;
}

4. 使用applyColorMap实现

效果

opencv遍历实现灰度图转伪彩色图[C/C++][附applyColorMap方法]_第13张图片

代码

#include
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main() {
	Mat img = imread("lenna_gray.bmp", 0);
	Mat dst;
	applyColorMap(img, dst, COLORMAP_JET);
	cv::imshow("dst", dst);
	waitKey(0);
	return 0;
}

参考:灰度图像的伪彩色处理_Python_michaelhan3的博客-CSDN博客

原文地址:http://blog.twentyy.cn/index.php/CV/cv-gray2rgb.html

后续有修改可能只会在原文更新

你可能感兴趣的:(数字图像处理,opencv)