数字图像处理的作业,利用opencv实现通过灰度隐射将灰度图转化为伪彩色图。
效果大概如下,在最后附带opencv自带函数处理的方法
原图
遍历图
opencv的 applyColorMap 函数处理图像
根据色彩学方面的研究结果,将灰度图像对应到red , green , blue三个通道上,最后将三个通道的颜色值合成为需要显示的RGB颜色值即可。灰度值与三个通道的映射关系如下
粗略的分为四个区间,分别对rgb三种颜色对应的灰度进行映射。再简单的调一下参数使其更加接近真实彩图的样子。
RGB=1:1:1
RGB=1:0.1:-1
具体的映射参数参照和后期的RGB参数调整一定会有更优的选择,主要是掌握方法。
接下来就是具体的实现过程
opencv里面读图和现实图像经常会用到的 imread()和imshow()函数
这里只有一点要注意,在读入图像的时候imread的flag参数要为0或者是CV_LOAD_IMAGE_GRAYSCALE
在这里也逼逼一下参数的区别,flag<0是以原图读入 flag=0 是灰度图 flag>0是RGB读入
虽然这是一张灰度图,而且我也只需要单通道图像的参数。opencv读入的灰度图是单通道的,这个可以使用img.channels()返回的参数来验证,当你没有设置imread()参数的时候,虽然看起来是灰度图,但实际上却是3通道的图像
如果是三通道的图像,那么可以使用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<
创建图片容器的方法
Mat imgBlue = Mat(grayImage.rows, grayImage.cols, CV_8UC3);
创建一个名字为imgBlue的Mat类型,长宽与grayImage相同的8位(0-255)三通道Mat类型变量
int rows = grayImage.rows;;
int cols = grayImage.cols;
这两个int类型是获取Mat类型变量的行数和列数,用于稍后的遍历操作
接着就是重头戏了,是对于单通道和三通道Mat类型的像素遍历,方法又很多种,我这边选择较为简单的at方法。
附上一个简单的单通道图像反色方法
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类型
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类型
单通道和三通道图像的遍历操作大概就是这样。多用几次就熟悉了。
最后我选择的是加运算,大致原理以一个像素点来演示
point1 =[128,128,128] point2 =[1 ,1 ,1 ]
对point1和point2进行加运算 输出到point3 = [129,129,129]
在opencv里面使用add函数实现加运算
add(imgRed, imgGreen, result);
演示一下两张图像的加运算结果
首先是提取出一个单通道的Mat,然后参考三张RGB对应gray的映射图计算出RGB三色的参数
然后将其写入到三通道的Mat对象中。输出即可
以下是全部代码,需要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;
}
效果
代码
#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
后续有修改可能只会在原文更新