How Do I Implement Histogram Normalization for RGB Image?

38 visualizaciones (últimos 30 días)
Nadira
Nadira el 31 de Mzo. de 2024 a las 3:09
Editada: DGM el 1 de Abr. de 2024 a las 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 comentarios
Nadira
Nadira el 31 de Mzo. de 2024 a las 3:12
Editada: Nadira el 31 de Mzo. de 2024 a las 3:12
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 el 31 de Mzo. de 2024 a las 3:15
Movida: Voss el 31 de Mzo. de 2024 a las 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?

Iniciar sesión para comentar.

Respuestas (2)

DGM
DGM el 31 de Mzo. de 2024 a las 14:24
Editada: DGM el 1 de Abr. de 2024 a las 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 el 1 de Abr. de 2024 a las 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;

Categorías

Más información sobre Image Processing and Computer Vision en Help Center y File Exchange.

Productos


Versión

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by