function main()
clear all;clc;
path='.\image_files\'; %___________image files path
path_posmap='.\pos_maps\';%_________stores positions of agents
NumOfImages = length(dir(path)) - 2;
w = dir(path);
img_names={}; %________stores names of all images
for i=3:NumOfImages+2,
img_names{i-2} = w(i).name;
end
for i=1:numel(img_names),
imname = [ path img_names{i}];
im0 = imread(imname);
imageHandle =imshow(im0);%_____________displays the image
xlabel(num2str(i));
set(imageHandle,'ButtonDownFcn',#ImageClickCallback);
end
end
function coordinates=ImageClickCallback ( objectHandle , eventData )
axesHandle = get(objectHandle,'Parent');
coordinates = get(axesHandle,'CurrentPoint');
coordinates = coordinates(1,1:2);
message = sprintf('x: %.1f , y: %.1f',coordinates (1) ,coordinates (2));
disp(coordinates); %___ add these coordinates for each image
close(gcf);
end
I want to display a series of images to a user. For each image request input from the user in the form of a mouse click on the image. Store the coordinates of each click in a matrix. Thus, in end having a matrix of dimension num_images x 2.
But in the above
a. I can't get the coordinates returned from the function ImageClickCallback
b. I am unable to close the image and display a new one whenever the user clicks.
I have no MATLAB here right now, so there are a couple guesses in my answer. Here we go:
Closing Figures
You don't close the image, so it won't close. Just add close gcf; at the end of your callback.
Passing Data
Now to get the coordinates I'd suggest using the base workspace instead of a global variable, or pass an argument to your callback.
Means I'd use assignin('base','newcords',coordinates); at the end of your callback.
Use evalin to get your coordinates back from the base workspace. You can try to access newcords without evalin, however I am pretty sure it isn't going to work.
newcords=evalin('base','newcords');
Now you create a new Variable (initialize it outside the for-loop), which holds all coordinates, assuming 2D-coordinates: allcords=zeros(2,numel(img_name));
Write the coordinates from the callback into your new-allcords-variable.
allcords(1,i)=newcords(1);
allcords(2,i)=newcords(2);
On Second thought you don't need to pass the coordinates back from the callback, go with:
Initialize allcords outside your loop:
allcords=zeros(2,1);
In your callback:
allcords=evalin('base',allcords);
allcordssize=size(allcords):
if min(allcordssize)=1
allcords(1,end)=coordinates(1);
allcords(2,end)=coordinates(2);
assignin('base','allcords',allcords);
else
allcords(1,end+1)=coordinates(1);
allcords(2,end+1)=coordinates(2);
assignin('base','allcords',allcords);
end
close gcf %close picture
With that you have all your coordinates from your callback. Another way you could use is, as I mentioned above, passing a variable to your callback.
Make sure data is matched with correct figure
The second problem is, your for loop does open all pictures at once I guess? (I Have no MATLAB available). So how about using uiwait(gcf); in your for loop? (After your set). This way you know which coordinates are assigned to which figure (also if all pictures are opened your coordinates are reverse to the img-list-indexes).
P.S.: I'm not sure if uiwait works in this case, what would work for sure is if you create a single GUI with just 1 handle (for your image), and instead of closing your figure just redraw your image each time your coordinates are chosen. Or load your GUI each loop-iteration, and pass the image name to the GUI.
Related
I have one problem with InputPoint.face method in Sketchup Ruby API.
When i import one image object and then draw 5-edges polygon on this image. I used InputPoint.face for getting number of edges in the polygon after clicking on it. I think the output is 5, but actually, the output is 4
If i remove the image , result will be 5.
I don't understand why the output is like that, and what can i do to get output 5?
This is my code
# The onLButtonDOwn method is called when the user presses the left mouse button.
def onLButtonDown(flags, x, y, view)
#ip = view.inputpoint x,y
#f = #ip.face
aEdges = #f.edges
puts aEdges.length
end
Thanks you
So you have drawn pentagon faces on the Image entity you imported? And when you use InputPoint to click on one of the pentagons you get a face with four edges?
What happens here is probably that you are getting the Face inside the Image entity. Under the hood an Image entity is a special component instance. You can in fact find the definition for the Image entity in model.definitions.
For more details on SketchUp and Components, Groups and Images read this article: http://www.thomthom.net/thoughts/2012/02/definitions-and-instances-in-sketchup/
InputPoint and PickHelper seem to let you pick the face inside the Image entity instead of stopping when it hits the Image entity.
You will probably want to filter out your results before using them and you probably wantto use the PickHelper class instead of InputPoint.
http://www.sketchup.com/intl/en/developer/docs/ourdoc/pickhelper.php
http://www.thomthom.net/thoughts/2013/01/pickhelper-a-visual-guide/
InputPoint is more for getting 3d points for inference, while PickHelper is best to use to pick and select entities.
You can check the Face entity you get from InputPoint and it's parent to verify which face it is and what context it belongs to.
I have a double 2D image that I want to use in my UI that I made with guide. I have a axis handle which I want to draw it to. I tried this with no success, my image is all blue.
function ComputeMap_Callback(hObject, eventdata, handles)
% hObject handle to ComputeMap (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global healthyImage;
global sickImage;
global tumorMapImage;
global costFunction;
if(get(handles.radiobuttonMSE,'Value') == get(hObject,'Max'))
costFunction = 0;
else
costFunction = 1;
end
disp(costFunction);
tumorMapImage = mexFunction(im2double(sickImage),im2double(healthyImage),get(handles.blockSize,'Value'),get(handles.windowSize,'value'), costFunction);
image(tumorMapImage,'parent',handles.sImageGUI);
This mexFunction returns a double 2D image. If I just call this function without matlab and imShow (resultImage); I get the right result. So I believe it has something to do with the colormapping of the double and the fact that the image is not 3D but 2D. But I am 0 familiar with gui in matlab to be sure what to do. I've done some more researches and I think my problem might be related to the AlphaData property, but I don't know what to do with that.
your image values must be in range [0, 1] in order to be plotted properly by the image function.
imshow works because it first looks at the min and max value in your image and then scales values to match this range. or so. (maybe it works differently internally, but whatever..)
I define values for the variables and call the function, it returns the output image in the figure. But when i want to test another set of data, the output image will come out, it's together with the previous output image. How can i solve it, do i need to add what code at the end of the function file?
Either close all before your generate the new figure if you're not interested in the old output figure, or make a figure call before creating the new image to ensure it pops up in a new figure window. Or, you can overwrite the current open figure by setting hold off first, although that's specifically for graphs.
Is it possible to output images so that they all will be inside a single window?
Before, I used to output data using only opencv functions:
cvNamedWindow("Image 1");
cvShowImage("Image 1", img);
So I change image, then call: cvShowImage function and so on.
But If I want to look at more than one image, then every new image needs its own window to be shown there And what I want is to put every such an output opencv's window inside one big main window.
Is it possible to do it? And how?
You will have to construct a new image and place each img into it. I don't think there's a builtin function like MATLAB's subplot. I recommend using the ROI functions to quickly copy an image into a region-of-interest (ROI) of the big image (which holds the others).
You can show as many images as you want on a single window using hconcat function.
Let us suppose your original image was
Mat frame;
Now clone or make a copy of this image using
Mat frame1 = frame.clone();//or
Mat frame2;
frame.copyTo(frame1);
Now let us suppose your output images are
Mat img1,img2,img3,img4;
Now if you want to show images horizontally, use
hconcat(img1,img2,frame1)//hconcat(input_image1,input_image2,destination_image);
And if you want to show images vertically, use
frame2.push_back(img1);//main_image.push_back(image_to_be_shown_below);
This process processess images one at a time, so if you want to show 4 images side by side, you have to call this function 4 times as in
hconcat(img1,img2,frame1);
hconcat(frame1,img3,frame1);
hconcat(frame1,img4,frame1);
imshow("Final Image",frame1);
NOTE:
Clone process is done because the images have to be of same size.
Enjoy...
I am making a GUI for a program I have created, where I need to be able to change the position of a load along a beam. I have set up the axes and the slider properly, but I am unsure how to get the axes to update, as I can't find any examples that show how to do this on the internet.
At present, as I move the load, the position updates properly, but the old position stays on screen as well, which is quite annoying.
Can anyone recommend any good examples that show how to do this, or does anyone have a suggestion of how to go about refreshing the axes?
Here is the slider callback (I haven't included the create_fcn function). Also, theres a lot of comments in the code, as I used the Guide function to make the GUI.
Please note that the input to slider is a proportion of the overall beam length (as a decimal).
function PointLoadxx1posslider_Callback(hObject, eventdata, handles)
% hObject handle to PointLoadxx1posslider (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
PLxx1pos = get(handles.PointLoadxx1posslider,'value');
set(handles.PLxx1posedit, 'String', num2str(PLxx1pos));
l = 3000; % This is the Length of the beam
zpl1 = get(handles.PointLoadxx1posslider,'value')*l;
% Multiplies the position decimal by the overall length
LoadPlotter(hObject,zpl1,handles) % Sends the command to the plot plot function
guidata(hObject,handles);
function LoadPlotter(hObject,zpl1,handles)
% The following draws the beam supports as lines
SH = l/20; %Height of supports
line([0 l], [SH/2 SH/2])
line([-SH/2 SH/2], [0 0])
line([-SH/2 0], [0 SH/2])
line([0 SH/2], [SH/2 0])
line([l-SH/2 l+SH/2], [0 0])
line([l-SH/2 l], [0 SH/2])
line([l l+SH/2], [SH/2 0])
xlim([ -100 l+200])
ylim([-l/2 l/2])
%Draw Load position
% zpl1 = get(handles.PointLoadxx1posslider,'value')*l;
% zpl1 = 0.5*l;
zpl2 = 0.2*l;
PL1 = 50;
%This is the value of the point load applied to the beam, which will
be an input from another slider
PL1Draw = line([zpl1 zpl1],[SH/2 PL1*10]);
% refresh(handles.axes1);
guidata(hObject,handles);
Obviously, I would like to keep the other lines drawn, but change PL1Draw as the slider is moved. Please can you explain what I am supposed to tag to do this?
Many thanks in advance.
James
I assume that you have plotted a beam, which is supposed to bend as you change the slider value. Since you are able to plot the new position into the axes, I assume that you know how to write callbacks. I further assume that there are parts of the plot that should stay the same, and parts that should change.
To change the parts that need changing, the easiest method is just to delete them and then to redraw. In order to delete specific items from a plot, it's best to tag them. Thus, your plotting would go like this
%# remove the old position
%# find the handle to the old position by searching among all the handles of
%# the graphics objects that have been plotted into the axes
oldPosHandle = findall(handles.axes1,'Tag','position');
delete(oldPosHandle);
%# plot new position
PL1Draw = line([zpl1 zpl1],[SH/2 PL1*10]);
%# add the tag so that you can find it if you want to delete it
set(PL1Draw,'Tag','position');
Note 1
To make the GUI respond faster (if needed), do not delete and re-plot, but change the 'XData' and 'YData' property of the old position object.
Note 2
If you aren't already doing so, put the plotting function (the one that updates everything in the plot, not just the position of the load) in a separate function, not into the callback of the slider, and have instead the slider callback call the plot function. This way, you can call the same plotting function from several buttons and sliders, which makes the code a lot easier to maintain.
EDIT
I have updated the commands. Note that there is no special 'tagging' function. 'Tag' is a property of every graphics object, like 'Units', or 'Color'. It simply helps you to label the graphics objects so that you don't need to remember the handles.
Unrelated to the actual question, but related to the project:
http://www.mathworks.com/matlabcentral/fileexchange/2170
This book is still available used on Amazon, it might save you a lot of the coding of the Mechanics of Materials stuff. I wrote this about 12 years ago as an undergrad, but I think the MATLAB code should still be functional.