Consider the following example
ax(1) = subplot(2,1,1)
plot(1:100,rand(1,100))
ax(2) = subplot(2,1,2)
plot(1:100,rand(1,100))
hzoom(1) = zoom(ax(1));
hzoom(1).Motion = 'horizontal';
hzoom(2) = zoom(ax(2));
hzoom(2).Motion = 'horizontal';
zoom on
linkaxes(ax, 'x');
waitforbuttonpress;
while 1
[x, ~] = ginput(2);
zoom on
waitforbuttonpress;
click_break = waitforbuttonpress;
if(click_break)
break;
end
end
In the above plots for the first time of the loop the mouse cursor is magnifying glass and i can zoom into a data by simply selecting it
and here we can see the data is zoomed in
but when i have clicked twice (for the ginput to get datapoints) and the loop runs in the next iteration the cursor doesnt magnify/zoom by selecting the specific data , I know we can also zoom in by scrolling but my scroll has developed some problem the magnification converges to centre data points so the only posibility is data selection through mouse click, am I missing any function in my loop?
Related
I am trying to do create a ball or dot or whatever that goes from left bottom corner to right bottom corner then top right corner then left top corner then on the start so left bottom corner. Basically around the screen. And in total fullscreen that important. For fullscreen graph i am using WindowAPI.
So here is my code.
try
% Create a figure to operate on: --------------------------------------------
% The OpenGL renderer is confused by the alpha blending, so Painters is used:
FigH = figure('Color', ones(1, 3), 'Renderer', 'Painters');
axes('Visible', 'off', 'Units', 'normalized', 'Position', [0, 0, 1, 1]);
% Set topmost status:
WindowAPI(FigH, 'topmost'); % Command is not case-sensitive
drawnow;
WindowAPI(FigH, 'TopMost', 0);
drawnow;
WindowAPI(FigH, 'front');
drawnow;
% Nicer to have the figure on topmost for the rest of the demo:
WindowAPI(FigH, 'topmost');
% Special maximizing such that the inner figure fill the screen:
WindowAPI(FigH, 'Position', 'full'); % Complete monitor
% START MOVING BALL
X = 2;
Y = 0;
for i=1:1490
X = X + 0.1;
Y = 2
plot(X,Y,'or','MarkerSize',20,'MarkerFaceColor','r')
axis([0 151 0 85])
pause(0)
end
% END MOVING BALL
end
For simplicity that dot goes only from left to right bottom corner.
But there are two problems.
that dot lag sometimes which is a problem.
There are visible black lines (from the graph).
And I don't know how to fix these two problems. So if u know how to fix them or any better way how to animate ball in Matlab please post it here. Thanks for your time.
To reduce the amount of 'Lag' you can do a few of the following:
Move the plot line outside of the loop and assign it to a handle, additionally move the axis commandos out with it
pH = plot(X,Y,'or','MarkerSize',20,'MarkerFaceColor','r');
axis([0 151 0 85])
axis off
Now you can update the X Y data directly in the loop.
set(pH,'XData',X,'YData',Y)
Replace the pause with (replace 0 with the length in seconds that you want to delay the frame by):
tic;while toc<0;end
This is faster, more precise, and does not cause an interrupt to MatLab.
Add the drawnow command in the loop to cause the figures to update.
I would like to implement the fly-through effect as shown in this nice example. First I created a figure from matrix hm, a 300X300 matrix by using the surf function:
surf(hm);
Then, I defined an animated line from variables x, y, and z and displayed on the figure as follows:
curve = animatedline;
curve.LineWidth = 6;
curve.Color = [ 1 0 1];
for i = 1:length(x)
addpoints(curve, x(i), y(i), z(i));
drawnow;
end
Then, I wanted to implement the fly-through effect so that the camera will move along the line. I tried this code piece I took from the example above and I slightly modified it:
for i = 1:length(x)
campos([(x(i) -5), (y(i)-5), 0]);
camtarget([x(i), y(i), z(i)]);
drawnow;
end
But the camera doesn't move as I intended. What am I doing wrong?
If you want to mimic the behavior of the linked example, you need to have both the camera target and camera position moving along your curve defined by (x, y, z). The way you've written it above, the camera target moves along the curve, but the camera position is always offset from the target by (-5, -5) in the xy plane and sitting at z = 0. If you want the camera to follow the curve behind the target, you should try something like this:
for iPoint = 6:numel(x)
campos([x(iPoint-5) y(iPoint-5) z(iPoint-5)]); % Note the index is shifted, not the value
camtarget([x(iPoint) y(iPoint) z(iPoint)]);
drawnow;
end
If you don't want the camera moving along the same curve, and instead want it to always be at a fixed offset from your moving camera target, you could try this:
offset = [-5 -5 0]; % X, Y, and Z offset from target
for iPoint = 1:numel(x)
campos([x(iPoint)+offset(1) y(iPoint)+offset(2) z(iPoint)+offset(3)]);
camtarget([x(iPoint) y(iPoint) z(iPoint)]);
drawnow;
end
Finally, if you'd like to control the speed of the animation, you can replace the drawnow command with a call to pause. Note that a call to pause is equivalent to a call to drawnow in that it will force an update of graphics objects. You can also animate graphics using a timer object, as I illustrate in this answer.
I am writing a GUI in MATLAB (guide) where user will be shown 2 images(both images are positioned side by side in single gui window) from a series of images (but each drifted little bit) and will be allowed to select area of interest.
I want user to select working are in image 1 while simultaneously highlighting the selected area in image 2, so that it is easier to judge whether the feature of interest has drifted out of selected area or not. How to do that?
I am using following answer to select and crop area of interest(just FYI):
crop image with fixed x/y ratio
Here is a way to do it using imrect and its addNewPositionCallback method. Check here for a list of available methods.
In the following figure I create 2 axes. On the left that's the original image and on the right that's the "modified" image. By pressing the pushbutton, imrect is called and the addNewPositionCallback method executes a function, called GetROIPosition that is used to get the position of the rectangle defined by imrect. At the same time, in the 2nd axes, a rectangle is drawn with the same position as that in the 1st axes. To be even more fancy you can use the setConstrainedPosition to force the rectangle to be enclosed in a given axes. I'll let you do it :)
Here is the whole code with 2 screenshots:
function SelectROIs(~)
%clc
clear
close all
%//=========================
%// Create GUI components
hfigure = figure('Position',[300 300 900 600],'Units','Pixels');
handles.axesIm1 = axes('Units','Pixels','Position',[30,100,400 400],'XTick',[],'YTIck',[]);
handles.axesIm2 = axes('Units','Pixels','Position',[460,100,400,400],'XTick',[],'YTIck',[]);
handles.TextaxesIm1 = uicontrol('Style','Text','Position',[190 480 110 20],'String','Original image','FontSize',14);
handles.TextaxesIm2 = uicontrol('Style','Text','Position',[620 480 110 20],'String','Modified image','FontSize',14);
%// Create pushbutton and its callback
handles.SelectROIColoring_pushbutton = uicontrol('Style','pushbutton','Position',[380 500 120 30],'String','Select ROI','FontSize',14,'Callback',#(s,e) SelectROIListCallback);
%// ================================
%/ Read image and create 2nd image by taking median filter
handles.Im = imread('coins.png');
[Height,Width,~] = size(handles.Im);
handles.ModifIm = medfilt2(handles.Im,[3 3]);
imshow(handles.Im,'InitialMagnification','fit','parent',handles.axesIm1);
imshow(handles.ModifIm,'InitialMagnification','fit','parent',handles.axesIm2);
guidata(hfigure,handles);
%%
%// Pushbutton's callback. Create a draggable rectangle in the 1st axes and
%a rectangle in the 2nd axes. Using the addNewPositionCallback method of
%imrect, you can get the position in real time and update that of the
%rectangle.
function SelectROIListCallback(~)
hfindROI = findobj(handles.axesIm1,'Type','imrect');
delete(hfindROI);
hROI = imrect(handles.axesIm1,[Width/4 Height/4 Width/2 Height/2]); % Arbitrary size for initial centered ROI.
axes(handles.axesIm2)
rectangle('Position',[Width/4 Height/4 Width/2 Height/2],'EdgeColor','y','LineWidth',2);
id = addNewPositionCallback(hROI,#(s,e) GetROIPosition(hROI));
end
%// Function to fetch current position of the moving rectangle.
function ROIPos = GetROIPosition(hROI)
ROIPos = round(getPosition(hROI));
axes(handles.axesIm2)
hRect = findobj('Type','rectangle');
delete(hRect)
rectangle('Position',ROIPos,'EdgeColor','y','LineWidth',2);
end
end
The figure after pressing the button:
And after moving the rectangle around:
Yay! Hope that helps! Nota that since you're using GUIDE the syntax of the callbacks will look a bit different but the idea is exactly the same.
I have an inverted pendulum video here which is 33 second length. The objective is to plot a red point in the center of moving rectangle part of the pendulum and to plot a line along the black stick calculating its angle for every frame.
I have handled the video frame by frame. Then I have used Object Detection In A Cluttered Scene Using Point Feature Matching. It would be good if I had access to the matching point's indexes and then I would easily calculate the angle.
I have thought that I can get the moving rectangle part's region and seek the similar regions in the next frames. But this solution seems too local.
I do not know which techniques to apply.
clear all;
clc;
hVideoFileReader = vision.VideoFileReader;
hVideoPlayer = vision.VideoPlayer;
hVideoFileReader.Filename = 'inverted-pendulum.avi';
hVideoFileReader.VideoOutputDataType = 'single';
while ~isDone(hVideoFileReader)
grayFrame = rgb2gray(step(hVideoFileReader));
frame = step(hVideoFileReader);
if isFirstFrame
part = grayFrame(202:266,202:282); % #moving part's region
isFirstFrame = false;
subplot(1,2,1);
imshow(part);
end
partPoints = detectSURFFeatures(part);
grayFramePoints = detectSURFFeatures(grayFrame);
hold on;
subplot(1,2,1), plot(partPoints .selectStrongest(10));
subplot(1,2,2), imshow(grayFrame);
subplot(1,2,2), plot(grayFramePoints .selectStrongest(20));
frame2 = pointPendulumCenter(frame);
frame3 = plotLineAlongStick(frame2);
step(hVideoPlayer, frame3);
hold off;
end
release(hVideoFileReader);
release(hVideoPlayer);
%% #Function to find the moving part's center point and plot a red dot on it.
function f = pointPendulumCenter(frame)
end
%% #Function to plot a red line along the stick after calculating the angle of it.
function f = plotLineAlongStick(frame)
end
It would make the problem much easier if your camera did not move. If you take your video with a stationary camera (e.g. mounted on a tripod) then you can use vision.ForegroundDetector to segment out moving objects from the static background.
I'm displaying a 3D scatterplot, but label on the z-axis is getting overlapped by the color bar. How can I shift the color bar a desired number of pixels to the right or left?
You can use findobjto get an handle to the colorbar, query its current position via get and then modify according to your needs and change it using set:
h = findobj('tag', 'Colorbar');
pos = get(h, 'position')
% modify pos according to your needs
set(h, 'position', pos)