1. 程式人生 > >【影象處理筆記】灰度變換

【影象處理筆記】灰度變換

最近在學習岡薩雷斯的《數字影象處理》,想把整理的筆記和自己實現的小實驗整理在部落格上~

今天的主題是影象的灰度變換:

g(x,y)= T [ f(x,y)]

f(x,y)是輸入影象,g(x,y)是處理後的影象,T是在點(x,y)鄰域上定義的關於f 的一種運算元。

T處理,從輸入影象的左上角開始,以水平掃描的方式逐畫素地處理。當該鄰域的圓點位於影象的邊界上時,部分鄰域將位於影象的外部。此時,不是忽略外側鄰點,就是用0或者其他指定的灰度值填充影象的邊緣。被填充的邊界的厚度取決於鄰域的大小。

以上的描述過程稱為空間濾波,其中,鄰域與預定義的操作一起稱為空間濾波器(也稱為空間掩模、核、模板或視窗)。

最小鄰域的大小為1×1。在這種情況下,g 僅取決於點(x,y)處的灰度值f ,而T則成為一個形如下式的灰度(也稱為灰度級或對映)變換函式:

S = T(r)

其中,為表達方便,另r和S分別表示變數,即g和f 在任意點(x,y)處的灰度。

例如,如果T(r)有如圖所示的形式


對f 中每一個畫素施以變換產生相應的g的畫素的效果將比原影象有更高的對比度。這種技術被稱為對比度拉伸。

極限情況下,會產生二級(二值)圖


影象增強技術是面向問題的,沒有通用的“理論”。

一些基本的灰度變換函式:

①影象反轉

S = L - 1 - r

通俗的說,就是影象的黑邊反轉交換。

特別適用於增強嵌入在一幅影象的暗區域中的白色或灰色細節。

②對數變換

S = c*log(1+ r)


改變換將輸入中範圍較窄的低灰度值對映為輸出中較寬範圍的灰度值,對範圍較寬的高輸入灰度值對映為輸出中較窄範圍的灰度值。

我們一般使用這種型別的變換來擴充套件影象中的暗畫素值,同時壓縮更高灰度級的值。

反對數變換的作用與此正好相反。

對數函式的一般形狀的任何曲線,都能完成影象的灰度級的擴充套件和壓縮,但是一會介紹的冪律變換對於這個目的更為通用。

對數函式有個重要的特徵,即它壓縮畫素值變換較大的影象的動態範圍。這一特徵一般被應用於傅立葉頻譜中。

通常,頻譜值的範圍從0到10^6,甚至更高。儘管計算機能毫無疑問的處理這一範圍的數字,但影象的顯示系統通常不能如實地再現如此大範圍的灰度值。因而,最終結果是許多重要的灰度細節在典型的傅立葉頻譜的顯示中丟失了。

如果我們先將這些頻譜進行對數函式的對比度拉伸,再線性的縮放到新的值域,並在同一個8位元顯示系統中顯示頻譜的結果。會看到很多豐富的細節。

③冪律(伽馬)變換

S = c* r ^γ


習慣上,冪律方程中的指數被稱為伽馬

用於校正冪律響應現象的處理稱為伽馬校正

冪律變換與對數變換一樣,也可以擴充套件和壓縮一些灰度級,且應用的更為廣泛。

④分段線性變換函式

優點:形式可以是任意複雜的。

缺點:技術說明要求使用者輸入。

上面就是關於灰度變換的一些總結。

下面我想做一個小實驗,對一幅光照不均勻的影象,進行一下伽馬變換的對比度拉伸,調整一下顯示的亮度。

我是用VB.NET的Emgu來實現的。

這個是原圖


'伽馬變換的灰度拉伸
'處理光照不均勻的影象
Dim img As New Image(Of Gray, Byte)("C:\test.bmp")
Dim height As Integer = img.Height
Dim width As Integer = img.Width
Dim gama As Double = 0.4

Dim Sbigest As Integer = 0
Dim Sfewest As Integer = 255
For i = 0 To height - 1
    For j = 0 To width - 1
        If img.Data(i, j, 0) < Sfewest Then
            Sfewest = img.Data(i, j, 0)
        End If
        If img.Data(i, j, 0) > Sbigest Then
            Sbigest = img.Data(i, j, 0)
        End If
    Next
Next
For i = 0 To height - 1
    For j = 0 To width - 1
        img.Data(i, j, 0) = (img.Data(i, j, 0) ^ gama - Sfewest ^ gama) / (Sbigest ^ gama - Sfewest ^ gama) * 255
    Next
Next
img.Save("C:\test-result.bmp")

處理後的結果,其實效果還可以。只是不道為啥圖片一貼上到部落格上,較深的背景就會變成綠色的了。

2015.9.3補充~

最近細緻的學習了灰度變換以及直方圖的一些相關的處理,回過頭來,想把這篇博文中的那張圖處理下。

之前的實驗結果,伽馬變換後的圖片,四個角的部位都有陰影。這是因為那些部分的灰度值都較小,影象較暗,伽馬變換後也難以校正。

如果想校正這部分割槽域,就需要考慮對比度的問題,才能對我們想要的部分進行有效的增強。

因此我想求出整體的方差與區域性的方差。如果區域性的方差大於整體方差,則認為是文字與背景的交界區域。否則,則認為是背景。

以下是程式碼實現。放假在家沒有VS,只好用matlab實現的~

clear all;
close all;
clc;

I = imread('C:\test\src.bmp');  
I = rgb2gray(I);
[height,width] = size(I);
E1 = 1.6;
E2 = 10;
k0 = 0.9;
k1 = 0.8;
k2 = 0.2;

m = 0;
for i=1:height
    for j=1:width
        m = m + double(I(i,j));
    end
end
%灰度級平均值
m = m / (height * width);
variance = 0;
for i=1:height
    for j=1:width
        variance = variance + (double(I(i,j) - m))^2;
    end
end
%灰度方差
variance = variance / (height * width);

I2 = I;
for i=1:height
    for j=1:width
        
        m1 = 0;        
        for h1 = i - 3: i + 3
            for h2 = j - 3: j + 3
                if(h1)<1 || (h2)<1 || (h1)>height || (h2)>width
                    m1 = m1 + m;
                else
                    m1 = m1 + double(I(h1,h2));
                end 
            end
        end
        m1 = m1 / 49;
        variance1 = 0;
        for h1 = i - 3: i + 3
            for h2 = j - 3: j + 3
                if(h1)<1 || (h2)<1 || (h1)>height || (h2)>width
                    variance1 = variance1 + (m1 - m)^2;
                else
                    variance1 = variance1 + (double(I(h1,h2)) - m1)^2;
                end 
            end
        end
        variance1 = variance1 / 49;

        if  (variance1 >= k1 * variance) && (m1 <= I(i,j))
           %方差大於平均方差
           %該點處的灰度值大於鄰域的平均灰度值
           I2(i,j) = E1*I(i,j) ;
        elseif (variance1 >= k1 * variance) && (m1 > I(i,j))
           
        elseif (variance1 < k2 * variance)           
           I2(i,j) = 2*E2*I(i,j) ;
        else
        end        
    end
end
imwrite(I2,'C:/test/test_result.bmp','bmp');


圖片邊上的黑邊是因為鄰域的選取造成的。