How Do I Implement Histogram Normalization for RGB Image?

23 Ansichten (letzte 30 Tage)
Nadira
Nadira am 31 Mär. 2024
Bearbeitet: DGM am 1 Apr. 2024 um 16:17
I want to implement some image enhancement like, histogram normalization and histogram equalization for an RGB image? To do so, first I taking the R, G, B channel separately and do the normalization on each of the channel. and after that I combine it
using the
cat(3,R,G,B)
but, the image result is kind of weird so I was wondering am I doint it right?
  2 Kommentare
Nadira
Nadira am 31 Mär. 2024
Bearbeitet: Nadira am 31 Mär. 2024
Here is how I implement the histogram normalization
f1R = f1(:,:,1);
f1G = f1(:,:,2);
f1B = f1(:,:,3);
Bmax = max(max(f1B));
Bmin = min(min(f1B));
f1BNormal = (f1B-Bmin)./(Bmax-Bmin).*255;
Gmax = max(max(f1G));
Gmin = min(min(f1G));
f1GNormal = (f1G-Gmin)./(Gmax-Gmin).*255;
Rmax = max(max(f1R));
Rmin = min(min(f1R));
f1RNormal = (f1R-Rmin)./(Rmax-Rmin).*255;
f1Normal = cat(3,f1RNormal,f1GNormal,f1GNormal);
Voss
Voss am 31 Mär. 2024
Verschoben: Voss am 31 Mär. 2024 um 15:25
You have f1GNormal two times:
cat(3,f1RNormal,f1GNormal,f1GNormal)
The last one should be f1BNormal.
If you change that, does it seem right?

Melden Sie sich an, um zu kommentieren.

Antworten (2)

DGM
DGM am 31 Mär. 2024 um 14:24
Bearbeitet: DGM am 1 Apr. 2024 um 16:17
Unless you're converting your image to unit-scale floating point, then these operations will destroy the image.
inpict = imread('westconcordaerial.png'); % uint8
% split the image
[f1R f1G f1B] = imsplit(inpict);
% normalize each channel
% this is where the image data is destroyed
Bmax = max(max(f1B));
Bmin = min(min(f1B));
f1BNormal = (f1B-Bmin)./(Bmax-Bmin).*255;
Gmax = max(max(f1G));
Gmin = min(min(f1G));
f1GNormal = (f1G-Gmin)./(Gmax-Gmin).*255;
Rmax = max(max(f1R));
Rmin = min(min(f1R));
f1RNormal = (f1R-Rmin)./(Rmax-Rmin).*255;
% reassemble the image
outpict = cat(3,f1RNormal,f1GNormal,f1BNormal); % still uint8
% compare the images
montage({inpict,outpict})
If your image is unit-scale float, then the result will be improperly scaled for its class and will be mishandled by many tools such as imshow(), imwrite(), etc. It will be unviewable, and it will be destroyed if saved without explicitly being cast or rescaled.
inpict = imread('westconcordaerial.png'); % uint8
inpict = im2double(inpict); % unit-scale float
% split the image
[f1R f1G f1B] = imsplit(inpict);
% normalize each channel
% no data is lost here, but it's improperly scaled
Bmax = max(max(f1B));
Bmin = min(min(f1B));
f1BNormal = (f1B-Bmin)./(Bmax-Bmin).*255;
Gmax = max(max(f1G));
Gmin = min(min(f1G));
f1GNormal = (f1G-Gmin)./(Gmax-Gmin).*255;
Rmax = max(max(f1R));
Rmin = min(min(f1R));
f1RNormal = (f1R-Rmin)./(Rmax-Rmin).*255;
% reassemble the image
outpict = cat(3,f1RNormal,f1GNormal,f1BNormal); % improperly-scaled float
% compare the images
montage({inpict,outpict}) % nothing will handle it correctly
There is an image there, but there are only three pixels which are not truncated at white.
You can avoid all this by just using imadjust(). Use stretchlim() to get the input limits.
inpict = imread('westconcordaerial.png'); % any standard image class
% normalize each channel with respect to its extrema
outpict = imadjust(inpict,stretchlim(inpict,0));
% compare the images
montage({inpict,outpict})
Like @Image Analyst points out, doing independent normalization on the channels will shift the color balance. Sometimes that's a bad thing. Sometimes that's coincidentally a good thing. Will anyone notice? What will they conclude? Truly it is a mystery.

Image Analyst
Image Analyst am 1 Apr. 2024 um 3:07
Yes it will look weird. That's because you stretched each color channel independently and that destroys the color relationship. What you should have done was to convert to HSV color space and stretch the V channel ONLY. Then convert back. This will change only the brightness and contrast of the image but maintain the hues (colors).
Here is a full demo.
% Demo by Image Analyst
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
markerSize = 20;
%--------------------------------------------------------------------------------------------------------
% READ IN TEST IMAGE
folder = [];
% baseFileName = 'pears.png';
baseFileName = 'hands2.jpg';
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
rgbImage = imread(fullFileName);
%--------------------------------------------------------------------------------------------------------
% Display the image.
subplot(2, 2, 1);
imshow(rgbImage, []);
impixelinfo;
axis('on', 'image');
title('Original RGB Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Update the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(rgbImage)
% Maximize window.
g = gcf;
g.WindowState = 'maximized';
g.Name = 'Demo by Image Analyst';
g.NumberTitle = 'off';
drawnow;
%--------------------------------------------------------------------------------------------
% Convert to HSV color space
hsvImage = rgb2hsv(rgbImage);
% Split into separate channels
[hImage, sImage, vImage] = imsplit(hsvImage);
subplot(2, 2, 2);
imshow(vImage)
impixelinfo;
axis('on', 'image');
title('Original V Image', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
fprintf('Max V value = %f.\n', max(vImage, [], 'all'))
%--------------------------------------------------------------------------------------------
% Rescale the v image
% vImage = rescale(vImage, 0, 1);
vImage = imadjust(vImage);
subplot(2, 2, 3);
imshow(vImage)
impixelinfo;
axis('on', 'image');
title('Scaled V Image', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
fprintf('Now Max V value = %f.\n', max(vImage, [], 'all'))
%--------------------------------------------------------------------------------------------
% Recompbine into HSV image
hsvImage = cat(3, hImage, sImage, vImage);
% Convert back to RGB
rgbImage2 = hsv2rgb(hsvImage);
subplot(2, 2, 4);
imshow(rgbImage2)
impixelinfo;
axis('on', 'image');
title('Scaled RGBImage', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;

Kategorien

Mehr zu Image Processing and Computer Vision finden Sie in Help Center und File Exchange

Produkte


Version

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by