Abhishek Bhatia
Abhishek Bhatia

Reputation: 9796

Zooming and record previous picture pixel points, Keep constant zoom

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.

function main()
    clc;
    global agent_pos;
    ....
    for i=1:numel(img_names),
        imname = [ path_img img_names{i}];
        im0 = imread(imname);
        imageHandle =imshow(im0);%_____________displays the image
        set(gcf,'units','normalized','outerposition',[0 0 1 1])
        set(imageHandle,'ButtonDownFcn',@ImageClickCallback);
        uiwait(gcf);
    end

end

function coordinates=ImageClickCallback ( objectHandle , eventData )
    axesHandle  = get(objectHandle,'Parent');
    coordinates = get(axesHandle,'CurrentPoint'); 
    coordinates = coordinates(1,1:2);
    global agent_pos;
    agent_pos=[agent_pos;coordinates]; %___ add these coordinates for each image
    uiresume;
end

What I want to do is to zoom into a part of the picture using the GUI and click on the image. When I do so, matlab should record the pixel points' location with respect to the unzoomed image. Also, once the select the zoom location in the first image. It should the same in coming up ones.


When I try do the zoom through GUI in the first image now, and then change back the pointer to a cursor, it somehow stops and doesn't either record my click or go to the next image. Warning: figure JavaFrame property will be obsoleted in a future release. For more information see the JavaFrame resource on the MathWorks web site.

I tried to use imtools instead of imshow, but it show below warning with opening 2 images at a time and not record the clicks.

In main at 20 java.lang.NullPointerException at com.mathworks.hg.peer.FigureFrameProxy.setMaximized(FigureFrameProxy.java:302) at com.mathworks.hg.peer.FigureMediator.setMaximized(FigureMediator.java:468) at com.mathworks.hg.peer.FigurePeer.doSetMaximized(FigurePeer.java:3414) at com.mathworks.hg.peer.FigurePeer$26.run(FigurePeer.java:3403) at com.mathworks.hg.util.HGPeerQueue$HGPeerRunnablesRunner.runit(HGPeerQueue.java:294) at com.mathworks.hg.util.HGPeerQueue$HGPeerRunnablesRunner.runNotThese(HGPeerQueue.java:326) at com.mathworks.hg.util.HGPeerQueue$HGPeerRunnablesRunner.run(HGPeerQueue.java:342) at java.awt.event.InvocationEvent.dispatch(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$200(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source) Operation terminated by user during uiwait (line 81)

EDIT 1: Complete code:

function main()
    clc;
    global agent_pos;
    h = figure(1);   % Initiate figure with a specific number for easy handling
    set(h,'WindowButtonDownFcn',@ImageClickCallback);
    agent_pos=[];
    path_img='.\image_files_resized\';  %__________image files path
    path_posmap='.\pos_maps\';%_________stores positions of agents
    NumOfImages = length(dir(path_img)) - 2;
    w = dir(path_img);
    img_names={};      %________stores names of all images
    for i=3:NumOfImages+2,
        img_names{i-2} = w(i).name;
    end
    for ii=1:numel(img_names),
         % Get the XLim and YLim from previous imshow session
        if ii > 1   
            XLim = h.CurrentAxes.XLim;
            YLim = h.CurrentAxes.YLim;
        end


        imname = [ path_img img_names{ii}];
        im0 = imread(imname);
        figure(1);
        imageHandle =imshow(im0);%_____________displays the image
        [ht,wid,c]=size(im0);


        if ii==1,
            pause(0.00001);
            frame_h = get(handle(gcf),'JavaFrame');
            set(frame_h,'Maximized',1);
             hold on;
            [x,y]=getPrevAgents();
            plot(x,y,'o','color','green')
        end
        xlabel(img_names{ii});
        % Set the zoom level and location the same with previous imshow session
        if ii > 1    
            set(h.CurrentAxes, 'XLim', XLim)
            set(h.CurrentAxes, 'YLim', YLim)
        end
        uiwait(gcf);
    end
    filename = datestr(now,'mm_dd-HH_MM_SS');
    csvwrite(strcat(path_posmap,filename,'.csv'),agent_pos);
    close(gcf);
    plot_posagents();
    d = dir(strcat(path_posmap,'*.csv'));
    numfiles = length(d);
    disp(sprintf('Only %d files done..',length(d)));
end
function coordinates = ImageClickCallback ( objectHandle , eventData )
    global agent_pos;
    coordinates = get(objectHandle,'CurrentPoint'); 
    coordinates = coordinates(1, 1:2);
    agent_pos = [agent_pos;coordinates]; 
    uiresume;
end

ERROR:

Invalid or deleted object.

Error in main_new (line 18)
            XLim = h.CurrentAxes.XLim;

Upvotes: 3

Views: 202

Answers (1)

user3667217
user3667217

Reputation: 2192

In MATLAB, zoom is implemented through setting the XLim and YLim of the current axes. So to get the zoom info, you simply need to acquire these properties from the axes. If all your images are of the same size, you won't need to perform any calculation to get the zoom factor and zoom location to be applied to different images. Otherwise, zoom factor will be (XLim[2] - XLim[1])/size(img,2). CurrentPoint is a property of the figure but not its axes. So in your code, you won't get any coordinates. The following code should work properly if you first click on zoom button, zoom in or out, click the zoom off then go the position you like and click. If you click the mouse button while the zoom is still on, the 'WindowsButtondownFcn' will be that of the zoom object and won't do what you want it to do.

function main()
    global agent_pos; 
    h = figure(1);   % Initiate figure with a specific number for easy handling
    set(h,'WindowButtonDownFcn',@ImageClickCallback);

    for ii = 1:numel(img_names)
        % Get the XLim and YLim from previous imshow session
        if ii > 1   
            % for version 2014b and later 
            % XLim = h.CurrentAxes.XLim;
            % YLim = h.CurrentAxes.YLim;

            CurrentAxes = get(h, 'CurrentAxes');
            XLim = get(CurrentAxes, 'XLim');
            YLim = get(CurrentAxes, 'YLim');
        end

        imname = [ path_img img_names{ii}];
        figure(1)    % To ensure we're always staying on the same figure
        imshow(imname)            

        % Set the zoom level and location the same with previous imshow session
        if ii > 1
            % for version 2014b and later    
            % set(h.CurrentAxes, 'XLim', XLim)
            % set(h.CurrentAxes, 'YLim', YLim)

            CurrentAxes = get(h, 'CurrentAxes');
            set(CurrentAxes, 'XLim', XLim)
            set(CurrentAxes, 'YLim', YLim)
        end
        uiwait(gcf);
    end
end

function coordinates = ImageClickCallback ( objectHandle , eventData )
    global agent_pos;
    coordinates = get(objectHandle,'CurrentPoint'); 
    coordinates = coordinates(1, 1:2);
    agent_pos = [agent_pos;coordinates]; 
    uiresume;
end

It should be noted that since MATLAB 2014b, there's a major change on how graphics handle is implemented. see here

And to ensure your plotting command doesn't change the zoom setting, you can add these

if ii==1,
    CurrentAxes = get(h, 'CurrentAxes');
    XLim = get(CurrentAxes, 'XLim');
    YLim = get(CurrentAxes, 'YLim');

    % your code here
    pause(0.00001);
    ...
    plot(x,y,'o','color','green')

    set(CurrentAxes, 'XLim', XLim)
    set(CurrentAxes, 'YLim', YLim)
end

Upvotes: 3

Related Questions