1.點運算概述
數字圖像處理系統處理流程:預處理--->特征提取--->識別分析.
點運算是對圖像中的每個像素依次進行同樣的灰度變換運算。設輸入圖像f(x,y)和輸出圖像g(x,y)在任一點(x,y)的灰度值,點運算表示為:g(x,y) = T(f(x,y))。其中T為采用的點運算算子,表示原始圖像和輸出圖像之間的某種灰度級映射關系。
點運算常用於改變圖像的灰度范圍及分布,點運算因其作用的性質有時也被稱為對比度增強、對比度拉伸或灰度變換。(對比度:灰度圖像中最大亮度與最小亮度的比值)
2.灰度直方圖
灰度直方圖描述了一幅圖像的灰度級統計信息,主要用於圖像分割和圖像灰度變換等處理過程。
從數學較讀來說,圖像直方圖描述的是圖像中各個灰度級統計特性,它是關於圖像灰度值的函數,用於統計一幅圖像中各個灰度級出現的次數或概率(即各個灰度級像素出現的次數或占比)。歸一化直方圖可以直接反映不同灰度級出現的比率。
從圖形上來說,灰度直方圖是一個二維圖,橫坐標為圖像中各個像素點的灰度級別,縱坐標為各個灰度級別的像素出現的次數或概率。
Matlab生成圖像的灰度直方圖:
I = imread('pout.tif'); figure; % 創建一個窗口 imshow(I); title('Source'); % 顯示原圖,設置標題 figure; imhist(I);title('Graph'); % 生成灰度直方圖,默認是256個灰度值,區間也是256個(0~255),此時統計的是在256個區間上像素出現的次數 figure; >> imhist(I, 64); title('Graph64'); % 將灰度級划分成64個區間
繪制歸一化直方圖:
I = imread('pout.tif'); figure; [M, N] = size(I); [counts,x] = imhist(I, 32); % 32個區間,返回落在各個區間的像素個數counts, x是各個區間 counts = counts / (M * N); % 歸一化 stem(x, counts); % 繪制歸一化直方圖
3.灰度的線性變換
Matlab示例:
I = imread('coins.png'); I = im2double(I); % 轉成浮點表示 [M,N] = size(I); figure(1); imshow(I); title('Source Image'); figure(2); [H,x] = imhist(I, 64); stem(x, (H / (M * N)), '.'); title('Source Stem'); % 歸一化直方圖 % 增加對比度 Fa = 2; Fb = -55; O = Fa .* I + Fb / 255; figure(3); subplot(2,2,1); imshow(O); title('Fa = 2 Fb = -55 Add Contrast'); figure(4); subplot(2,2,1); [H,x] = imhist(O, 64); stem(x, (H/M/N), '.'); title('Fa = 2 Fb = -55 Add Contrast'); % 減少對比度 Fa = 0.5; Fb = -55; O = Fa .* I + Fb / 255; figure(3); subplot(2,2,2); imshow(O); title('Fa = 2 Fb = -55 Sub Contrast'); figure(4); subplot(2,2,2); [H,x] = imhist(O, 64); stem(x, (H/M/N), '.'); title('Fa = 2 Fb = -55 Sub Contrast'); % 增加亮度 Fa = 1; Fb = 55; O = Fa .* I + Fb / 255; figure(3); subplot(2,2,3); imshow(O); title('Fa = 1 Fb = 55 Add Brightness'); figure(4); subplot(2,2,3); [H,x] = imhist(O, 64); stem(x, (H/M/N), '.'); title('Fa = 1 Fb = 55 Add Brightness'); % 反向顯示 Fa = -1; Fb = 255; O = Fa .* I + Fb / 255; figure(3); subplot(2,2,4); imshow(O); title('Fa = -1 Fb = 255 Reverse'); figure(4); subplot(2,2,4); [H,x] = imhist(O, 64); stem(x, (H/M/N), '.'); title('Fa = -1 Fb = 255 Sub Reverse');
從上面的示例可以看出改變圖像的對比度是對直方圖的縮放與平移,改變圖像的亮度則只是平移直方圖在橫軸上的位置,而反向就是將直方圖水平鏡像。單純的線性灰度變換只能在一定程度上解決視覺上整體對比度問題,但是對於圖像細節部分的增強較為有限,一般還需要結合非線性變換來解決。
4.灰度對數變換
對數變換的一般表達式:
如下圖的對數函數曲線圖,函數自變量低值時曲線斜率很高,自變量高值時曲線斜率變小。由對數函數曲線可知,這種變換可以增強一幅圖像中較暗部分(相當於低值自變量)的細節,從而可以用來擴展被壓縮的高值圖像中的較暗像素,因此對數變換被廣泛運用於頻譜圖像的顯示中。一個典型的運用是傅里葉頻譜,其動態范圍可能寬達0~10^6.直接顯示頻譜時,圖像顯示設備的動態范圍往往不能滿足要求,從而會丟失大量的暗部細節,而在使用對數變換之后,圖像的動態范圍被合理的非線性壓縮,從而可以清晰的顯示。
使用如下數學函數實現對圖像I的對數變換:
下面使用Matlab實現對傅里葉頻譜圖像進行對數變換,從
% 讀取圖像 I = imread('coins.png'); % 計算圖像的傅里葉頻譜 F = fft2(im2double(I)); F = fftshift(F); F = abs(F); % 對數變換 T = log(F + 1); subplot(1,2,1); imshow(F, []); title('未經變換的傅里葉頻譜'); subplot(1,2,2); imshow(T, []); title('經對數變換后的頻譜圖');
5.伽瑪變換
伽瑪變換又叫指數變換或冪次變換,時另一種常用的灰度非線性變換。
伽馬變換的映射關系如下圖,在進行變換時通常要將0~255的灰度范圍先先變換到0~1的范圍,執行完伽馬變換后再映射到原來的范圍。
如下程序實現了gamma系數不同取值時的效果:
I = imread('pout.tif'); % Gamma = 0.75 subplot(1,3,1); imshow(imadjust(I, [], [], 0.75)); title('Gamma 0.75'); % Gamma = 1.0 subplot(1,3,2); imshow(imadjust(I, [], [], 1.0)); title('Gamma 1.0'); % Gamma = 1.5 subplot(1,3,3); imshow(imadjust(I, [], [], 1.5)); title('Gamma 1.5');
從效果可以看出伽馬因子給圖像的整體明暗程度帶來的變化,以及圖像暗部和亮部細節清晰度的影響。當伽馬銀子取1時,圖像沒有任何改變。下面生成3幅圖像的灰度直方圖:
subplot(1,3,1); imhist(imadjust(I, [], [], 0.75)); title('Gamma=0.75'); subplot(1,3,2); imhist(imadjust(I, [], [], 1)); title('Gamma=1'); subplot(1,3,3); imhist(imadjust(I, [], [], 1.5)); title('Gamma=1.5');
觀察直方圖非零值區間位置的變化,以及這些變化給圖像帶來的影響。由於伽馬變換並不是線性變換,所以它不僅可以改變圖像的對比度,還能增強細節,從而帶來整體效果的改善。
6.灰度閾值變換
灰度閾值變換可以將一幅灰度圖像轉換成黑白的二值圖像,這種過程也叫二值化或閾值化。用戶指定一個起到分解限作用的灰度值,如果圖像中某像素的灰度值小於該灰度值,則將該像素的灰度值設置為0,否則設置為255,這個起到分解先作用的灰度值稱為閾值。通過閾值化可以直接將圖像內容划分為我們關心和不關心的2個部分,是圖像分割的重要手段之一。
Matlab與閾值相關的函數主要2個:im2bw和graythresh
BW = im2bw(I, level) 將灰度圖像I轉換為二值圖像BW,其中level是閾值等級它是一個[0,1]之間的double類型,可以映射到對應的灰度值,未指定時默認是0.5。 例如輸入圖像I為灰度范圍在0~255之間的uint8圖像,指定level=0.5則對應的分割閾值為128. BW = im2bw(X, map, level) 將帶有顏色映射表的索引圖像X轉換成二值圖像 BW = im2bw(RGB, level) 將真彩色圖像RGB轉換成二值圖像 如果輸入圖像不是灰度圖像,則im2bw將輸入圖像轉換為灰度圖像,然后通過閾值將此灰度圖像轉換為二進制圖像。 level = graythresh(I) 使用Otsu算法(大津算法)計算一個出全局閾值,該閾值可用於將灰度圖像轉換為二值圖像。I為需要計算閾值的輸入圖像。 具體說明可以查看Matlab幫助文檔,使用doc+函數名 命令即可查看。
Matlab2017B版本
為了使圖片轉換為二值圖,利用 imbinarize 函數,其中的參數必須為二維的灰度圖:
bw=imbinarize( g ); 或 bw=im2bw( g );
在 matlab2018 中建議用 imbinarize 來將圖片轉換為二值圖,其參數必須為灰度圖。
在 matlab2016 中,只有 im2bw 函數,其參數可以是灰度圖或 rgb 圖。
即在 matlab2016 中可以用 im2bw 直接將 rgb 圖像轉換為二值圖;但是在 matlab2018 中只能先將 rgb 圖片轉換為灰度圖(用 rgb2gray() 函數),再用 imbinarize 轉換為二值圖。
兩個函數都是將圖片轉換為灰度圖,除了參數的類型不同,兩個函數都可再傳入一個 [0,1] 的閾值,即:
bw = im2bw( g , level ); 或 bw = imbinarize( g , level );
閾值(level)的作用為:用值 1 (白色)替換輸入圖像中亮度大於 level 比例的所有像素,用值 0 (黑色)替換所有其他像素。
當 im2bw 的 level 省略時,默認為 0.5 。
下面是一個示例:
I = imread('rice.png'); thresh = graythresh(I); % 使用大津算法計算最優閾值 bw1 = im2bw(I, thresh); % 閾值化 bw2 = imbinarize(I, 130/255); % 使用130閾值做閾值化 subplot(1,3,1);imshow(I);title('Source Img'); subplot(1,3,2);imshow(bw1);title('Threshed By Otsu'); subplot(1,3,3);imshow(bw2);title('Threshed By 130');
7.分段線性變換
分段線性變換又很多種,包括灰度拉伸、灰度窗口變換等,本節只分析最常用的灰度拉伸。
以下是示例,先定義了2個自定義函數:
% parse_inputs.m % 分析輸入參數個數和有效性 % A 輸入圖像,RGB圖(3D),灰度圖(2D),索引圖(X) % map 索引圖的調色板(顏色表) (:,3) % [x1, x2] 參數組1,分段線性曲線中2個轉折點的橫坐標 % [y1, y2] 參數組2,分段線性曲線中2個轉折點的縱坐標 function [A, map, x1, x2, y1, y2] = parse_inputs(varargin) map = []; % iptchecknargin(low, high, num_inputs, func_name)函數 % 檢查nargin中包含的輸入遍歷個數是否在low和high指定的范圍,不在范圍則報錯。 % 使用方法參考幫助文檔 iptchecknargin(3,4,nargin,mfilename); % iptcheckinput(A, classes, attributes, func_name, var_name, arg_pos)函數 % 檢查矩陣A中元素是否屬於給的的類型列表,如果有元素不屬於給定類型則報錯 iptcheckinput(varargin{1},... {'uint8', 'uint16', 'int16', 'double'},... {'real', 'nonsparse'},mfilename,'I, X or RGB',1); % 根據參數個數返回不同的值 switch nargin case 3 % 參數可能是(I, [x1,x2],[y1,y2])或(RGB, [x1,x2],[y1,y2]) A = varargin{1}; x1 = varargin{2}(1); x2 = varargin{2}(2); y1 = varargin{3}(1); y2 = varargin{3}(2); case 4 % (I, map,[x1,x2],[y1,y2]) A = varargin{1}; map = varargin{2}; x1 = varargin{3}(1); x2 = varargin{3}(2); y1 = varargin{4}(1); y2 = varargin{4}(2); end % 檢查輸入參數的有效性 % 檢查RGB數組 if(ndims(A) == 3) && (size(A,3) ~= 3) msg = sprintf('%s:真彩色圖像應使用M-N-3維度數組', mfilename); eid = sprintf('Images:%s:RGB Color Image Must Be M-N-3', mfilename); error(eid, '%s', msg); end % 檢查調色板 if ~isempty(map) if (size(map,2) ~= 3) || ndims(map)>2 msg1 = sprintf('%s:調色板必須是一個矩陣,有3列(R G B)', mfilename); error('Error', '%s', msg1); elseif (min(map(:))<0) || (max(map(:)>1)) msg1 = sprintf('%s:調色板中各個分量的強度應在[0,1]范圍', mfilename); error('Error', '%s', msg1); end end % int16轉uint16 if isa(A, 'int16') A = int16touint16(A); end
% imgrayscaling.m % 執行灰度拉伸 % 語法: % out = imgrayscaling(I, [x1,x2],[y1,y2]); % out = imgrayscaling(X, map, [x1,x2],[y1,y2]); % out = imgrayscaling(RGB, [x1,x2],[y1,y2]); % 執行灰度拉伸,輸入圖像應為灰度圖像,但是如果不是灰度圖像函數會自動將其轉換為灰度圖x1,x2,y1,y2應使用double類型 function out = imgrayscaling(varargin) % 解析參數 [A, map, x1, x2, y1, y2] = parse_inputs(varargin{:}); % 計算輸入圖像A中數據類型對應的取值范圍 range = getrangefromclass(A); range = range(2); % 如果不是灰度圖則轉換 if ndims(A)==3 % A矩陣為3維,RGB圖像 A = rgb2gray(A); elseif ~isempty(map) % 索引圖像 A = ind2gray(A, map); end % 讀取原始圖像大小,並初始化輸出圖像 [M,N] = size(A); I = im2double(A); % 轉double out = zeros(M,N); % 灰度拉伸 for m=1:M for n=1:N if I(m,n)<x1 out(m,n)=y1*I(m,n)/x1; elseif I(m,n)>x2 out(m,n)=(I(m,n)-x2)*(range-y2)/(range-x2)+y2; else out(m,n)=(I(m,n)-x1)*(y2-y1)/(x2-x1)+y1; end end end % 將輸出圖像的格式轉換成與輸入圖像相同 if isa(A,'uint8') out = im2uint8(out); elseif isa(A,'uint16') out=im2uint16(out); % 其他情況輸出double end % 輸出處理 if nargout==0 % 外面沒有接收返回值 imshow(out); return; end
I = imread('coins.png'); J1=imgrayscaling(I,[0.3 0.7],[0.15 0.85]); figure,imshow(J1,[]);title('[x1 x2]=[0.3 0.7], [y1 y2]=[0.15 0.85]'); J2=imgrayscaling(I,[0.15,0.85],[0.3,0.7]); figure,imshow(J2,[]);title('[x1 x2]=[0.15,0.85], [y1 y2]=[0.3,0.7]'); figure(3); subplot(1,2,1); imhist(J1); subplot(1,2,2); imhist(J2);
8.直方圖均衡化
直方圖均衡化也叫灰度均衡化,是指通過灰度映射使輸入圖像轉換為在每一灰度級上都有近似相同的像素點數的輸出圖像(即輸出的直方圖是均勻的)。經過處理的圖像中像素將占有盡可能多的灰度級並且分布均勻,因此具有較高的對比度和動態范圍。
首先考慮灰度級范圍為[0,1]連續的情況,此時圖像的歸一化直方圖即為概率密度函數(在數學中,連續型隨機變量的概率密度函數是一個描述這個隨機變量的輸出值在某個確定的取值點附近的可能性的函數;隨機變量的取值落在某個區域之內的概率則為概率密度函數在這個區域上的積分。當概率密度函數存在的時候,累積分布函數是概率密度函數的積分。百度百科:https://baike.baidu.com/item/%E6%A6%82%E7%8E%87%E5%AF%86%E5%BA%A6%E5%87%BD%E6%95%B0/5021996?fr=aladdin):
I=imread('pout.tif'); I=im2double(I); % 對於對比度較大的圖像 I1=2*I-55/255; subplot(4,4,1); imshow(I1); subplot(4,4,2); imhist(I1); subplot(4,4,3); % [J,T]=histeq(I)函數用於直方圖均衡化,輸入圖像I,輸出圖像J和變換矩陣T imshow(histeq(I)); subplot(4,4,4); imhist(histeq(I1)); % 對於對比度較小的圖像 I2=0.5*I+55/255; subplot(4,4,5); imshow(I2); subplot(4,4,6); imhist(I2); subplot(4,4,7); imshow(histeq(I2)); subplot(4,4,8); imhist(histeq(I2)); % 對於線性增加亮度的圖像 I3=I+55/255; subplot(4,4,9); imshow(I3); subplot(4,4,10); imhist(I3); subplot(4,4,11); imshow(histeq(I3)); subplot(4,4,12); imhist(histeq(I3)); % 對於線性減小亮度的圖像 I4=I-55/255; subplot(4,4,13); imshow(I4); subplot(4,4,14); imhist(I4); subplot(4,4,15); imshow(histeq(I4)); subplot(4,4,16); imhist(histeq(I4));
9.直方圖規定話(匹配)
Matlab示例:
% 實現從圖像I分別到圖像I1和I2的直方圖匹配 I=imread('pout.tif'); % 原圖 I1=imread('coins.png'); % 要匹配直方圖的圖像 I2=imread('circuit.tif'); % 要匹配直方圖的圖像 % 計算直方圖 [hgram1,x]=imhist(I1); [hgram2,x]=imhist(I2); % 執行直方圖均衡化 J1=histeq(I,hgram1); J2=histeq(I,hgram2); % 繪圖 subplot(2,3,1); imshow(I);title('原圖'); subplot(2,3,2); imshow(I1);title('標准圖1'); subplot(2,3,3); imshow(I2);title('標准圖2'); subplot(2,3,5); imshow(J1);title('匹配到1'); subplot(2,3,6); imshow(J2);title('匹配到2'); % 直方圖 figure; subplot(2,3,1); imhist(I);title('原圖'); subplot(2,3,2); imhist(I1);title('標准圖1'); subplot(2,3,3); imhist(I2);title('標准圖2'); subplot(2,3,5); imhist(J1);title('規定化到1'); subplot(2,3,6); imhist(J2);title('規定化到2');