# How Do I Implement Histogram Normalization for RGB Image?

18 vues (au cours des 30 derniers jours)
Modifié(e) : DGM le 1 Avr 2024
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 commentairesAfficher AucuneMasquer Aucune
Modifié(e) : Nadira le 31 Mar 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 le 31 Mar 2024
Déplacé(e) : Voss le 31 Mar 2024
You have f1GNormal two times:
cat(3,f1RNormal,f1GNormal,f1GNormal)
The last one should be f1BNormal.
If you change that, does it seem right?

Connectez-vous pour commenter.

### Réponses (2)

DGM le 31 Mar 2024
Modifié(e) : DGM le 1 Avr 2024
Unless you're converting your image to unit-scale floating point, then these operations will destroy the image.
% 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 = 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
% 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.
##### 0 commentairesAfficher -2 commentaires plus anciensMasquer -2 commentaires plus anciens

Connectez-vous pour commenter.

Image Analyst le 1 Avr 2024
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;
%--------------------------------------------------------------------------------------------------------
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
%--------------------------------------------------------------------------------------------------------
% 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);
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;
##### 0 commentairesAfficher -2 commentaires plus anciensMasquer -2 commentaires plus anciens

Connectez-vous pour commenter.

### Catégories

En savoir plus sur Image Processing and Computer Vision dans Help Center et File Exchange

R2023a

### Community Treasure Hunt

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

Start Hunting!

Translated by