[英]Matlab Image Processing - increasing contrast using histogram
我必須將灰度圖像導入到matlab中,將由無符號的8位整數組成的像素轉換為雙精度,繪制直方圖,最后使用以下轉換來改善圖像質量:
v'(x,y) = a(v(x,y)) + b
其中v(x,y)
是點x,y
處像素的值x,y
而v'(x,y)
是像素的新值。
我的主要問題是轉換時必須選擇的兩個常數a
和b
的值。 我的理解是,均衡的直方圖對於獲得良好的圖像是理想的。 互聯網上找到的其他代碼都使用內置的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
或使用圖像的概率密度函數(的前體,直方圖均衡)以增強圖像。 直方圖均衡化試圖使圖像直方圖平坦化,以使強度在圖像中遇到時或多或少是等概率的。 如果您希望對此主題進行更權威的解釋,請參見我有關直方圖均衡化工作原理的回答:
無論如何,選擇a
和b
的值在很大程度上取決於圖像。 但是,我想建議的一件事是使用min-max規范化 。 基本上,您可以使用直方圖並線性映射強度,以便將最低輸入強度映射到0,將最高輸入強度映射到圖像的關聯數據類型的最大值。 例如,如果您的圖像是uint8
,則意味着最高值將映射到255。
執行最小/最大歸一化非常容易。 它只是以下轉換:
out(x,y) = max_type*(in(x,y) - min(in)) / (max(in) - min(in));
in
與out
是輸入和輸出圖像。 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))
。
您將使它們a
和b
並運行您的代碼。 順便說一句,如果我有什么建議,請考慮向量化您的代碼。 您可以非常容易地使用該方程式並立即對整個圖像數據進行運算,而不用遍歷圖像中的每個值。
簡而言之,您的代碼現在如下所示:
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);
....不是更簡單嗎?
現在,修改您的代碼,以便以我們討論的方式計算新常數a
和b
:
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.