# How can I create a glass distortion effect in an image?

I'd like to overlay a glass jar onto an image with realistic light bending. Can anyone think of a way to automate this effect (perhaps this can be done with the raytracing package rayica)?

-
A similar question. –  Ｊ. Ｍ. Aug 15 '12 at 17:39
@J.M. - Seems completely different to me. That one is about a partial enlargement, this one about refraction. –  stevenvh Aug 15 '12 at 17:47
If you're looking for ray tracing solutions, then there isn't really much to be said for Mathematica here. I would use Blender instead. –  Jens Aug 15 '12 at 18:48
Ok, then can some simpler distorting function be used? –  M.R. Aug 15 '12 at 18:49

================= UPDATE ======================

Due to @halirutan comment I'll add a note on realism. First of all pure water and clouds are not the best subject to simulate reflecations because they have fractal structure - meaning they tend to appear the same on different magnification scales. So it is hard to give impression to a human eye of refraction effect.

I suggest introducing some non-fractal elements, like the one below. Also @halirutan is right slight offset of horizon line from vertical my enhance effect perception. This is the new app with vertical and horizontal scales added. Code is below the app. (I do not give URL for o variable - please find your own source.)

I also realized we can do magnifying or metaphorical effects like the one below:

o = ImageResize[Import[ (* use your own source *) ], 900];

j = ImageResize[Import["http://i.stack.imgur.com/2KISh.jpg"], 500];

Manipulate[i1 = ImageMultiply[ImageResize[#, {h, v} ImageDimensions[#]] &@o,
mask = Blur[Binarize[ImageMultiply[i1, RegionBinarize[j, {{10, 10}}, 0.1]], .0], 4];
, {{g, 3, "jar opacity"}, .1, 10}
, {{h, .85, "horizontal refraction"}, .5, 1.5}
, {{v, .9, "vertical refraction"}, .875, 1.5}
, {{b, 7, "background blur"}, 0, 10}, FrameMargins -> 0,
SynchronousUpdating -> False]


================= ORIGINAL POST ======================

Some public ocean image and your jar:

o = ImageResize[Import["http://upload.wikimedia.org/wikipedia/commons/e/e0/Clouds_\
over_the_Atlantic_Ocean.jpg"], 900];

j = ImageResize[Import["http://i.stack.imgur.com/2KISh.jpg"], 500];


Now this line does:

• Compression image re-sizing to simulate refraction effect
• Gamma correction of jar to change its opacity
• ImageMultiply for nice overlaying of images

Here you go:

i1=ImageMultiply[ImageResize[#, {.5, 1} ImageDimensions[#]] &@o,ImageAdjust[j, {0, 0, 5}]]


mask = Blur[Binarize[ImageMultiply[i1, RegionBinarize[j, {{10, 10}}, 0.1]], .0], 3]


Blur original image and use mask to cut a hole. Then use mask to create filler for the hole:

{Blur[ImageMultiply[o, mask], 5], ImageMultiply[i1, ColorNegate@mask]}


Finally fill the hole with ImageAdd and make an app:

Manipulate[i1 = ImageMultiply[ImageResize[#, {r, 1} ImageDimensions[#]] &@o,
mask = Blur[Binarize[ImageMultiply[i1, RegionBinarize[j, {{10, 10}}, 0.1]], .0], 4];
, {{g, 3, "jar opacity"}, .1, 10}
, {{r, .6, "refraction"}, .5, 1.5}
, {{b, 7, "background blur"}, 0, 10}, FrameMargins -> 0]


Your given glass jar image has slight shadow against white background which is a usual thing that Photoshop artists add. A photo without the shadow would blend with ocean background better. There is also another Blur function for the mask that you can control to blend to your taste.

-
+Masterful Lesson in image processing. Thanks. –  David Carraher Aug 16 '12 at 11:05
+1 I think it's better to scale in both direction so that the horizon-line is shifted. This gives in my opinion a more realistic refraction fake. See here –  halirutan Aug 16 '12 at 12:03
@halirutan good point. I updated the post. –  Vitaliy Kaurov Aug 16 '12 at 16:25
In case someone wants the original image: wallpaperswide.com/bungalows_on_the_ocean-wallpapers.html –  rm -rf Aug 16 '12 at 17:39
@DavidCarraher Thank you David ;-) –  Vitaliy Kaurov Aug 17 '12 at 5:41

This is more of an add-on to Vitaliy's excellent answer, than a completely new approach. I wanted to try to simulate some of the image distortion that would be seen at the jar walls. A simple (though utterly wrong in a physics sense) way to do this is to make the demagnification vary according to the jar image intensity.

Load a picture and the jar image, and pad the jar image to match the picture size.

image = Import["sunset.jpg"];
jar = ImageResize[Import["2KISh.jpg"], 750];
jar = ImageCrop[jar, ImageDimensions@image, Padding -> White];


For the fake refraction, I use a grayscale copy of the jar with a gamma adjustment (this amplifies the effect). ImageTransformation is used to create the effect, which is a simple magnification whose amplitude is obtained from the ImageValue of jar2. The variable p determines the centre of magnification, in this case it is at the image centre since that is where the jar is.

jar2 = ImageAdjust[ColorConvert[jar, "Grayscale"], {0, 0, 2}];
p = Round[ImageDimensions[image]/2];
refract = ImageTransformation[image, p + ImageValue[jar2, #] (# - p) &, DataRange -> Full];
refract = ImageMultiply[refract, jar];


To combine the refraction effect with the original image I use Vitaliy's mask as an alpha channel to remove everything outside the jar. The final image is then made using ImageCompose.

mask = ColorNegate@Blur[RegionBinarize[jar, {{10, 10}}, 0.05]];