Background color correction of a rgb picture
16 views (last 30 days)
Show older comments
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
0 Comments
Answers (5)
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
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)
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:
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
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
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.
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
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.
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!