【问题标题】:Save data structure in existing .mat-file without nesting将数据结构保存在现有的 .mat 文件中而不嵌套
【发布时间】:2017-05-13 21:10:14
【问题描述】:

我创建了一个简单的 GUI,当我按下按钮 (SAVE) 时,系统会获取一些字段的值,计算某个函数并将结果保存在数据结构中。 我希望这个数据结构在程序外部,也就是说它保留在 Matlab 的出口处,并且在程序的下一次打开时,这个数据结构必须可用且可升级。

为此,我使用了一个全局 data 变量,我会在需要时保存并加载它。

问题是它不能正常工作,data结构被奇怪地填充了。

我给你看一个可能更能说明问题的 gif:

保存的结构是这样的:

如您所见,在另一个中存在一个结构,而不是元素列表。为什么?

我想要一个包含 n 个元素(其中 n 是图像数量)的 data 结构,每个元素由 9 个字段组成(namecategorysiftOctavessiftLevelssiftPeak, siftEdge, numFeatures, siftFeatures, siftDescriptors)。

这是一段代码:

%% 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);

谢谢!

【问题讨论】:

    标签: matlab data-structures struct workspace matlab-gui


    【解决方案1】:

    您面临的问题是在您加载data.mat 文件时产生的。

    此外,使用data 作为load 重复的变量名称会导致混淆。

    指令

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

    读取data.mat 并将其包含的“数据”存储在名为data 的结构中,因此,您的结构实际上是data 返回的结构datafiled

    您可以通过在load 调用之后设置断点并检查变量data 来测试它。

    您可以通过在加载.mat 文件时从结构中提取data 字段来解决此问题。

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

    希望对你有帮助,

    卡普拉'

    【讨论】:

      【解决方案2】:

      通过使用load 函数的输出变量,您可以将变量data 从您的.mat 文件存储到一个名为data 的结构中——因此它是嵌套的。只需使用load 不带任何输出即可。

      if exist('data.mat', 'file') == 2 
          %// data = load('data');  % does not work!
          load('data');  % does work!
      else
          data = struct;
      end
      
      data(1).a = 42;
      data(2).a = 3;
      data(1).b = 41;
      data(2).b = 4;
      
      %// make sure you just store what you want to store, in this case "data"
      save('data.mat','data')
      

      另外,我会避免将 data 声明为全局变量。相反,您可以使用这样一个事实,即您的 GUI 的所有功能都是同一个图形窗口的一部分,因此可以使用图形句柄:

      hFig = gcf;
      

      还允许添加dynamic properties 作为figure 的实例,因此只需将数据存储在图形句柄本身中即可:

      hFig = gcf;
      addprop(hFig,'globalData')
      
      data = struct;
      hFig.globalData = data;
      
      % ...
      

      在下一个函数中,您只需执行以下操作:

      data = hFig.globalData
      

      【讨论】:

      • OP 正在使用数组 if struct;在这种情况下,保存数据时不能使用-struct选项。
      • @il_raffa,你是对的。谢谢你。但是,临时变量不是必需的!
      猜你喜欢
      • 2015-12-19
      • 2016-06-12
      • 1970-01-01
      • 2014-05-08
      • 2018-10-07
      • 1970-01-01
      • 2012-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多