How to draw keypoints onto input image using matlab? - image

This question is regarding SIFT features and its use in MATLAB. I have some data containing the following information:
The x,y co-ordinates of each feature point
The scale at each feature point
The orientation at each feature point
The descriptor vector for each feature point. Each vector has 128 components.
I'm having a problem with drawing the keypoints onto the corresponding input image. Does anyone have an idea of how to do this? Are there any built-in functions I can use?
Thanks a lot.

If you just want to display the points themselves, read in the x and y co-ordinates into separate arrays, then display the image, use the hold on command, then plot the points. This will overlay your points on top of the image.
Assuming you have these co-ordinates already available and stored as x and y, and assuming you have your image available and stored as im, you can do this:
imshow(im);
hold on;
plot(x, y, 'b.');
Keep in mind that the x co-ordinates are horizontal and increase from the left to right. The y co-ordinates are vertical and increase from top to bottom. The origin of the co-ordinates is at the top left corner, and is at (1,1).
However, if you want to display the detection window, the size of it and the orientation of the descriptor, then suggest you take a look at the VLFeat library as it has a nice function to do that for you.
Suggestion by Rafael Monteiro (See comment below)
You can also modify each point so that it reflects the scale that it was detected at. If you want to do it this way, assume you have saved the scales as another array called scales. After, try doing the following:
imshow(im);
hold on;
for i = 1 : length(x)
plot(x(i), y(i), 'b.', 'MarkerSize', 10*scales(i));
end
The constant factor of 10 is pretty arbitrary. I'm not sure how many scales you have used to detect the keypoints and so if the scale is at 1.0, then this would display the keypoint at the default size when plotting. Play around with the number until you get results that you're comfortable with. However, if scale doesn't matter for you, the first method is fine.

Related

Labeling plots with images in Matlab

Is there any way of labeling plots with images. For example, when I use the following:
plot(Y(:,1),Y(:,2),'o','LineWidth',2);
gname(names)
I can label each dot in a plot with a name. Is there any way to insert images instead of names?
It is possible, but not as convenient as gname by far. You can use the low-level version of image to insert images in your plot at arbitrary positions. Here's a simple example which puts the "Mandrill" image that comes with Matlab with its upper left corner pixel at the position (pi/2, 0):
% example plot
x = linspace(0, 2*pi, 100);
plot(x, cos(x))
% insert image
load mandrill
colormap(map)
image('CData', X, 'XData', [pi/2, pi/2 + 0.5], 'YData', [0, -0.3])
The result looks like this:
Problems with this approach:
There is no interactive point-and-click facility, you have to explicitly insert and position the image labels programmatically, or program such a point-and-click facility yourself. ginput might help doing so.
A figure window can only have one associated color map. That means if you have different images, they either all have to use the same colormap or have to be truecolor images.
Not just the position, but also the display size of the image has to be specified in the call to image, and both are by default specified with respect to the plot's coordinate system. This makes it hard to achieve the correct aspect ratio. You can switch (temporarily) to absolute units using the axes property 'Units' , but then you have to figure out the correct position in e.g. absolute millimeters or inches. Moreover, images are usually indexed with vertical coordinates increasing from top to bottom, while plots usually have vertical coordinates increasing from bottom to top. This is the reason for the negative value -0.3 in the 'YData' property above.
Alternatively, you can insert images each in their own little axes sitting on top of the plot's axes, which makes it easy to get the right orientation and aspect ratio using axis image. You'll still have the problem though to figure out the correct position for the axes.

Map image/texture to a predefined uneven surface (t-shirt with folds, mug, etc.)

Basically I was trying to achieve this: impose an arbitrary image to a pre-defined uneven surface. (See examples below).
-->
I do not have a lot of experience with image processing or 3D algorithms, so here is the best method I can think of so far:
Predefine a set of coordinates (say if we have a 10x10 grid, we have 100 coordinates that starts with (0,0), (0,10), (0,20), ... etc. There will be 9x9 = 81 grids.
Record the transformations for each individual coordinate on the t-shirt image e.g. (0,0) becomes (51,31), (0, 10) becomes (51, 35), etc.
Triangulate the original image into 81x2=162 triangles (with 2 triangles for each grid). Transform each triangle of the image based on the coordinate transformations obtained in Step 2 and draw it on the t-shirt image.
Problems/questions I have:
I don't know how to smooth out each triangle so that the image on t-shirt does not look ragged.
Is there a better way to do it? I want to make sure I'm not reinventing the wheels here before I proceed with an implementation.
Thanks!
This is called digital image warping. There was a popular graphics text on it in the 1990s (probably from somebody's thesis). You can also find an article on it from Dr. Dobb's Journal.
Your process is essentially correct. If you work pixel by pixel, rather than trying to use triangles, you'll avoid some of the problems you're facing. Scan across the pixels in target bitmap, and apply the local transformation based on the cell you're in to determine the coordinate of the corresponding pixel in the source bitmap. Copy that pixel over.
For a smoother result, you do your coordinate transformations in floating point and interpolate the pixel values from the source image using something like bilinear interpolation.
It's not really a solution for the problem, it's just a workaround :
If you have the 3D model that represents the T-Shirt.
you can use directX\OpenGL and put your image as a texture of the t-shirt.
Then you can ask it to render the picture you want from any point of view.

Display 3D volume from an array of images in OpenGL

I have a question about displaying a 3D volume made from an array of 2D grayscale images using OpenGL.
To be more precise, I only want to display the central slices of the volume in x, y and z directions.
I have successfully done this just by looping through the volume data at the coordinates I want to show and painting them using GL_POINTS, as shown here (displaying the z direction central slice):
for (x=0; x<sizeX; x++){
for (y=0; y<sizeY; y++){
color=volume(x,y,0)
glBegin(GL_POINTS);
glColor3f(color,color,color);
glVertex3f(x,y,0);
glEnd();
}
}
I know the real world dimensions of the voxels in mm so I was thinking of displaying the voxels as cubes with that dimensions instead of GL_POINTS like I'm doing it now. Is this a good way to do this? I have read somewhere that displaying voxels as cubes generally isn't a good idea.
Just to add, the volume consists of around 300 images with dimensions of 400x350px.
If your application is to display slices of dense volumetric data, I don't see the benifit of using either points or voxels. To me the best way to achieve what you are asking for is to use simple planes, that you texture map with your image data. You mention the dimensions of your grid data, if you want to visualize this fact, you could also use boxes instead of planes. Using texture maps should be far more efficient for your purpose compared to glPoint or using boxes to represent each individual voxel.
There are many Tutorials on the web which tell you how to do that (e.g. NeHe).

OpenGL custom navigation/selection

I have a situation that I'm not realy sure how I can handle. I have an openGl object of about 20k vertices, and I need to offer the user the possibility to select any one of these vertices (let's say with a smallest margin of error possible). Now here is what I want to do in order to do this:
Next to the 3D canvas of the object, I also offer the user 3 'slices' done by the planes x=0; y=0 and z=0. Say for the simplest example for a sphere these would be 3 circles, correponding to 'cutting' out one of the dimensions. Now let's take the z=0 one for the purpose of the example. When the user clicks on a point say (x_circle, y_circle) i would like to get the actual point in the 3d representation where he clicked. The z would be 0 of course but I can't figure out a way to get the x and y. I can easily translate that (x_circle, y_circle) -> (x_screen, y_screen) which would have the same result as a click on the canvas at those coordinates, but I need to find a way to translate that into the (x, y, 0) coordinate in 3D view.
The same thing would need to be done with x=0, y=0 but I think if I can understand/implement a way for z=0 I can just apply more or less the same solution with an added rotation over something. If anyone can help with any examples/code or even math behind this it would help a lot because at the moment I'm not really sure how to proceed.
When the user clicks, you can render the vertices using GL.POINTS (with a certain size, if you like) to an off-screen buffer using a shader that renders each vertex' index into RGBA. Then you read back the pixel on the mouse position and see what index it is.

Display image at desired scale across subplot axes

Is it possible to display an image in multiple subplot axes, such that the image appears at the desired scale?
subplot(3,3,[1 4 7]);
%# image scaled down to fit 1 set of axes
imshow(img);
subplot(3,3,2);
plot(relevantData);
%# And so on with 5 other plots
I want to have the image scaled to either a fixed size or to fit the axes available to it, rather than to the size of a single axes.
My use case is to show a video alongside plots derived from the video, such that the plots are progressively drawn in step with the video. Once the display is correct I can save each image and combine them into a video.
Clarification
I am asking if it is possible to produce a figure as described without specifying the position of every element in absolute terms. Though one can make arbitrary figures that way (and in fact I have done so for this project), it is very tedious.
Edit:
For changing the size of the subplot:
In help subplot they mention that you can set parameters on the selected "axes" (that's what they call a plotting area in Matlab).
Using that, you can set the 'position', as seen in help axes. This property takes takes as argument:
[left, bottom, width, height]
As pointed out by #reve_etrange, one should use absolute positioning for axes 'Position'and 'OuterPosition' parameters. they can be in normalized coordinates, though.
For changing the size of the image in the subplot:
I think there are 2 useful things for you in the help imshow output:
'InitialMagnification': setting the magnification of the image.
'Parent': determines which parent imshow will use to put the image in (never tried using imshow with subplots).

Resources