Getting pixel coordinates efficiently in Matlab - matlab

I would like to create a function in Matlab that, given an image, will allow one to select a pixel by clicking on it in the image and return the coordinates of the pixel. Ideally, one would be able to click on several pixels in the image in succession, and the function would store all the respective coordinates in a matrix. Is there a way to do this in Matlab?

ginput
Graphical input from mouse or cursor
Syntax
[x,y] = ginput(n)
[x,y] = ginput
[x,y,button] = ginput(...)
Description
[x,y] = ginput(n) enables you to
identify n points from the current
axes and returns their x- and
y-coordinates in the x and y column
vectors. Press the Return key to
terminate the input before entering n
points.

I think this is what you want:
A=imread('filename.jpg');
image(A)
[x,y]=ginput()

Related

Using streamslice/quiver and inpolygon crop

Suppose we have quiver field i.e. we have a meshgrid and then we assign a vector to each point. Is it possible to plot only the quiver field within some polygon?
So in the figure below, we want everything outside the triangle to be cropped out.
Ideally the code will also be helpful for the next step of having multiple such polygons and cropping out everything on their complement.
Some approaches:
A direct way is to figure out the meshgrid for the particular polygon and then assign a vector to each point. But that will take a lot of time to figure out as polygons get more complicated. In other words, the regular meshgrid is the square polygon, so we must modify the meshgrid matrix depending on our polygon. A friend informed me of a mesh generator matlab code.
Use inpolygon. The input of inpolygon are points in (x,y). But in our case we only have the vector field assigned to a meshgrid. One idea is to solve the ode system to obtain concrete solution pairs (x,y) to plug into the polygon. But solving them takes a lot longer and the pictures are not as nice.
Here's some sample code which I think will generate the kind of plot you want. It uses inpolygon to "filter" out the points inside the polygon. The vector field is still evaluated at the original meshgrid points. It easily extends to multiple polygons too.
clear
clc
x = linspace(0, 1, 21);
[X,Y] = meshgrid(x,x);
U = -Y; %some velocity field
V = X;
hold off
quiver(X,Y,U,V); %quiver on all points
polygon = [0.2,0.2;
0.7,0.5;
0.5,0.8]; %polygon vertices
ind = inpolygon(X,Y,polygon(:,1),polygon(:,2)); %get indices of points inside polygon
hold on
quiver(X(ind),Y(ind),U(ind),V(ind)); %quiver of points inside polygon

Matlab imline snapping

Is there a way to make the ends of a line created by imline snap to the nearest data point on a curve?
I'm trying to measure the slope between two points on a curve. The imline is great, but the ends of the line created by it do not snap to data points on a curve.
I'm wondering if I can drag the line around while both ends of the line remained on the curve.
It can be done using the 'PositionConstraintFcn' property of imline. Its value specifies a function handle that is called whenever the line is dragged using the mouse:
'PositionConstraintFcn': Function handle fcn that is called whenever the line is dragged using the mouse.
Whenever the object is moved because
of a mouse drag, the constraint function is called using
the syntax: constrained_position = fcn(new_position) where new_position is of the form [...]
The form of new_position is a 2x2 matrix, where each row is an endpoint of the line; and columns represent x and y respectively.
So all you have to do is specify a function that finds the closest point for each end and returns that constrained position. This can be done in two steps:
Create a function to do the actual job, using as inputs the new position (2x2 matrix) and the set of allowed positions (Nx2, where N represents the number of points of the curve). The output is a 2x2 matrix with the constrained position.
function constr_pos = imline_snap(new_pos, positions)
[~, ind1] = min(sum(bsxfun(#minus, new_pos(1,:), positions).^2, 2));
[~, ind2] = min(sum(bsxfun(#minus, new_pos(2,:), positions).^2, 2));
constr_pos = [positions(ind1,:); positions(ind2,:)];
Define this function in its own m-file (imline_snap.m) and place it where Matlab can find it, for example in the current folder.
Here's how it works. The function receives the two points selected by the mouse (new_pos) and the set of points defining the curve (positions). It computes the distance from the first mouse point to each point in the curve (sum(bsxfun(#minus, new_pos(1,:), positions).^2, 2)), and gets the index of the point in the curve with minimum distance (ind1). The same is done for the second point (giving the index ind2). Finally, those indices are used for selecting the appropriate curve points and building the ouput (constr_pos).
The above imline_snap function needs to be particularized with the allowed positions corresponding to the points of the curve. This is necessary because the PositionConstraintFcn must accept only one input, namely the first input of imline_snap. This can be done via an anonymous function (see the example below, line fcn = ...); whose handle is then passed to imline.
Example code:
h = plot(0:.01:1, (0:.01:1).^2); %// example curve. Get a handle to it
a = gca; %// handle to current axes
X = get(h,'XData'); %// x values of points from the curve
Y = get(h,'YData'); %// y values of points from the curve
fcn = #(pos) imline_snap(pos, [X(:) Y(:)]); %// particularize function using curve points
imline(a, 'PositionConstraintFcn', fcn) %// create imline with that PositionConstraintFcn
It should be noted that the code snaps to actual curve points. It doesn't for example interpolate between curve points. That could be done modifying the imline_snap function accordingly (but could result in sluggish movement if the number of operations is large).
Here's the above example at work (in Matlab R2010b). The righmost endpoint of the curve was dragged arbitrarily with the mouse, but it is seen to be snapped to the curve.
As a bonus, it would be easy to modify the function to display the slope in the figure title. Just add the following line at the end of the imline_snap function:
title(['Slope: ' num2str((constr_pos(2,2)-constr_pos(1,2))/(constr_pos(2,1)-constr_pos(1,1)))])
Example showing slope:

Select input pixel of image by mouseclick in Matlab

I am trying to implement a tracking program using the Mean-Shift algorithm in Matlab. The idea is that, given the first frame of one video, the user can click on top of any object he wants and the program will track it all through the video sequence. I have already implemented and working the tracking part, but I am having problems giving the user the possibility to click on top of the image to select the initial pixel for the tracking algorithm.
I have thought about input function, but I don't know how to make it work. How can I display an image and click on top of a pixel and get its coordinates [x,y] to initialize the program?
You could use ginput (Graphical input from mouse or cursor)
Read any image and show them using imread and imshow
h = imread('hestain.png'); % any input image
imshow(h);
Get the coordinates using ginput, where the input argument corresponds to the number of user clicks recorded.
[x,y] = ginput(1); % getting coordinates from user
To obtain the pixel value, we need to pass the coordinates as indices of the image. To do this, the output arguments from the ginput which are double by default, must be converted to unsigned integers.
Also, x and y represents horizontal and vertical by default. But matlab syntax takes first dimension as rows (number of horizontal lines calculated vertically). Hence y value is passed as first dimension. Similarly x value as second dimension.
pixelValue = h(uint8(y),uint8(x)); % using coordinates as indices

Matlab - Get (x,y) value of a plot by clicking on it

Matlab has the ginput for getting the (x,y) value of where you have clicked on the graph. However, say that I have plotted a graph with plot(t, sin(2*pi*t)). I want to be able to have the cursor move on the actual plot, and by clicking it, I get the (x,y) coordinate of my plot (in this case, the time and the value of sine).
Is this possible?
When the MATLAB figure is open, you can use the data cursor tool to help you traverse through the plot.
Here's a quick example:
t = 0 : 0.01 : 10;
plot(t, sin(t));
Here's what your plot looks like, and I have highlighted the option of where you can click for the data cursor tool.
Once you click on the data cursor option, click anywhere on the plot and it'll give you a data cursor tip. At that point you selected, it shows the x and y co-ordinate. In your case, x denotes time and y denotes amplitude.
Once you have a data cursor tip there, click on it (the black square) and drag it along the curve. You will see that the data cursor tip updates and moves along the curve. Judging from your question, I believe this is what you're looking for.
Take note that the data cursor tip only works for the points that you have plotted. It does not interpolate in between the points. As such, if you want finer resolution, choose a smaller step size between the beginning and end points.
Also, if you want to know the exact index of where your point is, plot just the amplitude values themselves:
plot(sin(t));
The x axis will plot the index number of each point instead of the time values. You can then use the data cursor tip to locate which index you want, then do that indexing that you have specified in your comment above. In other words:
This is telling us that at index 304, it gives us a y value of 0.1114. Then you could do t(304) to find the actual time value where the amplitude was at 0.1114.
h = plot(t, sin(2*pi*t)); %// get a handle to the graph
[x, ~] = ginput(1); %// y from ginput not wanted; it will be read from the graph
y = interp1(get(h,'XData'), get(h,'YData'), x); %// interpolate the graph for y

Clickable/ Interactive contour plots in Matlab

I have formed a 2D matrix of 180X360. In fact, it is a LatXLong grid of 1°X1°. Each grid point has a value calculated according to my algorithm.
If I want to plot this LatXLong grid using any contour function, it is easy to do.
Now, what I need to do is to make this grid a clickable/ interactive contour plot in a way that when the user clicks anywhere on my grid plot, he gets an onscreen information or a further plot to be displayed specifically related to that grid point.
In short, I want to make a grid/contour plot in which all grid points are hyperlinks and linked to further background information.
check this answer:
if you don't want to have the variable as title of the plot, you can modify the code as:
function mouseExample()
h = plot(rand(10,1), 'o-');
set(h, 'ButtonDownFcn',#buttonDownCallback)
function out = buttonDownCallback(o,e)
p = get(gca,'CurrentPoint');
out = p(1,1:2);
% title( sprintf('(%g,%g)',p) ) % --> no need this line anymore
end
end
the information is saved in the P variable that you can use later.
To get started, look into ginput and text. ginput will let you click on points in your plot and return the coordinates to some function that can generate information to be displayed in the current plot using text of by opening another figure.
You can use ginput in a loop to display multiple data points as you go:
for t = 1:10
[x,y] = ginput(1);
text(x,y,'some info');
end
I don't know of a way to remove the gird lines. NKN's solution might do that for you.