I wanted to do Color correction in an image such that the image appears to be taken under a white light source..... please could someone help me......

 Respuesta aceptada

Image Analyst
Image Analyst el 11 de En. de 2013

2 votos

One of the best ways is to take a photo of the X-rite ColorChecker chart. Then use a polynomial regression to fit each color channel to the desired colors, sch as the sRGB values of the color checker chart.
An alternative ad-hoc way is to locate the bright region of your image, and assume that should be white (red=green=blue), then linearly scale each color channel so that the gray level of the brightest pixels end up all the same (say they all = the mean of the 3 color channels in the bright portion). This is by far the easiest (but worst) way to color correct.
Of course there are more sophisticated ways, but I don't know how fancy you want to get.

6 comentarios

Elysi Cochin
Elysi Cochin el 11 de En. de 2013
sir, could u please show me an example of the way u suggested??
Image Analyst
Image Analyst el 11 de En. de 2013
OK. You asked for it: (Save as crude_white_balancing.m)
% Does a crude white balancing by linearly scaling each color channel.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables.
workspace; % Make sure the workspace panel is showing.
format longg;
format compact;
fontSize = 15;
% Read in a standard MATLAB gray scale demo image.
folder = fullfile(matlabroot, '\toolbox\images\imdemos');
button = menu('Use which demo image?', 'onion', 'Kids');
% Assign the proper filename.
if button == 1
baseFileName = 'onion.png';
elseif button == 2
baseFileName = 'kids.tif';
end
% Read in a standard MATLAB color demo image.
folder = fullfile(matlabroot, '\toolbox\images\imdemos');
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% Didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
[rgbImage colorMap] = imread(fullFileName);
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows columns numberOfColorBands] = size(rgbImage);
% If it's an indexed image (such as Kids), turn it into an rgbImage;
if numberOfColorBands == 1
rgbImage = ind2rgb(rgbImage, colorMap); % Will be in the 0-1 range.
rgbImage = uint8(255*rgbImage); % Convert to the 0-255 range.
end
% Display the original color image full screen
imshow(rgbImage);
title('Double-click inside box to finish box', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition', [0 0 1 1]);
% Have user specify the area they want to define as neutral colored (white or gray).
promptMessage = sprintf('Drag out a box over the ROI you want to be neutral colored.\nDouble-click inside of it to finish it.');
titleBarCaption = 'Continue?';
button = questdlg(promptMessage, titleBarCaption, 'Draw', 'Cancel', 'Draw');
if strcmpi(button, 'Cancel')
return;
end
hBox = imrect;
roiPosition = wait(hBox); % Wait for user to double-click
roiPosition % Display in command window.
% Get box coordinates so we can crop a portion out of the full sized image.
xCoords = [roiPosition(1), roiPosition(1)+roiPosition(3), roiPosition(1)+roiPosition(3), roiPosition(1), roiPosition(1)];
yCoords = [roiPosition(2), roiPosition(2), roiPosition(2)+roiPosition(4), roiPosition(2)+roiPosition(4), roiPosition(2)];
croppingRectangle = roiPosition;
% Display (shrink) the original color image in the upper left.
subplot(2, 4, 1);
imshow(rgbImage);
title('Original Color Image', 'FontSize', fontSize);
% Crop out the ROI.
whitePortion = imcrop(rgbImage, croppingRectangle);
subplot(2, 4, 5);
imshow(whitePortion);
caption = sprintf('ROI.\nWe will Define this to be "White"');
title(caption, 'FontSize', fontSize);
% Extract the individual red, green, and blue color channels.
redChannel = whitePortion(:, :, 1);
greenChannel = whitePortion(:, :, 2);
blueChannel = whitePortion(:, :, 3);
% Display the color channels.
subplot(2, 4, 2);
imshow(redChannel);
title('Red Channel ROI', 'FontSize', fontSize);
subplot(2, 4, 3);
imshow(greenChannel);
title('Green Channel ROI', 'FontSize', fontSize);
subplot(2, 4, 4);
imshow(blueChannel);
title('Blue Channel ROI', 'FontSize', fontSize);
% Get the means of each color channel
meanR = mean2(redChannel);
meanG = mean2(greenChannel);
meanB = mean2(blueChannel);
% Let's compute and display the histograms.
[pixelCount grayLevels] = imhist(redChannel);
subplot(2, 4, 6);
bar(pixelCount);
grid on;
caption = sprintf('Histogram of original Red ROI.\nMean Red = %.1f', meanR);
title(caption, 'FontSize', fontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
% Let's compute and display the histograms.
[pixelCount grayLevels] = imhist(greenChannel);
subplot(2, 4, 7);
bar(pixelCount);
grid on;
caption = sprintf('Histogram of original Green ROI.\nMean Green = %.1f', meanR);
title(caption, 'FontSize', fontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
% Let's compute and display the histograms.
[pixelCount grayLevels] = imhist(blueChannel);
subplot(2, 4, 8);
bar(pixelCount);
grid on;
caption = sprintf('Histogram of original Blue ROI.\nMean Blue = %.1f', meanR);
title(caption, 'FontSize', fontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
% specify the desired mean.
desiredMean = mean([meanR, meanG, meanB])
message = sprintf('Red mean = %.1f\nGreen mean = %.1f\nBlue mean = %.1f\nWe will make all of these means %.1f',...
meanR, meanG, meanB, desiredMean);
uiwait(helpdlg(message));
% Linearly scale the image in the cropped ROI.
correctionFactorR = desiredMean / meanR;
correctionFactorG = desiredMean / meanG;
correctionFactorB = desiredMean / meanB;
redChannel = uint8(single(redChannel) * correctionFactorR);
greenChannel = uint8(single(greenChannel) * correctionFactorG);
blueChannel = uint8(single(blueChannel) * correctionFactorB);
% Recombine into an RGB image
% Recombine separate color channels into a single, true color RGB image.
correctedRgbImage = cat(3, redChannel, greenChannel, blueChannel);
figure;
% Display the original color image.
subplot(2, 4, 5);
imshow(correctedRgbImage);
title('Color-Corrected ROI', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Display the color channels.
subplot(2, 4, 2);
imshow(redChannel);
title('Corrected Red Channel ROI', 'FontSize', fontSize);
subplot(2, 4, 3);
imshow(greenChannel);
title('Corrected Green Channel ROI', 'FontSize', fontSize);
subplot(2, 4, 4);
imshow(blueChannel);
title('Corrected Blue Channel ROI', 'FontSize', fontSize);
% Let's compute and display the histograms of the corrected image.
[pixelCount grayLevels] = imhist(redChannel);
subplot(2, 4, 6);
bar(pixelCount);
grid on;
caption = sprintf('Histogram of Corrected Red ROI.\nMean Red = %.1f', meanR);
title(caption, 'FontSize', fontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
% Let's compute and display the histograms.
[pixelCount grayLevels] = imhist(greenChannel);
subplot(2, 4, 7);
bar(pixelCount);
grid on;
caption = sprintf('Histogram of Corrected Green ROI.\nMean Green = %.1f', meanR);
title(caption, 'FontSize', fontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
% Let's compute and display the histograms.
[pixelCount grayLevels] = imhist(blueChannel);
subplot(2, 4, 8);
bar(pixelCount);
grid on;
caption = sprintf('Histogram of Corrected Blue ROI.\nMean Blue = %.1f', meanR);
title(caption, 'FontSize', fontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
% Get the means of the corrected ROI for each color channel.
meanR = mean2(redChannel);
meanG = mean2(greenChannel);
meanB = mean2(blueChannel);
correctedMean = mean([meanR, meanG, meanB])
message = sprintf('Now, the\nCorrected Red mean = %.1f\nCorrected Green mean = %.1f\nCorrected Blue mean = %.1f\n(Differences are due to clipping.)\nWe now apply it to the whole image',...
meanR, meanG, meanB);
uiwait(helpdlg(message));
% Now correct the original image.
% Extract the individual red, green, and blue color channels.
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
% Linearly scale the full-sized color channel images
redChannelC = uint8(single(redChannel) * correctionFactorR);
greenChannelC = uint8(single(greenChannel) * correctionFactorG);
blueChannelC = uint8(single(blueChannel) * correctionFactorB);
% Recombine separate color channels into a single, true color RGB image.
correctedRGBImage = cat(3, redChannelC, greenChannelC, blueChannelC);
subplot(2, 4, 1);
imshow(correctedRGBImage);
title('Corrected Full-size Image', 'FontSize', fontSize);
message = sprintf('Done with the demo.\nPlease flicker between the two figures');
uiwait(helpdlg(message));
Jean-Marie Sainthillier
Jean-Marie Sainthillier el 18 de Dic. de 2013
Very interesting ! Some little errors with the means of each color channel (in the figure and after correction).
Image Analyst
Image Analyst el 18 de Dic. de 2013
I'm not sure what you mean by errors. What are the "true values"? The means will change from uncorrected to corrected because there is a color shift due to the white balancing procedure. Like I said, this is very crude and there are better methods that use combinations of the colors rather than doing each channel independently.
Walter Roberson
Walter Roberson el 12 de Sept. de 2016
Fu-An Nung comments,
Excuse me. May I ask you a question about color balance a video?
Walter Roberson
Walter Roberson el 12 de Sept. de 2016
Fu-An Nung, please open a new Question for that topic.

Iniciar sesión para comentar.

Más respuestas (2)

Jurgen
Jurgen el 11 de En. de 2013

0 votos

I guess we just have to assume you are using a normal rgb format... What image analyst suggested was to use your knowledge of the image to identify a pixel or area(group of pixels) that should be white/gray. Lets say these pixels have on average a ratio of 100:50:25 for red:green:blue. Then you correct by doubling the green intensities and quadrupling the blue intensities of all pixels.
Another way often used in cameras is histogram based. It adjusts the shape of the red, green & blue histograms to make them more similar. The downside is if your scene has alot of red for example it will look unnatural.
ALEXANDROS
ALEXANDROS el 14 de Oct. de 2013

0 votos

Dear image analyst, Some questions regarding the first method you propose with the X-rite ColorChecker chart. I have used the original rgb values given by the manufacturer for each of the 3 channels for all the 24 blocks in the colorchecker.
Then i took an image with my camera with the x-rite on the scene and in order to find how these 24 colors are changing for each channel.
then i used polynomial regression for each of the 3 channels seperatly to crate an input-output relationship between the real and the distorted values for each of the 3 channels.
Lastly i apply all these input-output relationships for all the image pixels.
the final result it's not seem correct. Am i doing something wrong?

1 comentario

Image Analyst
Image Analyst el 14 de Oct. de 2013
That's basically it. I don't know what's wrong without seeing the code or images. Perhaps you can start a new Question on this and we'll get it figured out. Probably not until much later today because I'm teaching a color science course all day today. Post your images and code in a new question and I'll look at it when I can.

Iniciar sesión para comentar.

Categorías

Más información sobre Image Processing Toolbox en Centro de ayuda y File Exchange.

Preguntada:

el 11 de En. de 2013

Comentada:

el 12 de Sept. de 2016

Community Treasure Hunt

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

Start Hunting!

Translated by