views:

474

answers:

3

alt text

One can use Google's logo for a try:

alt text

BTW, what's the term for it?

+1  A: 

I think you are referring to the fisheye lens effect. Here is some code for imitating fisheye in matlab.

Greg Bray
+6  A: 

I believe this is typically referred to as either a "fisheye lens" effect or a "barrel transformation". Here are two links to demos that I found:

Example

In this example, I started with the function radial.m from the first link above and modified the way it relates points between the input and output spaces to create a nice circular image. The new function fisheye_inverse is given below, and it should be placed in a folder on your MATLAB path so you can use it later in this example:

function U = fisheye_inverse(X,T)

  imageSize = T.tdata(1:2);
  exponent = T.tdata(3);
  origin = (imageSize+1)./2;
  scale = imageSize./2;

  x = (X(:,1)-origin(1))/scale(1);
  y = (X(:,2)-origin(2))/scale(2);
  R = sqrt(x.^2+y.^2);
  theta = atan2(y,x);

  cornerScale = min(abs(1./sin(theta)),abs(1./cos(theta)));
  cornerScale(R < 1) = 1;
  R = cornerScale.*R.^exponent;

  x = scale(1).*R.*cos(theta)+origin(1);
  y = scale(2).*R.*sin(theta)+origin(2);
  U = [x y];

end

The fisheye distortion looks best when applied to square images, so you will want to make your images square by either cropping them or padding them with some color. Since the transformation of the image will not look right for indexed images, you will also want to convert any indexed images to RGB images using IND2RGB. Grayscale or binary images will also work fine. Here's how to do this for your sample Google logo:

[X,map] = imread('logo1w.png');  %# Read the indexed image
rgbImage = ind2rgb(X,map);       %# Convert to an RGB image
[r,c,d] = size(rgbImage);        %# Get the image dimensions
nPad = (c-r)/2;                  %# The number of padding rows
rgbImage = cat(1,ones(nPad,c,3),rgbImage,ones(nPad,c,3));  %# Pad with white

Now we can create the transform with MAKETFORM and apply it with IMTRANSFORM:

options = [c c 3];  %# An array containing the columns, rows, and exponent
tf = maketform('custom',2,2,[],...    %# Make the transformation structure
               @fisheye_inverse,options);
newImage = imtransform(rgbImage,tf);  %# Transform the image
imshow(newImage);                     %# Display the image

And here's the image you should see:

alt text

You can adjust the degree of distortion by changing the third value in the options array, which is the exponential power used in the radial deformation of the image points.

gnovice
Where should I place those `.m` files in order for it to work?
You put the files into any folder that is on the Matlab path. For example, when you start Matlab, type 'pwd' and hit return. The path shown is where you can put the files.
Jonas
Oh it works,but the corner is not so round,how to tune the parameters to get similar effect in my post?
It's not working with true color images like the google logo in my post.
Hi gnovice,how to make the code work for all kinda images?Based on your previous answer,the only case that's not covered yet is how to transform a grayscale or binary image?
How to adjust the parameters so that the image can fit into a circular frame like @upperBound's solution?Though @upperBound's transform will damage the quality..
I tried `options = [c/2 r/2 max(r,c)/2 1 1 1 1 1]; ` and `options = [c/2 r/2 max(r,c)/2 11 1 1 1 1]; `,both give:`Warning: FINDBOUNDS: Search procedure failed; returning OUTBOUNDS = INBOUNDS.`
@user198729: I updated my example. I think it addresses most of the concerns you raised in the comments.
gnovice
Seems there is something wrong with the padding,it's not working here,I'll post how it looks like in my question update.
@user198729: I found the typo. The `options` array should be `[c c 3]`, since the array has been padded to be square.
gnovice
Very impressive!But how to automate the padding for arbitary images?I'll accept this one and post a new question though:)
A: 

Just for the record:

This effect is a type of radial distortion called "barrel distortion".

For more information please see:

http: //en.wikipedia.org/wiki/Distortion_(optics)

Here is a different method to apply an effect similar to barrel distortion using texture mapping (adapted from MATLAB Documentation):

[I,map] = imread('logo.gif');
[h,w] = size(I);

sphere; 

hS = findobj('Type','surface');

hemisphere = [ones(h,w),I,ones(h,w)];

set(hS,'CData',flipud(hemisphere),...
    'FaceColor','texturemap',...
    'EdgeColor','none')

colormap(map)
colordef black
axis equal
grid off
set(gca,'xtick',[],'ztick',[],'ytick',[],'box','on')
view([90 0])

This will give you the circular frame you are looking for but the aliasing artifacts might be too much to deal with.

upperBound
The circular frame is very nice,but the image is blured,how to overcome this?
You may try to increase the image size or use a high resolution image to start with. It will also depend on how your graphics stack handles such mappings. On a positive side, you may map an image on an arbitrary surface and get "carnival mirror" effects...
upperBound
Can you update the code with the `carnival mirror` you mentioned?