將彩色圖片轉換為灰階圖是影像處理中常見的步驟之一。這個過程之所以重要,是因為彩色圖片通常包含豐富的色彩信息,但在某些情況下,我們可能更關心影像的細節、結構和特徵,而不是顏色。將圖片轉換為灰階能夠去除色彩的影響,使得我們能夠更專注於影像的亮度變化。
除此之外,灰階圖片也更加節省數據儲存空間和記憶體,因為每個像素只需要一個數值來表示亮度,而不需要分別表示紅、綠、藍三個通道的數值。這種數據的簡化有助於加速影像處理運算,降低計算成本。
在將彩色圖片轉換為灰階圖時,我們需要將每個像素的紅、綠、藍三個顏色通道的數值組合成一個單一的灰階值。為了達到這個目的,我們通常使用加權平均的方式,將這些通道的數值相應地加權組合起來。
灰階值是介於0和255之間的一個數值,代表了像素的亮度。而彩色影像的每個像素都由紅、綠、藍三個通道的顏色數值組成。在計算灰階值時,我們可以使用以下的加權平均公式:
這裡的0.299、0.587和0.114代表了紅、綠、藍三個顏色加權係數,加權值的總和等於1。這種加權平均的方式考慮了人眼對不同顏色的敏感度,因此可以得到比較自然的灰階影像。
這個程式碼提供了兩種運算方式,一個是使用OpenCV內建的函式,另一個是使用蜂巢迴圈實現的演算法,兩者效果一樣。你可以透過設定USE_OPENCV
成1
或0
來決定你要使用前者還是後者的實現方式。
#define USE_OPENCV 1
cv::cvtColor
函數用於影像的顏色空間的轉換,不只可以將圖片轉成灰階,還可以轉換到其他的色彩空間像是HSV、HSL,之後的主題會講解到這個函式的其他應用。
cv::cvtColor(colorImage, grayImage, cv::COLOR_BGR2GRAY);
colorImage
:原始彩色影像。grayImage
:用於儲存轉換後的灰階影像。cv::COLOR_BGR2GRAY
:表示從 BGR 彩色空間轉換到灰階空間的轉換方式。int width = colorImage.cols;
int height = colorImage.rows;
grayImage=cv::Mat(height, width, CV_8UC1);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
cv::Vec3b pixel = colorImage.at<cv::Vec3b>(y, x);
uchar grayValue = 0.299 * pixel[2] + 0.587 * pixel[1] + 0.114 * pixel[0];
grayImage.at<uchar>(y, x) = grayValue;
}
}
LOG_LEVEL_SILENT
,使OpenCV不輸出任何日誌訊息。colorImage
的cv::Mat
中。USE_OPENCV
的值,有兩種不同的轉換方式:
USE_OPENCV
為1,則使用OpenCV的cv::cvtColor
函式將colorImage
轉換為灰階影像USE_OPENCV
為0,則使用自己編寫的程式碼遍歷每個像素,按照灰度化公式計算灰階值,並將其存儲在grayImage
中。cv::imshow
函式。原始彩色影像顯示在窗口"Color Image"中,而灰階影像則顯示在窗口"Gray Image"中。cv::waitKey(0)
等待使用者按下鍵盤按鈕,直到使用者關閉窗口,然後程式結束運行。#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/utils/logger.hpp>
#define USE_OPENCV 1
int main() {
cv::utils::logging::setLogLevel(cv::utils::logging::LogLevel::LOG_LEVEL_SILENT);
// 讀取圖片
cv::Mat colorImage = cv::imread("C:\\Users\\vince\\Downloads\\Lenna.png", cv::IMREAD_UNCHANGED);
// 創建灰階影像
cv::Mat grayImage;
#if USE_OPENCV
// 使用OpenCV轉換彩色影像為灰階
cv::cvtColor(colorImage, grayImage, cv::COLOR_BGR2GRAY);
#else
int width = colorImage.cols;
int height = colorImage.rows;
grayImage = cv::Mat(height, width, CV_8UC1);
// 遍歷每個像素,手動計算灰階值
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// 獲取彩色影像中的像素值
cv::Vec3b pixel = colorImage.at<cv::Vec3b>(y, x);
// 計算灰階值
uchar grayValue = 0.299 * pixel[2] + 0.587 * pixel[1] + 0.114 * pixel[0];
// 將灰階值設置到對應位置
grayImage.at<uchar>(y, x) = grayValue;
}
}
#endif
// 顯示原始彩色圖和轉換後的灰階圖
cv::imshow("Color Image", colorImage);
cv::imshow("Gray Image", grayImage);
cv::waitKey(0);
return 0;
}
一張灰階的Lenna圖就這樣顯示出來啦!