一、灰度變換的原理:
通過變換函數(shù)T將原圖像像素灰度值r映射為灰度值s: s=T(r).
二、灰度變換的方法:
-
線性變換(亮度和對比度調(diào)整):
- 原理:線性變換是一種簡單的亮度和對比度調(diào)整方法,通過對每個(gè)像素的灰度級別應(yīng)用線性變換公式來實(shí)現(xiàn)。對每個(gè)像素應(yīng)用公式
output_pixel = input_pixel * alpha + beta
,其中alpha
控制對比度,beta
控制亮度。增大alpha
值可以增加對比度,增大beta
值可以增加亮度。
- 原理:線性變換是一種簡單的亮度和對比度調(diào)整方法,通過對每個(gè)像素的灰度級別應(yīng)用線性變換公式來實(shí)現(xiàn)。對每個(gè)像素應(yīng)用公式
-
對數(shù)變換:
- 原理:對數(shù)變換通過應(yīng)用對數(shù)函數(shù)對圖像的每個(gè)像素值進(jìn)行修改。這種變換適用于增強(qiáng)圖像的低灰度級別,因?yàn)樗炝说突叶燃墑e之間的差異。公式為
output_pixel = c * log(1 + input_pixel)
,其中c
是縮放常數(shù)。
- 原理:對數(shù)變換通過應(yīng)用對數(shù)函數(shù)對圖像的每個(gè)像素值進(jìn)行修改。這種變換適用于增強(qiáng)圖像的低灰度級別,因?yàn)樗炝说突叶燃墑e之間的差異。公式為
-
伽馬校正:
- 原理:伽馬校正通過應(yīng)用冪函數(shù)對圖像的每個(gè)像素值進(jìn)行修改。伽馬校正可以用于調(diào)整圖像的對比度和亮度。公式為
output_pixel = c * (input_pixel ^ gamma)
,其中c
是縮放常數(shù),gamma
是伽馬值。增大gamma
值可以增加對比度。
- 原理:伽馬校正通過應(yīng)用冪函數(shù)對圖像的每個(gè)像素值進(jìn)行修改。伽馬校正可以用于調(diào)整圖像的對比度和亮度。公式為
-
直方圖均衡化:
- 原理:直方圖均衡化旨在拉伸圖像的灰度級別分布,使其更均勻。這通過重新分配像素值以增加亮度級別的數(shù)量來實(shí)現(xiàn)。這有助于增強(qiáng)圖像的對比度,并突出圖像中的細(xì)節(jié)。該方法的原理是重新映射圖像的累積分布函數(shù),使其變?yōu)榫鶆蚍植肌?/li>
-
自適應(yīng)直方圖均衡化:
- 原理:自適應(yīng)直方圖均衡化將圖像劃分為小塊,然后對每個(gè)塊進(jìn)行直方圖均衡化。這使得圖像在不同區(qū)域的灰度級別分布更加均勻,尤其是當(dāng)圖像具有明顯的亮度變化時(shí)。
三、線性變換
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main() {
// 加載圖像
Mat image = imread("D://lena.png");
if (image.empty()) {
cout << "無法加載圖像" << endl;
return -1;
}
// 用戶定義的亮度和對比度參數(shù)
double alpha = 1.5; // 控制對比度
int beta = 30; // 控制亮度
// 線性變換
Mat adjusted_image = Mat::zeros(image.size(), image.type());
for (int y = 0; y < image.rows; y++) {
for (int x = 0; x < image.cols; x++) {
for (int c = 0; c < image.channels(); c++) {
adjusted_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(alpha * image.at<Vec3b>(y, x)[c] + beta);
}
}
}
// 顯示原始圖像和調(diào)整后的圖像
imshow("原始圖像", image);
imshow("亮度和對比度調(diào)整后的圖像", adjusted_image);
waitKey(0);
return 0;
}
函數(shù)介紹:
// 線性變換
Mat adjusted_image = Mat::zeros(image.size(), image.type());
Mat::zeros
是OpenCV中的一個(gè)函數(shù),用于創(chuàng)建一個(gè)矩陣(圖像)并將其所有元素初始化為零。在這個(gè)特定的情況下,Mat::zeros(image.size(), image.type())
用于創(chuàng)建一個(gè)與 image
具有相同尺寸和通道數(shù)的矩陣,并將其所有元素初始化為零。
具體解釋:
-
Mat
是OpenCV中用于表示圖像和矩陣的數(shù)據(jù)結(jié)構(gòu)。 -
image.size()
返回原始圖像image
的尺寸(行數(shù)和列數(shù))。 -
image.type()
返回原始圖像image
的數(shù)據(jù)類型和通道數(shù)信息。
Mat::zeros(image.size(), image.type())
將創(chuàng)建一個(gè)與原始圖像 image
具有相同尺寸和通道數(shù)的圖像,但所有像素的值都將初始化為零。這是為了在后續(xù)的操作中存儲調(diào)整后的圖像,因?yàn)樵谶M(jìn)行線性變換之前,我們希望輸出圖像的像素值都為零。
實(shí)際上,Mat::zeros
在圖像處理中經(jīng)常用于創(chuàng)建用于存儲中間或結(jié)果圖像的矩陣,以確保其初始值為零。這有助于避免潛在的垃圾值或不可預(yù)測的結(jié)果。
for (int y = 0; y < image.rows; y++) {
for (int x = 0; x < image.cols; x++) {
for (int c = 0; c < image.channels(); c++) {
adjusted_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(alpha * image.at<Vec3b>(y, x)[c] + beta);
}
}
}
-
for (int y = 0; y < image.rows; y++)
:這是外循環(huán),用于遍歷圖像的每一行。 -
for (int x = 0; x < image.cols; x++)
:這是內(nèi)循環(huán),用于遍歷圖像的每一列(像素)。 -
for (int c = 0; c < image.channels(); c++)
:這是內(nèi)部的循環(huán),用于遍歷圖像的通道(例如,對于彩色圖像,通道可能是B、G、R)。 -
adjusted_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(alpha * image.at<Vec3b>(y, x)[c] + beta);
:這行代碼執(zhí)行實(shí)際的線性變換操作。具體地,它對每個(gè)像素的每個(gè)通道執(zhí)行以下操作:-
image.at<Vec3b>(y, x)[c]
:這部分代碼從原始圖像image
中獲取當(dāng)前像素位置(y, x)
處的通道c
的灰度級別。 -
alpha * image.at<Vec3b>(y, x)[c] + beta
:這是線性變換的公式。alpha
控制對比度的調(diào)整,beta
控制亮度的調(diào)整。通過將alpha
乘以當(dāng)前像素的灰度級別并添加beta
,可以實(shí)現(xiàn)亮度和對比度的調(diào)整。 -
saturate_cast<uchar>(...)
:這是一個(gè)飽和操作,確保調(diào)整后的像素值在0到255之間。如果結(jié)果小于0,它將被截?cái)酁?;如果結(jié)果大于255,它將被截?cái)酁?55。 -
adjusted_image.at<Vec3b>(y, x)[c]
:最終的調(diào)整后的像素值將存儲在adjusted_image
中的相同位置(y, x)
處的通道c
中。
-
四、灰度反轉(zhuǎn):
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image1, output_image, image1_gray; //定義輸入圖像,輸出圖像,灰度圖像
image1 = imread("D://lena.png"); //讀取圖像;
if (image1.empty())
{
cout << "讀取錯(cuò)誤" << endl;
return -1;
}
cvtColor(image1, image1_gray, COLOR_BGR2GRAY); //灰度化
imshow(" image1_gray", image1_gray); //顯示灰度圖像
output_image = image1_gray.clone();
for (int i = 0; i < image1_gray.rows; i++)
{
for (int j = 0; j < image1_gray.cols; j++)
{
output_image.at<uchar>(i, j) = 255 - image1_gray.at<uchar>(i, j); //灰度反轉(zhuǎn)
}
}
imshow("output_image", output_image); //顯示反轉(zhuǎn)圖像
waitKey(0); //暫停,保持圖像顯示,等待按鍵結(jié)束
return 0;
}
其結(jié)果為:
左側(cè)為原始圖片,右側(cè)為反轉(zhuǎn)后的圖片
函數(shù)介紹:
cvtColor(image1, image1_gray, COLOR_BGR2GRAY);
cvtColor
函數(shù)的一般語法如下:
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn = 0);
以下是一些常見的 code
值以及它們的含義:
-
CV_BGR2GRAY
:BGR到灰度轉(zhuǎn)換。 -
CV_BGR2HSV
:BGR到HSV(色調(diào)、飽和度、明度)轉(zhuǎn)換。 -
CV_BGR2Lab
:BGR到Lab轉(zhuǎn)換。 -
CV_BGR2YUV
:BGR到Y(jié)UV轉(zhuǎn)換。 -
CV_RGB2BGR
:RGB到BGR轉(zhuǎn)換。 -
CV_GRAY2BGR
:灰度到BGR轉(zhuǎn)換。
該代碼中選擇的是CV_BGR2GRAY,即將BGR轉(zhuǎn)化為灰度。
output_image = image1_gray.clone();
for (int i = 0; i < image1_gray.rows; i++)
{
for (int j = 0; j < image1_gray.cols; j++)
{
output_image.at<uchar>(i, j) = 255 - image1_gray.at<uchar>(i, j); //灰度反轉(zhuǎn)
}
}
-
output_image = image1_gray.clone();
:首先,創(chuàng)建一個(gè)與輸入圖像image1_gray
具有相同尺寸和類型的輸出圖像output_image
,并將其初始化為與輸入圖像相同。 -
接下來,程序使用嵌套的循環(huán)遍歷輸入圖像
image1_gray
中的每個(gè)像素。 -
output_image.at<uchar>(i, j) = 255 - image1_gray.at<uchar>(i, j);
:在內(nèi)循環(huán)中,對于每個(gè)像素(i, j)
,它執(zhí)行以下操作:-
image1_gray.at<uchar>(i, j)
:從輸入圖像中獲取像素(i, j)
處的灰度值。at<uchar>(i, j)
表示像素值為無符號字符型(8位灰度圖像)。 -
255 - image1_gray.at<uchar>(i, j)
:將獲取的灰度值減去255,實(shí)現(xiàn)了灰度反轉(zhuǎn)。這將導(dǎo)致較亮的像素變暗,較暗的像素變亮,從而反轉(zhuǎn)了圖像的外觀。
-
通過這個(gè)過程,輸入圖像中的每個(gè)像素的灰度值都被反轉(zhuǎn),最終結(jié)果存儲在 output_image
中。這種操作可以用于創(chuàng)建底片效果或?qū)⒇?fù)片轉(zhuǎn)換為正片,以實(shí)現(xiàn)圖像的特殊效果。
五、伽馬校正
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main() {
// 加載圖像
Mat image = imread("D://lena.png");
if (image.empty()) {
cout << "無法加載圖像" << endl;
return -1;
}
// 伽馬值
double gamma = 2;//大于等于0,小于0為黑色。
// 伽馬校正
Mat gamma_corrected_image = Mat::zeros(image.size(), image.type());
for (int y = 0; y < image.rows; y++) {
for (int x = 0; x < image.cols; x++) {
for (int c = 0; c < image.channels(); c++) {
double pixel_value = image.at<Vec3b>(y, x)[c] / 255.0;
double corrected_value = pow(pixel_value, gamma) * 255.0;
gamma_corrected_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(corrected_value);
}
}
}
// 顯示原始圖像和伽馬校正后的圖像
imshow("原始圖像", image);
imshow("伽馬校正后的圖像", gamma_corrected_image);
waitKey(0);
return 0;
}
效果圖:
六、對數(shù)變換
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cmath>
using namespace cv;
using namespace std;
int main() {
// 加載圖像
Mat image = imread("D://lena.png");
if (image.empty()) {
cout << "無法加載圖像" << endl;
return -1;
}
// 對數(shù)變換參數(shù)
double c = 1.0; // 常數(shù)
double gamma = 0.5; // 對數(shù)變換的參數(shù)
// 對數(shù)變換
Mat log_transformed_image = Mat::zeros(image.size(), image.type());
for (int y = 0; y < image.rows; y++) {
for (int x = 0; x < image.cols; x++) {
for (int c = 0; c < image.channels(); c++) {
double pixel_value = image.at<Vec3b>(y, x)[c] / 255.0;
double corrected_value = c * log(1 + pixel_value) / log(1 + gamma);
log_transformed_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(corrected_value * 255.0);
}
}
}
// 顯示原始圖像和對數(shù)變換后的圖像
imshow("原始圖像", image);
imshow("對數(shù)變換后的圖像", log_transformed_image);
waitKey(0);
return 0;
}
效果圖:
七、直方圖均衡化
在這個(gè)示例中,我們加載了一幅圖像,并使用 IMREAD_GRAYSCALE
模式將其加載為灰度圖像。然后,我們使用 equalizeHist
函數(shù)執(zhí)行直方圖均衡化,將圖像的對比度增強(qiáng)。
直方圖均衡化是一種簡單而有效的方法,可以使圖像中的像素值更均勻分布,從而改善圖像的對比度。這個(gè)示例演示了如何使用OpenCV來實(shí)現(xiàn)直方圖均衡化,以改進(jìn)圖像的視覺質(zhì)量。
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main() {
// 加載圖像
Mat image = imread("D://lena.png", IMREAD_GRAYSCALE); // 以灰度模式加載圖像
if (image.empty()) {
cout << "無法加載圖像" << endl;
return -1;
}
// 直方圖均衡化
Mat equalized_image;
equalizeHist(image, equalized_image);
// 顯示原始圖像和均衡化后的圖像
imshow("原始圖像", image);
imshow("直方圖均衡化后的圖像", equalized_image);
waitKey(0);
return 0;
}
效果圖:
為什么直方圖均衡化前要將圖像轉(zhuǎn)化為灰度模式?
直方圖均衡化通常用于灰度圖像的處理,而不是彩色圖像,主要有以下原因:
-
簡化處理:直方圖均衡化是一種非?;A(chǔ)和常見的圖像增強(qiáng)技術(shù)。在灰度圖像中,每個(gè)像素只有一個(gè)灰度值,因此處理相對簡單。處理彩色圖像時(shí),需要對每個(gè)通道分別進(jìn)行直方圖均衡化,增加了復(fù)雜性。
-
直方圖均衡化的原理:直方圖均衡化的核心思想是通過重新分配像素值來拉伸和擴(kuò)展圖像的像素值范圍,以使圖像的直方圖更加均勻。在灰度圖像中,這意味著調(diào)整圖像的灰度級別,使其在0到255之間更均勻地分布。在彩色圖像中,需要對每個(gè)通道分別進(jìn)行這種操作。
-
彩色信息冗余:彩色圖像包含了更多的信息,包括顏色和亮度信息。在某些情況下,只需對亮度信息進(jìn)行均衡化,因?yàn)轭伾畔⒖赡懿⒉恍枰淖儭Mㄟ^將彩色圖像轉(zhuǎn)換為灰度圖像,可以更好地控制均衡化的效果,以保持圖像的整體外觀。
-
常見應(yīng)用:直方圖均衡化常用于醫(yī)學(xué)圖像處理、計(jì)算機(jī)視覺和圖像增強(qiáng)等應(yīng)用中,而這些應(yīng)用通常使用灰度圖像。因此,在這些場景下,直方圖均衡化通常直接應(yīng)用于灰度圖像以改善對比度。
盡管直方圖均衡化通常用于灰度圖像,但也存在用于彩色圖像的擴(kuò)展方法,例如對亮度通道進(jìn)行均衡化而保持色彩信息不變。這類方法通常稱為彩色直方圖均衡化或色彩均衡化。在這種情況下,處理的是亮度信息,而色彩信息得到保留。
八、自適應(yīng)直方圖均衡化
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main() {
// 加載圖像
Mat image = imread("D://lena.png", IMREAD_GRAYSCALE); // 以灰度模式加載圖像
if (image.empty()) {
cout << "無法加載圖像" << endl;
return -1;
}
// 自適應(yīng)直方圖均衡化
Mat adaptive_equalized_image;
equalizeHist(image, adaptive_equalized_image);
// 顯示原始圖像和自適應(yīng)直方圖均衡化后的圖像
imshow("原始圖像", image);
imshow("自適應(yīng)直方圖均衡化后的圖像", adaptive_equalized_image);
waitKey(0);
return 0;
}
在這個(gè)示例中,我們加載了一幅圖像,并使用 IMREAD_GRAYSCALE
模式將其加載為灰度圖像。然后,我們使用 equalizeHist
函數(shù)執(zhí)行自適應(yīng)直方圖均衡化,將圖像的對比度增強(qiáng)。
自適應(yīng)直方圖均衡化是一種改進(jìn)的直方圖均衡化方法,它在不同圖像區(qū)域上分別應(yīng)用均衡化,以應(yīng)對光照差異。這個(gè)示例演示了如何使用OpenCV來實(shí)現(xiàn)自適應(yīng)直方圖均衡化,以改進(jìn)圖像的視覺質(zhì)量。文章來源:http://www.zghlxwxcb.cn/news/detail-766541.html
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------文章來源地址http://www.zghlxwxcb.cn/news/detail-766541.html
到了這里,關(guān)于Opencv C++ 六、灰度變換:線性變換、灰度反轉(zhuǎn)、對數(shù)變換、伽馬變換、(自適應(yīng))直方圖均衡化的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!