《数字图像处理(第三版)》 第三章 数字图像处理 笔记2 (基本的灰度变换函数)
第 3 章 灰度變換與空間濾波
3.2 一些基本的灰度變換函數(shù)
??灰度變換是所有圖像處理技術(shù)中最簡(jiǎn)單的技術(shù),涉及
s=T(r)s = T(r) s=T(r)
其中 T 是把像素值 r 映射到像素值 s 的一種變換。
??由于處理的是數(shù)字量,變換函數(shù)的值通常存儲(chǔ)在一個(gè)一維陣列中,并且從 r 到 s 的映射通過(guò)查表得到。對(duì)于 8 比特環(huán)境,一個(gè)包含 T 值的可查閱的表需要有 256 個(gè)記錄。
??如上圖顯示了圖像增強(qiáng)常用的三類基本函數(shù):線性函數(shù)(反轉(zhuǎn)和恒等變換)、對(duì)數(shù)函數(shù)(對(duì)數(shù)和反對(duì)數(shù)變換)和冪律函數(shù)(n 次冪和 n 次根變換)。
3.2.1 圖像反轉(zhuǎn)
??對(duì)于灰度級(jí)范圍為 [0, L-1] 的一幅圖像,該圖像的反轉(zhuǎn)由下式給出:
s=L?1?rs = L - 1 - r s=L?1?r
使用這種方式反轉(zhuǎn)一幅圖像的灰度級(jí),可得到等效的照片底片。這種類型的處理特別適用于 增強(qiáng)嵌入圖像暗色區(qū)域中的白色或灰色細(xì)節(jié),特別是 當(dāng)黑色面積在尺寸上占主導(dǎo)地位時(shí)。
??如下例子中原圖像(左圖)是一幅數(shù)字乳房 X 射線照片,其中顯示有一小塊病變。通過(guò)反轉(zhuǎn)得到右圖,盡管視覺(jué)內(nèi)容上都一樣,但反轉(zhuǎn)之后的圖像在分析乳房組織時(shí)會(huì)更加容易。
3.2.2 對(duì)數(shù)變換
??通用形式為:
s=c?log(1+r)s = c * log(1 + r) s=c?log(1+r)
式中 c 是常數(shù),并假設(shè) r>=0。如下圖所示:
此變換將輸入中范圍較窄的低灰度值映射為輸出中范圍較寬的灰度值,或?qū)⑤斎胫蟹秶^寬的高灰度值映射為輸出中范圍較窄的灰度值。使用這種類型的變換來(lái) 擴(kuò)展圖像中的暗像素值,同時(shí)壓縮更高灰度級(jí)的值。反對(duì)數(shù)變換的作用與此相反。
??對(duì)數(shù)變換中對(duì)數(shù)的底數(shù)可以有多種選擇,以 2、10、e 為底均可。
??具有對(duì)數(shù)函數(shù)一般形狀的任何曲線,都能完成圖像灰度級(jí)的擴(kuò)展/壓縮,但后面將要討論的冪律變換更適用于這兒目的。
??如果原圖像的灰度級(jí)為 L,對(duì)數(shù)變換公式的結(jié)果應(yīng)當(dāng)重新標(biāo)定為 [0, L-1] 的灰度級(jí)。例如,對(duì)于一幅 256 灰度級(jí)的原圖像,對(duì)數(shù)變換增強(qiáng)的結(jié)果可用以下式子表示
s=c?log(1+r)?c?log(1+0)c?log(1+255)?c?log(1+0)?255s = \frac{c * log(1+r) - c * log(1+0)}{c * log(1+255) - c * log(1+0)} * 255 s=c?log(1+255)?c?log(1+0)c?log(1+r)?c?log(1+0)??255
??對(duì)數(shù)函數(shù)有一個(gè)重要特征,即它 壓縮像素值變化較大的圖像的動(dòng)態(tài)范圍。像素值有較大動(dòng)態(tài)范圍的一個(gè)典型應(yīng)用說(shuō)明是 傅里葉頻譜。通常,頻譜值的范圍從 0 到 106 或更高的情況是常見(jiàn)的,如果采用均勻量化,最后的效果是有很多的細(xì)節(jié)會(huì)在典型的傅里葉頻譜顯示是丟失。
??如下圖示例中,左圖為原始的傅里葉頻譜,值域?yàn)?0 ~ 1.5 × 106 ,當(dāng)這些值在一個(gè) 8 比特系統(tǒng)中被線性地縮放顯示時(shí),最亮的像素將支配該顯示,頻譜中地低值(恰恰是重要的)將損失掉。通過(guò)對(duì)數(shù)變換,將值域變?yōu)?0 ~ 6.2 得到右圖,與未改進(jìn)顯示地頻譜相比,這幅圖像中可見(jiàn)細(xì)節(jié)地豐富程度很明顯。
??所以 對(duì)數(shù)變換最主要的應(yīng)用是傅里葉頻譜的增強(qiáng)。
3.2.3 冪律(伽馬)變換
??冪律變換的基本形式為
s=crγs = cr^\gamma s=crγ
其中 c 和 γ 為正常數(shù)。對(duì)于不同的 γ 值,s 與 r 的關(guān)系曲線如下圖所示。與對(duì)數(shù)變換情況類似,部分 γ 值的冪律曲線將較窄范圍的暗色輸入值映射為較寬范圍的輸出值,或?qū)⑤^寬范圍的高灰度級(jí)輸入值映射為較窄范圍的輸出值。
如上圖所示,γ > 1 的值所生成的曲線和 γ < 1 的值所生成的曲線的效果完全相反。當(dāng) c = γ = 1 時(shí)就簡(jiǎn)化為了恒等變換。
??用于圖像獲取、打印和顯示的各種設(shè)備根據(jù)冪律變換來(lái)產(chǎn)生響應(yīng)。習(xí)慣上,冪律方程中的指數(shù)稱為 伽馬。用于校正這些冪律響應(yīng)現(xiàn)象的處理稱為 伽馬校正,指用來(lái)校正監(jiān)視器顯示的非線性特點(diǎn)。
??陰極射線管(CRT)設(shè)備有一個(gè)灰度——電壓響應(yīng),該響應(yīng)是一個(gè)指數(shù)變化范圍約為 1.8 ~ 2.5 的冪函數(shù)。如下圖示例中,左上圖顯示了一幅輸入到監(jiān)視器的簡(jiǎn)單灰度斜坡(漸變)圖像。右上圖是顯示器輸出的結(jié)果,可以看到,顯示器直接輸出比輸入暗。在這種情況下,伽馬校正很簡(jiǎn)單,只需要將圖像輸入到監(jiān)視器前進(jìn)行預(yù)處理,即進(jìn)行 s = r1/2.5 = r0.4 變換,結(jié)果如左下圖所示。當(dāng)輸入到相同的監(jiān)視器時(shí),經(jīng)過(guò)伽馬校正的輸入產(chǎn)生外觀接近于原圖像的輸出,如右下圖所示。類似的分析也適用于其他圖像設(shè)備,如掃描儀和打印機(jī)。
??若所關(guān)注的是在計(jì)算機(jī)屏幕上精確顯示圖像,則伽馬校正很重要。試圖精確再現(xiàn)彩色也需要伽馬校正的一些知識(shí),因?yàn)楦淖冑ゑR值不僅會(huì)改變亮度,而且會(huì)改變彩色圖像中的紅、綠、藍(lán)的比率。
??此外,目前的圖像標(biāo)準(zhǔn)并不包含創(chuàng)建圖像的伽馬值,因此問(wèn)題進(jìn)一步復(fù)雜化了。由于這些限制,在網(wǎng)站中存儲(chǔ)圖像時(shí),一種合理的方法是用伽馬值對(duì)圖像進(jìn)行預(yù)處理,這個(gè)伽馬值代表了在開(kāi)放的市場(chǎng)中,在任意給定時(shí)間點(diǎn),各種型號(hào)監(jiān)視器和計(jì)算機(jī)系統(tǒng)所期望的 “平均值”。
??使用冪律變換還能增強(qiáng)對(duì)比度,對(duì)于原始圖像整體偏暗的情況,需要擴(kuò)展灰度級(jí);對(duì)于原始圖像偏亮的情況,需要進(jìn)行灰度級(jí)壓縮。
??下圖中,圖(a)顯示了一幅人體胸上部脊椎骨折和椎線受影響的核磁共振圖像。在圖中上部約 1/4 處,骨折顯而易見(jiàn),由于所給圖像整體為暗色,灰度的擴(kuò)大是需要的,這可由指數(shù)為分?jǐn)?shù)的冪次變換來(lái)完成。對(duì)圖(a)的冪次變換函數(shù)處理可以得到示于圖中的其他幾幅圖像。圖(b)到(d)相應(yīng)的伽馬值分別為 0.6、0.4 和 0.3。
??圖(a) 有 “沖淡” 的顯示小國(guó),表明灰度級(jí)需要壓縮,令 c = 1,γ 值大于 1。令 γ = 3.0、4.0 和 5.0 的處理結(jié)果示于圖(b)到圖(d)。可見(jiàn),伽馬值取 3.0 和 4.0 時(shí),可得到合適的結(jié)果,且后者由于有較高的對(duì)比度而顯示出較好的效果。γ = 5.0 得到的結(jié)果有些地方太暗,從而丟失了一些細(xì)節(jié)。
3.2.4 分段線性變換函數(shù)
??分段線性函數(shù)相比前面所討論函數(shù)的主要優(yōu)勢(shì)在于它的形式可以任意合成。同時(shí),分段線性函數(shù)的主要缺點(diǎn)是其需要更多的用戶輸入。
??下面主要介紹分段線性變換函數(shù)的三個(gè)應(yīng)用:
- 對(duì)比度拉伸
- 灰度級(jí)分層
- 比特平面分層
3.2.4.1 對(duì)比度拉伸
??最簡(jiǎn)單的分段線性函數(shù)之一是 對(duì)比度拉伸變換。低對(duì)比度圖像由照明不足、成像傳感器動(dòng)態(tài)范圍太小、圖像獲取過(guò)程中鏡頭光圈設(shè)置錯(cuò)誤引起。對(duì)比度拉伸是 擴(kuò)展圖像灰度級(jí)動(dòng)態(tài)范圍的處理,因此可以跨越記錄介質(zhì)和顯示裝置的全部灰度范圍。
??下圖是對(duì)比度拉伸的一個(gè)例子:
- 圖(a)是對(duì)比度拉伸的典型變換,點(diǎn) (r1, s1) 和 (r2, s2) 的位置控制了變換函數(shù)的形狀。一般情況下,r1 <= r2,且 s1 <= s2,函數(shù)是單值的且單調(diào)遞增的。這一條件保持了灰度級(jí)的次序,從而避免了在處理后的圖像中產(chǎn)生人為的灰度錯(cuò)誤。
- 圖(b)為 8 比特低對(duì)比度圖像。
- 圖?為對(duì)比度拉伸的效果,設(shè)置 (r1, s1) = (rmin, 0),且 (r2, s2) = (rmax, L-1),其中 rmin,rmax 分別代表圖像中灰度的最小值和最大值。若 r1 = r2,s1 = 0,且 s2 = L-1,變換變?yōu)殚撝堤幚砗瘮?shù),并產(chǎn)生二值圖像。
- 圖(d)所示,若 r1 = r2,s1 = 0,且 s2 = L-1,變換變?yōu)殚撝堤幚砗瘮?shù),并產(chǎn)生二值圖像。
3.2.4.2 灰度級(jí)分層
??在圖像中提高特定灰度范圍的亮度通常是必要的,也被稱為 灰度級(jí)分層,其應(yīng)用包括增強(qiáng)某些特征。
??有許多方法可以進(jìn)行灰度級(jí)分層,但大多數(shù)是兩種基本方法的變形:
- 一種是將感興趣范圍內(nèi)的所有灰度值顯示為一個(gè) 較高值(譬如 “白色” )而將其他灰度值顯示為另一個(gè) 較低值(譬如 “黑色” ),產(chǎn)生一幅二值圖像。
- 第二種方法使所需范圍的灰度變亮,但是仍保持了圖像的背景和灰度色調(diào)。
測(cè)試程序
#define CVUI_IMPLEMENTATION #define CVUI_DISABLE_COMPILATION_NOTICES #include "cvui.h"#include <iostream>#include <opencv2/core/core.hpp> #include <opencv2/imgcodecs/imgcodecs.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp>#define WINDOW_NAME "Linear Transformation"void method1(); void method2(); void transformForMethod1(const cv::Mat& src, cv::Mat& dst, double& minSetGrayValue, double& maxSetGrayValue); void transformForMethod2(const cv::Mat& src, cv::Mat& dst, double& minSetGrayValue, double& maxSetGrayValue);int main(int argc, char* argv) {cvui::init(WINDOW_NAME);cv::Mat frame = cv::Mat(cv::Size(300, 300), CV_8UC3);while (true){frame = cv::Scalar(100, 100, 100);cvui::text(frame, 60, 25, "Gray Scale Layering", 0.6);if (cvui::button(frame, 100, 100, "Method 1"))method1();if (cvui::button(frame, 100, 150, "Method 2"))method2();if (cvui::button(frame, 115, 200, "Exit"))break;cvui::imshow(WINDOW_NAME, frame);if (cv::waitKey(100) == 27)break;}return 0; }void method1() {cv::Mat src = cv::imread(cv::samples::findFile("kidney.tif"), cv::IMREAD_GRAYSCALE);cv::Mat dst;dst.create(src.size(), src.type());cvui::init("Method 1");cv::Mat frame = cv::Mat(cv::Size(1500, 1000), CV_8UC1);double minSetGrayValue = 50;double maxSetGrayValue = 100;double tempMinSetGrayValue = 0;double tempMaxSetGrayValue = 0;while (true){frame = cv::Scalar(255);cvui::text(frame, 700, 5, "Method 1", 1.3, 0x000000);cvui::image(frame, 20, 60, src);cvui::image(frame, 760, 60, dst);int status = cvui::iarea(20, 60, 720, 828);int xCoord; int yCoord;switch (status){case cvui::OVER:cvui::printf(frame, 100, 900, 0.9, 0x000000, "Pointer Coordinate : (%d, %d)", cvui::mouse().x - 20, cvui::mouse().y - 60);xCoord = cvui::mouse().x - 20; yCoord = cvui::mouse().y - 60;//cvui::printf(frame, 100, 930, 0.9, 0x000000, "Pixel Value = %d", src.at<uchar>(xCoord, yCoord));cvui::printf(frame, 100, 930, 0.9, 0x000000, "Pixel Value = %d", src.at<uchar>(yCoord, xCoord));break;default:break;}cvui::text(frame, 770, 900, "Min Gray Value : ", 0.7, 0x000000);cvui::trackbar(frame, 970, 890, 500, &minSetGrayValue, (double)0, (double)255, 32, "%.0Lf");cvui::text(frame, 770, 950, "Max Gray Value : ", 0.7, 0x000000);cvui::trackbar(frame, 970, 940, 500, &maxSetGrayValue, (double)0, (double)255, 32, "%.0Lf");if (tempMinSetGrayValue != minSetGrayValue || tempMaxSetGrayValue != maxSetGrayValue){transformForMethod1(src, dst, minSetGrayValue, maxSetGrayValue);tempMinSetGrayValue = minSetGrayValue;tempMaxSetGrayValue = maxSetGrayValue;}if (cvui::button(frame, 1400, 10, "Exit"))break;cvui::imshow("Method 1", frame);if (cv::waitKey(20) == 27)break;}return; }void method2() {cv::Mat src = cv::imread(cv::samples::findFile("kidney.tif"), cv::IMREAD_GRAYSCALE);cv::Mat dst;dst.create(src.size(), src.type());cvui::init("Method 2");cv::Mat frame = cv::Mat(cv::Size(1500, 1000), CV_8UC1);double minSetGrayValue = 50;double maxSetGrayValue = 100;double tempMinSetGrayValue = 0;double tempMaxSetGrayValue = 0;while (true){frame = cv::Scalar(255);cvui::text(frame, 700, 5, "Method 2", 1.3, 0x000000);cvui::image(frame, 20, 60, src);cvui::image(frame, 760, 60, dst);int status = cvui::iarea(20, 60, 720, 828);int xCoord; int yCoord;switch (status){case cvui::OVER:cvui::printf(frame, 100, 900, 0.9, 0x000000, "Pointer Coordinate : (%d, %d)", cvui::mouse().x - 20, cvui::mouse().y - 60);xCoord = cvui::mouse().x - 20; yCoord = cvui::mouse().y - 60;//cvui::printf(frame, 100, 930, 0.9, 0x000000, "Pixel Value = %d", src.at<uchar>(xCoord, yCoord));cvui::printf(frame, 100, 930, 0.9, 0x000000, "Pixel Value = %d", src.at<uchar>(yCoord, xCoord));break;default:break;}cvui::text(frame, 770, 900, "Min Gray Value : ", 0.7, 0x000000);cvui::trackbar(frame, 970, 890, 500, &minSetGrayValue, (double)0, (double)255, 32, "%.0Lf");cvui::text(frame, 770, 950, "Max Gray Value : ", 0.7, 0x000000);cvui::trackbar(frame, 970, 940, 500, &maxSetGrayValue, (double)0, (double)255, 32, "%.0Lf");if (tempMinSetGrayValue != minSetGrayValue || tempMaxSetGrayValue != maxSetGrayValue){transformForMethod2(src, dst, minSetGrayValue, maxSetGrayValue);tempMinSetGrayValue = minSetGrayValue;tempMaxSetGrayValue = maxSetGrayValue;}if (cvui::button(frame, 1400, 10, "Exit"))break;cvui::imshow("Method 2", frame);if (cv::waitKey(20) == 27)break;}return; }void transformForMethod1(const cv::Mat& src, cv::Mat& dst, double& minSetGrayValue, double& maxSetGrayValue) {for (size_t iRow = 0; iRow < src.rows; iRow++){for (size_t iCol = 0; iCol < src.cols; iCol++){if (src.at<uchar>(iRow, iCol) <= int(minSetGrayValue))dst.at<uchar>(iRow, iCol) = 10;else if (src.at<uchar>(iRow, iCol) <= int(maxSetGrayValue))dst.at<uchar>(iRow, iCol) = 200;elsedst.at<uchar>(iRow, iCol) = 10;}}return; }void transformForMethod2(const cv::Mat& src, cv::Mat& dst, double& minSetGrayValue, double& maxSetGrayValue) {for (size_t iRow = 0; iRow < src.rows; iRow++){for (size_t iCol = 0; iCol < src.cols; iCol++){if (src.at<uchar>(iRow, iCol) <= int(minSetGrayValue))dst.at<uchar>(iRow, iCol) = src.at<uchar>(iRow, iCol);else if (src.at<uchar>(iRow, iCol) <= int(maxSetGrayValue))dst.at<uchar>(iRow, iCol) = 200;elsedst.at<uchar>(iRow, iCol) = src.at<uchar>(iRow, iCol);}}return; }輸出結(jié)果
3.2.4.2 比特平面分層
??代替提高灰度范圍的亮度,通過(guò)對(duì)特定位提高亮度,對(duì)整幅圖像質(zhì)量仍然是有貢獻(xiàn)的。
??設(shè)圖像中的每一個(gè)像素都是由 8 比特表示,假設(shè)圖像是由 8 個(gè) 1 比特平面組成,其范圍從最低有效位的位平面 0 到最高有效位的位平面 7 。在 8 比特字節(jié)中,平面 0 包含圖像中像素最低位,而平面 7 則包含最高位。即將一幅灰度級(jí)為 256 的圖像看作是 8 個(gè)二值圖像。
??上圖通過(guò)比特平面分層可以得到如下所示的 8 張比特平面圖。每個(gè)比特平面都是一幅二值圖像。
??把一幅圖像分解為比特平面,對(duì)于分析圖像中每個(gè)比特的相對(duì)重要性很有用,這一處理可幫助我們確定用于量化該圖像的比特?cái)?shù)的充分性。此外,這種類型的分解對(duì)于圖像壓縮也很有用,在圖像壓縮中,重建一幅圖像時(shí)所用的平面要比全部平面少。在圖像重建的實(shí)際應(yīng)用中可以得出如下結(jié)論:存儲(chǔ) 4 個(gè)高階比特平面將允許我們以可接受的細(xì)節(jié)來(lái)重建福源圖像。存儲(chǔ)這 4 個(gè)平面代替原始圖像可減少 50% 的存儲(chǔ)量。
總結(jié)
以上是生活随笔為你收集整理的《数字图像处理(第三版)》 第三章 数字图像处理 笔记2 (基本的灰度变换函数)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 设置Mac自动显示和隐藏 Dock 栏的
- 下一篇: 富文本编辑器初探