We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Grid displacement with gray level map
Page Index Toggle Pages: 1
Grid displacement with gray level map (Read 1804 times)
Grid displacement with gray level map
Jun 8th, 2008, 10:52pm
 
Hi programmers; some help with code is appreciated here!

Though PhiLho gave me very nice suggestions in my post about how to make a caricature of an image, I'm still struggling with this part of my project. I heard about displacement map filters and tried to find examples of code, but I'm afraid I need help here.

This is the idea: there's a jpg image of which some areas are enlarged according to points in an array. The enlarged areas have smooth transitions with the areas which are not enlarged (like in a caricature). I think the program would be something like this (but correct me if I'm wrong):

Part 1
An x and y coordinate are taken from an array; a 2D point.
Part 2
A displacement map is created according to these points. For example: a light gray area around each point. Gradations of darker gray on the edges give a smooth transition towards the black background. If points overlap, the area gets lighter; white is the maximum. So the image will become more enlarged if there are more points there.
Part 3
The original image is distorted according to the displacement map. The image is most enlarged in the light areas of the map. The darker the displacement map is, the less that part of the image is enlarged (zero at black).

Is there a smarter way or could the program work like this? As I don't have much experience with programming, I really appreciate if you could help me with the code.
Re: Displacement map filter code
Reply #1 - Jun 9th, 2008, 1:24am
 
Hi ksam,

I'm a little confused. A displacement map is an image (usually greyscale) that contains information about how much to displace (raise and lower) the height of a vertex in a grid. Making a 3D shape. A white pixel raises the vertex position up and a dark pixel lowers the vertex down. This can also be called heightmaps http://en.wikipedia.org/wiki/Heightmap

Or are you looking for a way to take a 2D grid of points and pull them towards certain pixels in a target image? Like the Photoshop liquify filter?
Re: Displacement map filter code
Reply #2 - Jun 9th, 2008, 11:11am
 
Hi MattD(polymonkey),

I understand your confusion. I confess that I don't have much experience with these filters, but I heard about them and I found this website:

http://www.codeproject.com/KB/GDI-plus/displacementfilters.aspx

Here 'displacement filters' are used for image processing, which is basically what I wish to do. The effect is probably best comparable to the 'sphere' on the website, but then applied locally. You can download code from that website, but it's C# and I don't really know how I should apply it in Processing. Moreover, I search for a smooth transition between the enlarged area and not enlarged parts. I don't know if a sphere would be the best option.

I guess 'displacement filters' are sometimes used for image processing. Is it smart to generate a map before distorting the image at once or is it better to enlarge areas one by one without the map? As I was thinking about this map, I named the idea 'displacement map filter', but maybe it's confusing. Perhaps you know a better name for it? But more important: could anyone help me with the code? Should I forget about the map and just use a displacement filter?
Re: Displacement map filter code
Reply #3 - Jun 9th, 2008, 7:06pm
 
If I understand correctly your project, your applet will display an image, eg. a portrait, and the user will move the mouse around. The applet is static until a click or a key hit. Then the positions where the mouse have been will be used to distort the picture. Right?
Somehow, it reminds me an experiment I have read upon: researchers recorded eye movement of a user reading a Web page. Then they highlighted the parts of the page where the eye spent the most time.
Should you replace your mouse input by such eye recording device (hard to find, I reckon...), it would be very interesting...

Anyway, your idea is interesting: instead of recording the mouse positions in an array, one can use the mouse movements in a non-displayed graphic. We could draw a circle at the current point, with size inversely proportional to current speed (distance since last point / time since last measure). The circle would be semi-transparent with a radial gradient (lighter at the center, and a stationary mouse would make the spot progressively lighter).
Thus we would have a map with gray levels.
Now, the idea of heightfields is interesting: instead of doing the hard math ourselves, perhaps we can ask OpenGL to do it: put the photo on a place (facing the camera), bump the plane according to the gray map (the lighter, the higher) and OpenGL would distort the image accordingly.
Now, you would need help from somewhere, because I have no idea how to do this bump map in OpenGL (I knew it with POV-Ray, but it is off topic... Wink).
Re: Displacement map filter code
Reply #4 - Jun 10th, 2008, 7:37pm
 
Hi PhiLho (and other programmers of course),

As an inexperienced programmer, I spend some hours today surfing for code and pondering on the idea how we could make this caricature idea working. Your ideas about the non-displayed image and the semi-transparent circles are great, but I’m afraid I don’t know anyone to help me with OpenGL. I tried to think of a way to get the effect with simple code (and little math!) instead of OpenGL. You were probably right about this: we can combine a gray level map with a grid.

About the project: do you know this ambiguous picture that seems to be a young woman if you look at it one way and an old woman if you look at it differently? For my project I will make ambiguous pictures, too, and do research about how people look at them. I think it’s a really funny project; I’m just struggling with this last part of the program!
Anyway, the user sees a blurred image. When the user drags the mouse, the image is sharp in a small square at the location of the mouse. I totally agree that eye-tracking would be very interesting. It may be an option for future research or in an art installation. But for now it’s also nice as a low-tech solution. For example: artists could put their work on their websites and see how visitors looked at it. Or it can be a simple tool for online marketing research where marketers want to know how people look at visual advertisements.
When the user releases the mouse, he/she sees an analysis of the path of the mouse. But after that comes the hard part: when ENTER is pressed, a caricature should appear. The parts where the user looked at (the mouse positions) should be enlarged while the image remains a nice picture as a whole.

Your idea about the non-displayed gray level map sounds great. We could indeed draw a light semi-transparent circle at the current point, with its size inversely proportional to the current speed. The circle would be bright in the middle and gradually fade in the black background. This way we would have a gray level map. I have an idea about how to transform the image, but I’m not sure how it will work out.

This idea is about a grid with x and y operations for each point done in a few for loops:
1)  Create a fine grid of squares connected to the texture, beginning at 0,0 and ending at width, height (1280, 800 in my case).
2)  Now we take each of the points of the grid except the first and last ones of the rows and columns (so the corners and edges of the image remain straight):
for (i = 1, i = (last of the points of the grid in a row - 1), i ++) {
for (j = 1, j = (last of the points of the grid in a column - 1), j ++) {
3)  We calculate the difference in grayscale value v:
Get the grayscale value at point i
Get the grayscale value at point (i+1)
v = grayscale value of point i - grayscale value of point (i + 1)
4)  The whiter an area is, the more attention is had and the more it should be magnified. So the point should move from the white areas towards the dark areas, making the white areas bigger.
If v = 0 then point i doesn’t move.
If v > 0 then point i is whiter than point (i + 1), so the point moves towards point (i + 1)
The x movement is positive: x-position point + (v * factor)
If v < 0 then point i is darker than point (i + 1), so the point moves from point (i + 1)
The x movement is negative (same formula with negative v): x-position point + (v * factor)
The factor should make sure the point moves a nice amount of pixels (never more than one square of the grid!), depending on v (the difference in gray level). Maybe it should be rounded.
5)  If this goes right, the points are moved in x-positions according to the gray levels of the map. Now we apply the same method for the y-positions, so steps 2 to 4 are repeated for y.
Some boundaries:
If x < 0, x = 0
If x > width (1280), x = width
If y < 0, x = 0
If y > height (800), x = height

Note 1:
With this method the points never move too far at once depending on the size of the squares of the grid. But if the process is repeated a couple of times, the points will move further and the caricature will be extremer, because every time a point is moved, it may get a new grayscale value. Maybe it’s nice to make the displacement extremer every time you hit a certain key (nice toy).

Note 2:
The gray level map would not be a bump map, but a map for gray level difference. If we want a certain area to be greatly enlarged, the middle should be quite white, quickly becoming darker around it. Where there should be a smooth transition between enlarged image and normal size, we could make a slower transition between darker gray and black. Your idea of the light semi-transparent circle would do fine here, if we make the middle bright with first a quick transition towards darker and then a slower transition (a little like an S-curve with a small top; should this be programmed or would an image be more convenient as a ‘stamp’?).

Do you think this is an option? It leaves out OpenGL and could give a nice effect (that is; if I’m right, which I can’t guarantee…). I can have this idea for code, but I know it’s quite something else to have it well implemented in Processing. Do you think you would be able to program this grayscale map and grid transformations?
Re: Displacement map filter code
Reply #5 - Jun 11th, 2008, 4:01pm
 
Thinking more about this project... No real coding yet. Cheesy

To build the gray map, one can use a method similar to those used in Photoshop or Gimp: create a bitmap showing a radial gradient, both on brightness (white on center, black on diameter) and on transparency (opaque on center, transparent on black). Then on each mouse position (perhaps with interpolation to avoid stippling) draw this bitmap. On a second step, one can manage 3 or 5 (or more) sizes of brushes: the faster the mouse go, the smaller the bitmap will be taken. It is probably faster than computing this gradient on each step. Now, the bitmaps can be loaded or recomputed on each sketch start.

Now the difficulty is to use this map to distort the photo.
A possible algorithm I imagined is to scan the surface: for each pixel, look at it and its eight neighbors. Sum up the gray level of all the pixels, and compute the target pixel as follow: for each color component, do a ponderated sum of all the pixels, ie. sum(gray_level_of_mask[i] * color_component_value[i] / total_gray_level)
Thus, the brighter the pixel, the more prominent it is in the pixel, it might result (or not!) in a magnifying effect.
A possible improvement is to change the range depending on the total gray level: if black, just copy the local pixel. If dark, take 8 neighbors (or perhaps even fraction of pixels! eg. cutting out by a circle around the target pixel). If medium, take 24 neighbors. Etc.
I haven't tried yet so it might be a dead end. I am not a specialist of filters...
Re: Displacement map filter code
Reply #6 - Jun 11th, 2008, 6:19pm
 
Hi PhiLho,

I think your idea to create this gay level map with various brush sizes and interpolation is smart. I admit I wouldn’t find it easy to program it, but it sounds logical.

I think I found a way to get the effect I wanted to achieve with image distortion. I work with quads of textures and vertices. Okay, it's inefficient but al least affective!

beginShape();  
texture(a);
vertex(0, 0, v1, 0, 0);    
vertex(200, 0, v2, 400, 0);  
vertex(200, 200, v3, 400, 400);    
vertex(0, 200, v4, 0, 400);  
endShape();

with v the values of heightmap with different levels of gray. So it's the idea with 3D vertices in OpenGL after all!

I'm still working on the height map you wrote about, but there's some progress finally...

Thank you so much for your advice in my posts!
Page Index Toggle Pages: 1