Background color correction of a rgb picture

16 views (last 30 days)
Recently i took this picture with a thermocamera, the color of the background should be homogeneus and more or less similir to the one in the center (red/orange), but on the corners of the picture due to small field of view of the camera it is violet/blue. how i can make it more uniform?? thanks in advance

Answers (5)

Image Analyst
Image Analyst on 14 Mar 2023
Try this:
% Demo by Image Analyst
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear all;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
%===============================================================================
% Get the name of the image the user wants to use.
baseFileName = 'prova2.jpg';
folder = pwd;
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
%=======================================================================================
% Read in image.
rgbImage = imread(fullFileName);
% Get the dimensions of the image.
[rows, columns, numberOfColorChannels] = size(rgbImage)
% Display image.
subplot(3, 1, 1);
imshow(rgbImage, []);
impixelinfo;
axis on;
caption = sprintf('Original RGB Image\n%s', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
g2 = gcf;
g2.WindowState = "maximized";
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
drawnow;
%=======================================================================================
% Read in template/mask image.
fullFileName = fullfile(folder, 'prova2 mask.png');
maskImage = imread(fullFileName);
% Get the dimensions of the image.
[rows, columns, numberOfColorChannels] = size(maskImage);
% Make sure it's binary.
if numberOfColorChannels > 3
maskImage = maskImage(:, :, 1) > 0;
else
maskImage = maskImage > 0;
end
% Display image.
subplot(3, 1, 2);
imshow(maskImage, []);
impixelinfo;
axis on;
caption = sprintf('Mask Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
%--------------------------------------------------------------------------------------------------
% Get the bottom part of the image
midRow = floor(rows / 2);
rgbImage2 = rgbImage(midRow:end, :, :);
mask2 = maskImage(midRow:end, :);
% Split up into individual color channels.
[r2, g2, b2] = imsplit(rgbImage2);
%--------------------------------------------------------------------------------------------------
% Get the mean RGB of the bottom half of the image outside of the mask
meanR = mean(r2(mask2));
meanG = mean(g2(mask2));
meanB = mean(b2(mask2));
%--------------------------------------------------------------------------------------------------
% Split up into individual color channels.
[r, g, b] = imsplit(rgbImage);
% Make everywhere outside the mask that color.
r(~maskImage) = meanR;
g(~maskImage) = meanG;
b(~maskImage) = meanB;
% Reconstruct RGB image.
rgbImage3 = cat(3, r, g, b);
% Display image.
subplot(3, 1, 3);
imshow(rgbImage3, []);
impixelinfo;
axis on;
title('Background-replaced Image', 'FontSize', fontSize, 'Interpreter', 'None');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
drawnow;
  10 Comments
Gianmaria Gasperoni
Gianmaria Gasperoni on 17 Mar 2023
Understood you are right. in the meanwhile, that i'm going speek with my tutor, can you tell me how i can do the flattening of a RGB picture?
Thanks
DGM
DGM on 17 Mar 2023
You have to do the flattening on the grayscale version.
Using imflatfield() directly on the RGB image flattens V in HSV. The resulting image no longer works with the original colormap. All scale information is lost. It's also worth noting that since V is a poor measure of perceived lightness, the operation doesn't really accomplish much perceived flattening.
% the false-color image
inpict = imread('prova2.jpg');
% flatten the image by flattening V in HSV
flattenedhsv = imflatfield(inpict,10);
imshow(flattenedhsv)
You could flatten each RGB channel, but again that results in an image which does not adhere to the colormap. Also, stretching B emphasizes a bunch of compression artifacts that used to be buried near black.
% flatten the image in RGB
flattenedrgb = inpict;
for c = 1:3
flattenedrgb(:,:,c) = imflatfield(inpict(:,:,c),10);
end
imshow(flattenedrgb)
Convert to grayscale with the appropriate color map, do the operations, and then convert back (if necessary). The result is an image which can still be read using the same map, though it's questionable whether the particular temperature values correspond to the surface temperature anymore.
% do the flattening on the grayscale copy as before
CT = ccmap_short('flir1',256);
Trange = [30 80]; % complete guess
tpict = rgb2ind(inpict,CT,'nodither');
tpict = rescale(tpict,Trange(1),Trange(2));
flattened = imflatfield(tpict,10);
flattened = mat2gray(flattened,Trange); % normalize
flattened = gray2ind(flattened,size(CT,1)); % quantize
flattened = ind2rgb(flattened,CT);
imshow(flattened)

Sign in to comment.


Praveen Reddy
Praveen Reddy on 13 Mar 2023
Hi Gianmaria,
I understand that you wanted to have your image background a uniform color. The following resources might help you:
  1 Comment
Gianmaria Gasperoni
Gianmaria Gasperoni on 13 Mar 2023
First of all thanks for the answer. Maybe i didn't explain it well. So the problem in not on the squares, the problem is on the background. The color of the background in the center and bottom part of the picture is the real one and i want to obtain somenthing similar on the top part where the blue and violet are dominant(without changing the palette of color).
i hope i was clear and thanks in advance

Sign in to comment.


Image Analyst
Image Analyst on 13 Mar 2023
See attached demo. Adapt as needed. You will need to come up with a mask for the squares. Hopefully they are in the same location for all images and you can just make up a template manually.
  4 Comments
Gianmaria Gasperoni
Gianmaria Gasperoni on 13 Mar 2023
Yes u are right,sorry.
Im not sure that i can use a template, i think not but i will ask.
My teacher told me to take inspiration from this https://it.mathworks.com/help/images/correcting-nonuniform-illumination.html . i have understood the logic behind but applying the same procedure on a rgb picture the result obtained is absolutely not good.
Image Analyst
Image Analyst on 14 Mar 2023
Well I did it on an RGB image. The logic is about the same.

Sign in to comment.


DGM
DGM on 14 Mar 2023
Edited: DGM on 25 Mar 2023
This looks more like a slightly off-normal camera position and a reflective surface.
Either way, you don't operate on the false-color image. You convert the image to a grayscale representation of temperature. For that, you'd need to know the colormap and the scaling.
% the false-color image
inpict = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1315795/prova2.jpg');
% i only assume that this is approximately the map in use
CT = flirmap('flir1',256);
% i'm going to assume that the mapping is linear
% and that these are the extents of T represented
Trange = [30 80]; % complete guess
% convert from false-color to temperature
% this image will be quantized
tpict = rgb2ind(inpict,CT,'nodither');
tpict = rescale(tpict,Trange(1),Trange(2));
hi = imshow(tpict,Trange);
datatip(hi,160,120,'location','northwest');
datatip(hi,670,140,'location','northeast');
datatip(hi,100,600,'location','southeast');
At this point, you can use imflatfield() or whater you want on it, but you're going to be left with the problem of losing your temperature information. You'll be left with a new image whose scale has nothing to do with the original. It's anybody's guess what the actual temperatures are now.
% flatten the image
flattened = imflatfield(tpict,10);
hi = imshow(flattened,Trange);
datatip(hi,160,120,'location','northwest');
datatip(hi,670,140,'location','northeast');
datatip(hi,100,600,'location','southeast');
If the temperature of the background is what matters, then you've lost that information. It's just been roughly averaged out. If you can assume that it's some uniform temperature, then you'd have to offset the result accordingly.
Of course, the temperature of the squares has been lost and even the local uniformity has been lost due to edge effects, so rescaling based on another assumed temperature reference isn't much of a fix.
Could you make a composite image out of the two? Sure, but that sounds an awful lot like fabricating measurements.
  4 Comments
Gianmaria Gasperoni
Gianmaria Gasperoni on 16 Mar 2023
First of all the picture on the top is part of a video that i need to analyze. Information regarding the background and the square are both important because allow us to predict some strange behaviur during the process (porosity, cracks etc). the interesting information can be extracted using the T, intensity of each pixel ecc. the squares should be equally reflective because are made by the same material (without considering little variation due to porosity ecc)
DGM
DGM on 16 Mar 2023
Edited: DGM on 25 Mar 2023
I don't know if this is any help. It's more or less a middleground between what IA and I have posted.
% the false-color image
inpict = imread('prova2.jpg');
% i only assume that this is approximately the map in use
CT = flirmap('flir1',256);
% i'm going to assume that the mapping is linear
% and that these are the extents of T represented
Trange = [30 80]; % complete guess
% convert from false-color to temperature
% this image will be quantized
tpict = rgb2ind(inpict,CT,'nodither');
tpict = rescale(tpict,Trange(1),Trange(2));
% flatten the image
flattened = imflatfield(tpict,10);
imshow(flattened,Trange);
% copy the squares back?
mask = im2double(imread('softmask.png'));
outpict = mask.*tpict + (1-mask).*flattened;
imshow(outpict,[])
% convert back to pseudocolor if desired
outpict = mat2gray(outpict,Trange); % normalize
outpict = gray2ind(outpict,size(CT,1)); % quantize
outpict = ind2rgb(outpict,CT);
imshow(outpict)
I don't know if it matters, but I used a soft mask for the composition to avoid creating any false edge features which might interfere with crack detection.

Sign in to comment.


Image Analyst
Image Analyst on 15 Mar 2023
If you want to convert a pseudocolored thermal image to an image where the pixel values are the actual temperatures, see attached demo.
  1 Comment
DGM
DGM on 16 Mar 2023
Edited: DGM on 25 Mar 2023
FWIW, the colormap generator I attached above will also generate an approximation of this particular map.
Avoiding colorbar extraction is a big deal, considering that most snapshots are pretty low-quality. They're usually horrible JPGs, so the extracted colormap will always have a curl at the ends.
names = {'flir1','flir2','dias1'};
m = 64; % block height
n = 256; % block width (CT length)
A = repmat(1:n,m,1); % basis
% generate test sweeps
nf = numel(names);
outpict = zeros(m,n,3,nf);
for f = 1:nf
outpict(:,:,:,f) = ind2rgb(A,flirmap(names{f},n));
end
outpict = imtile(outpict,[nf 1]);
imshow(outpict)
I know there are other maps used by both vendors, but these are the only ones for which I had enough examples to work from.

Sign in to comment.

Categories

Find more on Images in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!