How to normalize two images which have different lighting conditions?

33 visualizzazioni (ultimi 30 giorni)
how to normalize two images with different lighting conditions

Risposta accettata

Geoff
Geoff il 12 Apr 2012
Histogram normalisation can work quite well in some cases.
First, you take a histogram of your reference image (where each bucket is a count of pixel value). For colour, you can do one histogram per channel.
Now, for successive images, you are going to try to match their histograms to your reference.
Let's say your reference histogram is an array R, which is 256-elements long (one for each intensity 0..255), and your new frame's histogram is H.
If you plot these two profiles, you'll possibly see they have a different shape. Here's a contrived example using two completely different scenes from your MatLab demos folder...
Rim = importdata('street1.jpg');
Him = importdata('street2.jpg');
R = histc( reshape(Rim, size(Rim,1)*size(Rim,2), []), 0:255 );
H = histc( reshape(Him, size(Him,1)*size(Him,2), []), 0:255 );
clf;
subplot(2,1,1); plot(R);
subplot(2,1,2); plot(H);
What you want to do is remap your pixel intensities so that they roughly fill the buckets in the same distribution as the reference. Think of having the cumulative sum of intensities at any point in H being the same as the cumulative sum of intensities at some other point in R. You want to find how we map an intensity in H to R.
I suppose in MatLab this is pretty easy. There might even be a MatLab function for it, but I don't know one so here goes.
Rc = cumsum(R);
Hc = cumsum(H);
Now, for each index h into Hc, your remapped pixel value is the index r at which Rc first exceeds Hc(h). MatLab can do this in a couple of lines:
Hmap = arrayfun( @(val) find(Rc >= val, 1), Hc );
Hadj = uint8(Hmap(Him(:,:,1)+1)-1);
Compute the histogram for Hadj to confirm that it lines up with Rim.
As for a version of this that can do all channels at the same time, maybe that's a fun exercise, but I don't see a problem with keeping it conceptually simple:
function [Hadj] = HistNorm( Rim, Him, chan )
if nargin > 2
R = histc(reshape(Rim(:,:,chan),1,[]), 0:255);
H = histc(reshape(Him(:,:,chan),1,[]), 0:255);
Rc = cumsum(R);
Hc = cumsum(H);
Hmap = arrayfun( @(val) find(Rc >= val, 1), Hc );
Hadj = uint8(Hmap(Him(:,:,chan)+1)-1);
else
Hadj = uint8(zeros(size(Him)));
for c = 1:3
Hadj(:,:,c) = HistNorm( Rim, Him, c );
end
end
end
Usage:
Hadj = HistNorm(Rim,Him);
image(Hadj);
With my example images, this gives a lot of rubbishy colour artifacts, but that's because the scenes are totally different. You'll see why if you plot the histogram of Hadj using my first section of code. If you have a scene that doesn't tend to change much, this approach works okay. What I've described is really simplistic. You can get smoother results if you choose the nearest bucket to each cumulative sum.
But the benefit of simplicity is it's fast. I used this approach to do automatic irising and gain control on four cameras running at 230fps with no measurable performance hit.
Give it a go. Geez, I even gave you the code =)

Più risposte (1)

Giorgio
Giorgio il 31 Ago 2015
Great answer! Ty.

Community Treasure Hunt

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

Start Hunting!

Translated by