天天看點

opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖

灰階圖轉僞彩色圖

數字圖像處理的作業,利用opencv實作通過灰階隐射将灰階圖轉化為僞彩色圖。

效果大概如下,在最後附帶opencv自帶函數處理的方法

opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖

原圖

opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖

周遊圖

opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖

opencv的 applyColorMap 函數處理圖像

1. 原理

根據色彩學方面的研究結果,将灰階圖像對應到red , green , blue三個通道上,最後将三個通道的顔色值合成為需要顯示的RGB顔色值即可。灰階值與三個通道的映射關系如下

opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖
opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖
opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖

粗略的分為四個區間,分别對rgb三種顔色對應的灰階進行映射。再簡單的調一下參數使其更加接近真實彩圖的樣子。

opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖

RGB=1:1:1

opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖

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方法]灰階圖轉僞彩色圖

2.1.2 split剝離通道方法

如果是三通道的圖像,那麼可以使用split()函數提取單通道圖像

Mat img = imread("lenna_gray.bmp", 0);
	namedWindow("原圖", WINDOW_AUTOSIZE);
	cv::imshow("原圖", img);
	vector<Mat> dst(3);//構造容器,用于儲存提取的通道
	split(img, dst);//使用split()函數提取
	Mat grayImage = dst[0];//容器的儲存順序按照BGR的順序
	imshow("gray", grayImage);//檢視單通道圖像是否成功提取
	cout<<grayImage.channels()<<endl;//檢視通道數
           

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函數實作加運算

示範一下兩張圖像的加運算結果

opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖
opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖
opencv周遊實作灰階圖轉僞彩色圖[C/C++][附applyColorMap方法]灰階圖轉僞彩色圖

2.2 通道讀寫與周遊簡單的思路小結

首先是提取出一個單通道的Mat,然後參考三張RGB對應gray的映射圖計算出RGB三色的參數

然後将其寫入到三通道的Mat對象中。輸出即可

3. 源碼

以下是全部代碼,需要opencv運作庫

#include<iostream>
#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<uchar>(row, col) = 255 - grayImg.at<uchar>(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方法]灰階圖轉僞彩色圖

代碼

#include<iostream>
#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

後續有修改可能隻會在原文更新

繼續閱讀