簡體   English   中英

Matlab圖像處理-使用直方圖提高對比度

[英]Matlab Image Processing - increasing contrast using histogram

我必須將灰度圖像導入到matlab中,將由無符號的8位整數組成的像素轉換為雙精度,繪制直方圖,最后使用以下轉換來改善圖像質量:

v'(x,y) = a(v(x,y)) + b 

其中v(x,y)是點x,y處像素的值x,yv'(x,y)是像素的新值。

我的主要問題是轉換時必須選擇的兩個常數ab的值。 我的理解是,均衡的直方圖對於獲得良好的圖像是理想的。 互聯網上找到的其他代碼都使用內置的MATLAB histeq函數或計算概率密度。 我在任何地方都找不到為上述轉換選擇常量的參考。

我想知道是否有人對如何選擇這些常量有任何建議或想法。 我認為我的其余代碼可以實現預期的功能:

 image = imread('image.png');
 image_of_doubles = double(image);

 for i=1:1024
     for j=1:806
            pixel = image_of_doubles(i,j);
            pixel = 0.95*pixel + 5;
            image_of_doubles(i,j) = pixel;
    end
end

[n_elements,centers] = hist(image_of_doubles(:),20);
bar(centers,n_elements);

xlim([0 255]);

編輯:我也玩了一些不同的常量值。 改變時a常數似乎是拉伸直方圖a常數。 但是,這僅適用於介於0.8-1.2之間的值(並且拉伸范圍不足-僅在150-290范圍內使直方圖相等)。 如果將a設為0.5,則直方圖將被分為兩個斑點,其中許多像素的強度大約為4或5; 同樣,至少沒有相等。

您感興趣的操作稱為線性對比度拉伸 基本上,您希望將每個強度乘以某個增益,然后將強度偏移某個數字,以便可以操縱直方圖的動態范圍。 這是一樣的histeq或使用圖像的概率密度函數(的前體,直方圖均衡)以增強圖像。 直方圖均衡化試圖使圖像直方圖平坦化,以使強度在圖像中遇到時或多或少是等概率的。 如果您希望對此主題進行更權威的解釋,請參見我有關直方圖均衡化工作原理的回答:

MATLAB中直方圖均衡功能的說明


無論如何,選擇ab的值在很大程度上取決於圖像。 但是,我想建議的一件事是使用min-max規范化 基本上,您可以使用直方圖並線性映射強度,以便將最低輸入強度映射到0,將最高輸入強度映射到圖像的關聯數據類型的最大值。 例如,如果您的圖像是uint8 ,則意味着最高值將映射到255。

執行最小/最大歸一化非常容易。 它只是以下轉換:

out(x,y) = max_type*(in(x,y) - min(in)) / (max(in) - min(in));

inout是輸入和輸出圖像。 min(in)max(in)是輸入圖像的整體最小值和最大值。 max_type是與輸入圖像類型關聯的最大值。

對於輸入圖像的每個位置(x,y) ,您都可以替換輸入圖像的強度,並通過上面的公式進行運算以獲得輸出。 您可以說服自己,用min(in)max(in)代替in(x,y)會分別給您0和max_type ,其他所有參數都在此之間線性縮放。

現在,通過一些代數運算,您可以使它的形式為問題陳述中提到的out(x,y) = a*in(x,y) + b 具體來說:

out(x,y) = max_type*(in(x,y) - min(in)) / (max(in) - min(in));
out(x,y) = (max_type*in(x,y)/(max(in) - min(in)) - (max_type*min(in)) / (max(in) - min(in)) // Distributing max_type in the summation
out(x,y) = (max_type/(max(in) - min(in)))*in(x,y) - (max_type*min(in))/(max(in) - min(in)) // Re-arranging first term

out(x,y) = a*in(x,y) + b

a簡單地是(max_type/(max(in) - min(in))b-(max_type*min(in))/(max(in) - min(in))

您將使它們ab並運行您的代碼。 順便說一句,如果我有什么建議,請考慮向量化您的代碼。 您可以非常容易地使用該方程式並立即對整個圖像數據進行運算,而不用遍歷圖像中的每個值。

簡而言之,您的代碼現在如下所示:

image = imread('image.png');
image_of_doubles = 0.95*double(image) + 5; %// New

[n_elements,centers] = hist(image_of_doubles(:),20);
bar(centers,n_elements);

....不是更簡單嗎?

現在,修改您的代碼,以便以我們討論的方式計算新常數ab

image = imread('image.png');

%// New - get maximum value for image type
max_type = double(intmax(class(image)));

%// Calculate a and b
min_val = double(min(image(:)));
max_val = double(max(image(:)));
a = max_type / (max_val - min_val);
b = -(max_type*min_val) / (max_val - min_val);

%// Compute transformation
image_of_doubles = a*double(image) + b;

%// Plot the histogram - before and after
figure;
subplot(2,1,1);
[n_elements1,centers1] = hist(double(image(:)),20);
bar(centers1,n_elements1);
%// Change
xlim([0 max_type]);

subplot(2,1,2);
[n_elements2,centers2] = hist(image_of_doubles(:),20);
bar(centers2,n_elements2);
%// Change
xlim([0 max_type]);

%// New - show both images
figure; subplot(1,2,1);
imshow(image);
subplot(1,2,2);
imshow(image_of_doubles,[]);

這是非常重要的,你投的最大整數double ,因為什么被返回的不僅是整數,但整數轉換為數據類型。 我還自由更改了代碼,以便我們可以在轉換之前和之后顯示直方圖,以及在轉換之前和之后圖像的外觀。


作為查看這項工作的示例,讓我們使用圖像處理工具箱中的pout.tif圖像。 看起來像這樣:

在此處輸入圖片說明

可以肯定地看到,這需要一些圖像對比度增強操作,因為強度的動態范圍非常有限。 這看起來像洗掉了。

使用此圖像作為圖像,這就是直方圖之前和之后的樣子。

在此處輸入圖片說明

我們當然可以看到直方圖被拉伸了。 現在這是圖像的樣子:

在此處輸入圖片說明

您肯定可以看到更多細節,即使它更暗。 這告訴您,簡單的線性縮放是不夠的。 您可能需要實際使用直方圖均衡,或者使用伽瑪定律或冪定律變換。


希望這足以使您入門。 祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM