Matlab圖像處理系列1———線性變換和直方圖均衡

注:本系列來自於圖像處理課程實驗,用Matlab實現最基本的圖像處理算法

圖像點處理是圖像處理系列的基礎,主要用於讓我們熟悉Matlab圖像處理的編程環境。灰度線性變換和灰度拉伸是對像素灰度值的變換操作,直方圖是對像素灰度值的統計,直方圖均衡是對灰度值分佈的變換。


1.灰度線性變換

(1)線性變換函數

原圖向灰度值爲g,通過線性函數f(x)=kx+b轉換爲f(g)得到灰度的線性變換。

(2)代碼實現

Matlab中支持矩陣作爲函數參數傳入,定義一個線性轉換函數,利用Matlab矩陣操作,用一行代碼即可對整個二維圖像矩陣中所有點的灰度進行線性變換:

function [ new ] = LinearTransformFunc( original, k, d )
    new = original * k + d;
end

其中k和d是線性函數的斜率和截距,由用戶輸入指定,用戶輸入爲空時賦予默認值:

  • input函數獲取用戶輸入
  • isempty判斷用戶輸入是否爲空:
k = input('please input the slope(k) of grayscale linear transformation function:\n');

b = input('please input the intercept(b) of grayscale linear transformation function:\n');

if isempty(k)
    k = 1;
end

if isempty(b)
    b = 0;
end

變換圖像名也可以由用戶input指定,默認爲lena圖:

  • imread讀出圖片,返回值第一個是我們需要的灰度圖(二維矩陣)
  • 對變換後的灰度圖,用imshowfigure中顯示圖像
name = input('please input the name of image:\n');

if isempty(name) 
    name = 'lena'; 
end

original = imread(strcat('../exp/', name, '.bmp'));

transformed = LinearTransformFunc(original, k, b);

figure
imshow(transformed)

在這個實驗的操作中說明如何讀入、顯示,後面實驗不在贅述

(3)運行結果

利用subplot作圖,把原圖和線性變換後的圖像對比,線性變換函數是f(x)=2x+10:

這裏寫圖片描述

左圖是原圖像,右圖是線性變換後圖像。


2.灰度拉伸變換

(1)灰度拉伸變換和線性分段函數

灰度拉伸變換和線性變換相似,只是是將灰度值做分段線性變換。分段函數控制點(x1,y1)(x2,y2)

這裏寫圖片描述

(2)代碼實現

整個程序用戶接口和流程和線性變換相同,只是需要用戶輸入兩個控制點,並傳入以下的分段線性變換函數:

function [ new ] = StretchFunc(original, x1, y1, x2, y2 )
    new = original;

    w = size(new, 1);
    h = size(new, 2);

    k1 = y1 / x1;

    dk1 = (y2 - y1) / (x2 - x1);
    dk2 = (255 - y2) / (255 - x2);

    for i = 1 : w
        for j = 1 : h
            x = new(i, j);
            if x < x1
                new(i, j) = k1 * x;
            elseif x < x2
                new(i, j) = dk1 * (x - x1) + y1;
            else
                new(i, j) = dk2 * (x - x2) + y2;
            end
        end
    end
end

這裏不可避免要使用到for循環。

(3)運行結果

同樣對比原圖,默認控制點選取(-100,20)和(100,180)

這裏寫圖片描述


3.灰度直方圖

(1)灰度直方圖

灰度直方圖就是對圖像中每個像素點的灰度值出現的頻數或頻率(歸一化)的統計,那麼我們直接遍歷整個圖像統計出每個灰度值出現次數再做相應處理即可。

(2)代碼實現

首先需要遍歷統計灰度,我在GrayScaleStatistic函數裏完成統計,區間[low, high]是目標灰度統計區間,默認是[0,255]:

function [ result ] = GrayScaleStatistic( original, low, high )

    w = size(original, 1);
    h = size(original, 2);
    result = zeros(1, high - low + 1);

    for i = 1 : w
        for j = 1 : h
            g = original(i, j);
            if g >= low && g <= high
                g = g - low + 1;
                result(g) = result(g) + 1; 
            end
        end
    end

end

然後就使用Matlab條形圖作圖函數bar完成灰度圖作圖:

y = GrayScaleStatistic(original, low, high);
x = low : 1 : high;
bar(x, y)

對於題目要求的可輸入灰度區間顯示,我們要麼不統計區間[low, high]以外的灰度值,要麼直接全部統計但在作圖時用xlim函數限制x軸取值範圍:

xlim([low, high])

(3)運行結果

對比Matlab標準直方圖作圖函數histogram,結果如下:

這裏寫圖片

也可以通過input輸入限定區間,這裏是[20,150]區間的灰度直方圖:

這裏寫圖片描述

左右對比,效果一致。


4.直方圖均衡化

(1)直方圖均衡算法

直方圖均衡主要用於增強動態範圍偏小的圖像的反差,其基本思想是把原始圖像的直方圖變換爲均勻分佈,從而增強灰度值的動態範圍,以達到增強對比度的效果。

直方圖均衡化算法如下

  1. 歸一化灰度頻數直方圖,得到頻率直方圖sk
  2. sk計算頻率累計直方圖tk
  3. tk做取整擴展:tk = int[(L - 1) * tk + 0.5],將直方圖灰度映射儘量滿整個灰度取值空間L
  4. 確定變換映射關係k->tk
  5. 根據映射關係變換圖像灰度值

(2)代碼實現

在腳本中調用Normalize函數直接得到均衡化後的圖像,再統計直方圖並顯示。

Normalize函數如下:

function [ new ] = Normalize( original, v )

    s = sum(v);
    tv = v / s;

    l = length(v);

    for i = 2 : l
        tv(i) = tv(i) + tv(i - 1);
    end

    tk = uint8(255 * tv + 0.5);

    w = size(original, 1);
    h = size(original, 2);

    new = original;

    for i = 1 : w
        for j = 1 : h
            new(i, j) = tk(original(i, j) + 1);
        end
    end

end

說明:

  • tv先計算頻率直方圖,再通過累加得到累計直方圖
  • tk根據累計直方圖計算新的灰度映射關係
  • 最後遍歷整個圖像把原灰度轉換成均衡化後的灰度值

其中有一下幾點需要注意,也是Matlab圖操作的注意點:

  • Matlab默認類型是double,對灰度值賦值時注意強制轉換類型,保證類型一致
  • Matlab座標起始從1開始,而灰度值是uint8的0-255,因此映射數組tk把原始灰度映射到變換後灰度時需要加1

(3)結果展示

pout.bmp是一副灰度分佈較爲集中的圖像,因此圖像對比度不高,顯示較爲模糊。使用直方圖均值化,分散灰度分佈從而增強對比度:

j

通過對比均衡先後直方圖分佈,可以發現:

  • 灰度分佈不能完全平均化,是由於均值化算法中運用了取整運算,而不是離散值的完全均衡化
  • 得到的均衡化後直方圖走勢沒有發生變化,因此圖像沒有失真

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章