# How can I remove shadows from an image?

I have this image

I would like to remove the shadow from the image. I know a lot of different methods like certain morphological operations have been used to remove shadows:

I have created this mask for the same image

Are there some other methods I could try using this mask that I have created?

EDIT:

input image and mask of same size as requested :

EDIT 2: i generated a 1D invariant image however its not perfect

  I = imread('shadow.jpg');
J = im2double(I);

R = J(:,:,1);
G = J(:,:,2);
B = J(:,:,3);

[len,wid] = size(R);

% Generation of 2-D Log Chromaticity Image.
for i = 1:len
for j = 1:wid
if ((R(i,j)*G(i,j)*B(i,j))~= 0)
c1(i,j) = R(i,j)/((R(i,j)*G(i,j)*B(i,j))^(1/3));
c2(i,j) = G(i,j)/((R(i,j)*G(i,j)*B(i,j))^(1/3));
c3(i,j) = B(i,j)/((R(i,j)*G(i,j)*B(i,j))^(1/3));
else
c1(i,j) = 1;
c2(i,j) = 1;
c3(i,j) = 1;
end
end
end

rho1 = mat2gray(log(c1));
rho2 = mat2gray(log(c2));
rho3 = mat2gray(log(c3));

X1 = mat2gray(rho1*1/(sqrt(2)) - rho2*1/(sqrt(2)));                                         %(1/sqrt(2); -1/sqrt(2); 0)
X2 = mat2gray(rho1*1/(sqrt(6)) + rho2*1/(sqrt(6)) - rho3*2/(sqrt(6)));   %(1/sqrt(6); 1/sqrt(6); -2/sqrt(6))

theta = 120;

InvariantImage = cos(theta*pi/180)*X1 + sin(theta*pi/180)*X2;
imagesc(InvariantImage); colormap(gray)


Cannot understand what i am doing wrong out here please help?

-
Good question! Have you tried increasing brightness in the masked region? – Dima May 2 '12 at 20:47
Can you re-upload the mask without the frame and labels, at the same size as the source? – Emre May 2 '12 at 21:40
Check my answer here: dsp.stackexchange.com/questions/454/… – datageist May 3 '12 at 0:25
@Emre i have done as you requested – vini May 3 '12 at 12:16
@Dima yes i have tried doing that no success – vini May 3 '12 at 12:16

## 4 Answers

There are dozens of publications dealing with shadow-detection, generating shadow-masks, and indeed some that actually remove shadows - such as the ones mentioned in the previous posts. I could add some to the list, if needed. The problem, however, is IMHO far from being solved. For a quick-start, given a shadow-mask, I suggest (and have tried in the past) the two following approaches. They definitely reduce shadows - just not always seamless, and I'm sure there are publications (not by me) dealing with shadow-removal in similar ways.

• Gradient Domain Manipulation Techniques as described here (C and Matlab Codes provided): http://www.umiacs.umd.edu/~aagrawal/ICCV2007Course/index.html The gradient-integration approach can be used for a number of image-processing problems, see the slides/presentation for further examples.

The general idea:

1. Compute the spatial derivatives (gradient-images) for all color-channels.
2. Use the shadow-boundaries from the shadow-mask to generate a weight-mask that is close to zero on shadow-boundaries and increases to one within a specified neighborhood along the shadow-edge, i.e. orthogonal to a given edge-point.
3. Multiply the weight-mask from (2.) with all the gradient-images to reduce/damp the shadow-boundaries/edges.
4. Integrate the gradient-images using the code from the above link.
5. For RGB-images, from my experience, compute the average of the separate channels of the original images, and scale the integrated images to match these values to prevent "funny" color-artifacts.
• Brightness manipulation in the original image-domain.

1. Use the shadow-mask to generate a weight-mask that is one outside shadow regions, has a smooth transition (upwards) across the shadow-boundary and a larger than one scale-factor inside shadow-regions. As suggested in a previous post, the scale-factor can be estimated from the area immediately surrounding a shadow-area using the average-brightness together with the average-brightness of the shadow-region.
2. Multiply the original images (per channel) with the weight-mask, subject to clipping.

I have also tried using different color-models, e.g. HSV, that present luminance or brightness directly, which can then be modified independent of color (hue/saturation). This works essentially like the brightness-manipulation, i.e. generate a smooth weight-mask and multiply it with the luminance-channel. Maybe the two approaches, i.e. gradient-integration and brightness-manipulation, can be combined in a clever way, but someone has probably tried that before too.

Hope that helps, kind regards, Derik.

-
Brilliant that gives me so much insight.. I ll try it out – vini May 14 '12 at 5:36

I've seen this very image before. In fact here it is in the very paper on the topic of which you are looking to solve. Followed up with another paper from the same research group at Simon Fraser University. Both these will give you a good introduction to the problem of solving colour for lighting invariance.

-
yes i know that but was trying to try out a different method for the same problem – vini May 4 '12 at 9:58
@vini: If you've read that you should know what you are up against---simple morphological operations are not going to cut it. What else have you read and tried? I can suggest other papers if needed. – Emre May 4 '12 at 18:38
@Emre i am trying to change the brightness so that the effect of the shadow reduces however not much success .. Can an edge map be used to somehow mask this shadow out ..yes i figured that morphologcal operations woudn't help i tried imsubtract (matlab) to remove the shadow out – vini May 5 '12 at 6:26
@vini: This problem is beyond one-liner solutions. The linked papers (and there are others too) already solve the problem in most cases, so if you want to do something new you will have to find their weaknesses, and that means understanding them well, so I urge you to re-read them carefully. They usually mention problems in the Discussion and Conclusion sections. The log-chromaticity illumination-invariant projection approach seems most promising to me... – Emre May 5 '12 at 7:39
thanks @Emre yes i will study it carefully – vini May 5 '12 at 8:25

There are several methods that talk about Shadow detection essentially work against known background. There is no absolute notion of what is shadow just by looking at a pixel color. However, you need to identify shadow without reference.

While this problem is hard, here is a trivial solution - though readily this might not be the best one, but nevertheless it might help you gain some perspective.

Let's examine the image components in HSL domain

is Hue Component,
is Saturation Component, and is Lightness Component

It is well known that Lightness closely corresponds to the gray equivalent of the image and also that Shadow is essentially

a semi-transparent region in which the scene reﬂectance undergoes a local attenuation.

From here.

Hence, it is an overlay which decreases the reflectance said darkness you can identify the same in the gray part of the image - but you will find it's interplay much less in the color parts (Hue and in saturation to somewhat).

Now, here, i am able to produce two images - where

1. In this first image we have removed Lightness component (replaced with a fixed average value)

2. In the second image we have removed Saturation component in the same way

We can see that even if lightness is preserved but saturation is removed, the critical information about shadow is intact - where as when we removed lightness the shadow information is significantly dropped. Though this is not perfect, it makes a key feature that allows you to distinguish what is truly a shadow is from the background.

Based on this, you can treat the "Lightness removed" image as a background and other one as the incident image and segment the image based on this two information; So in the regions where shadow is not playing a major role, the difference could be much less, where as when shadow exists that segment will show high error.

Alternatively you can just apply independent segmentation (such as region growing) on both image. The saturation-removed image will have additional segment which won't exist in the lightness-removed image which is nothing but a shadow segment.

Note: You can you can distinguish HSL-lightness-removed image with original itself. Also try the similar things with HSV color space as well as YCbCr.

-
yes i will try that ..thanks so much – vini May 14 '12 at 5:33

You may take a histogram of the masked area (the shadow) and apply linear color transform so that the histogram of masked area and rest of the image is matched.

I suppose that scale factor in the transform would be negligible, only shifing of the brightness would be necessary, so you may just take average brightness of the two segments (shadow, sorroundings) and apply the difference.

-
could you please provide images for the same cause i donot have practical knowledge of what you have suggested – vini May 3 '12 at 18:16
Sorry I have little spare time to assist more on that. – Libor May 4 '12 at 8:06
alrite il try out what you suggested =) – vini May 4 '12 at 10:00