Search code examples
matlabdata-structuresstructworkspacematlab-gui

Save data structure in existing .mat-file without nesting


I have created a simple GUI that when I press a button (SAVE), the system takes the value of some fields, calculates a certain function and saves the results in a data structure. I would like this data structure to be external to the program, that is to say it remains at the exit of Matlab and at the next opening of the program this data structure must be available and upgradable.

To do this I used a global data variable that I save and load when needed.

The problem is that it doesn't work properly, the data structure is filled strangely.

I show you a gif that is perhaps more explanatory: enter image description here

The saved structure is this: enter image description here

As you can see, there is a structure within the other and not a list of elements. Why?

I would like to have a data structure that contains n elements (where n is the number of images) and each element consists of 9 fields (name, category, siftOctaves, siftLevels, siftPeak, siftEdge, numFeatures, siftFeatures, siftDescriptors).

This is a piece of code:

%% SAVE BUTTON
function pushSiftSave_Callback(hObject, eventdata, handles)
    % hObject    handle to pushSiftSave (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    global data;

    try
        % Vector of string = name of all possible images 
        imgs = createListOfImages('../img/');
        % Get selected image
        imgName = get(handles.listbox, 'Value');
        imgPath = strcat('../img/', imgs(imgName));
        imgPath = imgPath{1};
        I_or = imread(imgPath);
        I = single(rgb2gray(I_or));

        % Get some parameters enter by user
        [siftOctaves, siftLevels, siftPeak, siftEdge] = takeSiftParameters(handles.editSiftOctaves, handles.editSiftLevels, handles.editSiftPeakTh, handles.editSiftEdgeTh, I_or);  

        % Sift function
        [f, d] = vl_sift(I, 'Octaves', siftOctaves, 'Levels', siftLevels, 'PeakThresh', siftPeak, 'EdgeThresh', siftEdge);

        % Number of features
        perm = randperm(size(f, 2));
        numFeatures = size(perm, 2);

        % Check if file exists
        if exist('../data/data.mat', 'file') == 2 
            data = load('../data/data');
        else
            data = struct;
        end
        % Insert information in data structure
        data = saveSiftInformation(data, imgs, imgPath, siftOctaves, siftLevels, siftPeak, siftEdge, f, d, numFeatures);

    catch
        ErrorMessage = lasterr;
        msgbox(ErrorMessage);
        disp(ErrorMessage);
    end



function [data] = saveSiftInformation(data, imgs, imgPath, siftOctaves, siftLevels, siftPeak, siftEdge, features, descriptors, numFeatures)
    imgPath = imgPath(8 : end);

    % Find index of image
    i = find((ismember(imgs, imgPath)));

    % Update data structure
    data(i).name = imgPath;
    data(i).category = imgPath(1 : end-6);
    data(i).siftOctaves = siftOctaves;
    data(i).siftLevels = siftLevels;
    data(i).siftPeak = siftPeak;
    data(i).siftEdge = siftEdge;
    data(i).numFeatures = numFeatures;
    data(i).siftFeatures = features;
    data(i).siftDescriptors = descriptors;

    % Save data 
    save('../data/data', 'data');
end


%% SAVE & QUIT BUTTON.
function pushQuit_Callback(hObject, eventdata, handles)
    % hObject    handle to pushQuit (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    global data;
    assignin('base', 'data', data);

Thanks!


Solution

  • The problem you're facing is generated when you load the data.mat file.

    Also, using data as the name of variable reurned by load contributes to generating confusion.

    The instruction

    data = load('../data/data')
    

    reads the data.mat and stores the "data" it contains in a struct named data therefore, your struct is actually a filed of the struct data returned by load.

    You can test it by setting a breakpoint just after the load call and inspecting the varialbe data.

    You can fix the problem by extracting the data field from the structure when loading the .mat file.

    if(exist('data.mat', 'file') == 2)
    %    data = load('data');
       tmp = load('data');
       data=tmp.data
    else
       data = struct;
    end
    

    Hope this helps,

    Qapla'