首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将MATLAB .m脚本转换为与八度兼容的语法时的维数问题

将MATLAB .m脚本转换为与八度兼容的语法时的维数问题
EN

Stack Overflow用户
提问于 2019-11-13 11:26:21
回答 1查看 188关注 0票数 1

我想运行一个MATLAB脚本M-文件,以重建一个点云在八度.因此,我不得不重写代码的某些部分,以使其与Octave兼容。实际上,M文件在Octave中工作得很好(我没有任何错误),而且绘制的点云乍看上去也不错,但是看起来这些变量的大小只有原始MATLAB变量的一半。在附图中你可以看到我的意思。

八度:

MATLAB:

你可以看到,例如,八度M的维数是1311114x3,而在MATLAB中是2622227x3。我的原始文件中的实际行数也是2622227行。

在这里,您可以看到我使用的原始文件(原始数据)的摘录。

代码语言:javascript
运行
复制
Rotation angle  Measured distance
-0,090  26,295
-0,342  26,294
-0,594  26,294
-0,846  26,295
-1,098  26,294
-1,368  26,296
-1,620  26,296
-1,872  26,296

在MATLAB中,我创建了输出变量如下所示。

代码语言:javascript
运行
复制
data = table;
data.Rotationangle = cell2mat(raw(:, 1));
data.Measureddistance = cell2mat(raw(:, 2));

由于八度没有table函数,所以我写到

代码语言:javascript
运行
复制
data = cellfun(@(x)str2num(x), strrep(raw, ',', '.'))

而不是。

八度也没有struct2array功能,所以我也不得不更换它。我用MATLAB写的。

代码语言:javascript
运行
复制
data = table2array(data); 

在“八达通”中,这样做有点困难。我必须创建一个struct2array函数,这是通过这个错误报告实现的。

代码语言:javascript
运行
复制
%% Create a struct2array function
function retval = struct2array (input_struct)
  %input check
  if (~isstruct (input_struct) || (nargin ~= 1))
    print_usage;
  endif

  %convert to cell array and flatten/concatenate output.
  retval = [ (struct2cell (input_struct)){:}];  
endfunction

clear b;
b.a = data;
data = struct2array(b);

我是不是犯了什么错误,有人能帮我解决这个问题吗?

编辑:

下面是我的脚本中使用raw的部分。

代码语言:javascript
运行
复制
delimiter = '\t';
startRow = 5;
formatSpec = '%s%s%[^\n\r]';
fileID = fopen(filename,'r'); 
dataArray = textscan(fileID, formatSpec, 'Delimiter', delimiter, 'HeaderLines' ,startRow-1, 'ReturnOnError', false, 'EndOfLine', '\r\n');
fclose(fileID);

%% Convert the contents of columns containing numeric text to numbers.
%  Replace non-numeric text with NaN.
raw = repmat({''},length(dataArray{1}),length(dataArray)-1);
for col=1:length(dataArray)-1
    raw(1:length(dataArray{col}),col) = mat2cell(dataArray{col}, ones(length(dataArray{col}), 1));   
end

numericData = NaN(size(dataArray{1},1),size(dataArray,2)); 

for col=[1,2]
    % Converts text in the input cell array to numbers. Replaced non-numeric
    % text with NaN.
    rawData = dataArray{col};
    for row=1:size(rawData, 1)
        % Create a regular expression to detect and remove non-numeric prefixes and
        % suffixes.
        regexstr = '(?<prefix>.*?)(?<numbers>([-]*(\d+[\.]*)+[\,]{0,1}\d*[eEdD]{0,1}[-+]*\d*[i]{0,1})|([-]*(\d+[\.]*)*[\,]{1,1}\d+[eEdD]{0,1}[-+]*\d*[i]{0,1}))(?<suffix>.*)';
        try
            result = regexp(rawData(row), regexstr, 'names');
            numbers = result.numbers;

            % Detected commas in non-thousand locations.
            invalidThousandsSeparator = false;
            if numbers.contains('.')
                thousandsRegExp = '^\d+?(\.\d{3})*\,{0,1}\d*$';
                if isempty(regexp(numbers, thousandsRegExp, 'once'))
                    numbers = NaN;
                    invalidThousandsSeparator = true;
                end
            end

            % Convert numeric text to numbers.
            if ~invalidThousandsSeparator
                numbers = strrep(numbers, '.', '');
                numbers = strrep(numbers, ',', '.');
                numbers = textscan(char(numbers), '%f');
                numericData(row, col) = numbers{1};
                raw{row, col} = numbers{1};
            end
        catch
            raw{row, col} = rawData{row};
        end
    end
end

您不会在我的工作区中看到任何raw,因为在重构点云之前,我清除了所有临时变量。此外,我在第1311114和1311115行中的原始数据看起来也很正常。

编辑2:

正如建议的那样,这里有一个小示例表,用于澄清我想要什么,以及在我的例子中,MATLAB如何处理table2array函数。

代码语言:javascript
运行
复制
data =

   -0.0900   26.2950
   -0.3420   26.2940
   -0.5940   26.2940
   -0.8460   26.2950
   -1.0980   26.2940
   -1.3680   26.2960
   -1.6200   26.2960
   -1.8720   26.2960

使用我在Octave中使用的struct2array函数,我得到了以下数组。

代码语言:javascript
运行
复制
data =

    -0.090000    26.295000
    -0.594000    26.294000
    -1.098000    26.294000
    -1.620000    26.296000
    -2.124000    26.295000
    -2.646000    26.293000
    -3.150000    26.294000
    -3.654000    26.294000

如果您将Octave数组与我的原始数据进行比较,您可以看到每第二行都被跳过。这似乎是1311114行而不是2622227行的原因。

编辑3:

我试图用@Tasos Papastylianou的建议来解决我的问题,但不幸的是,这一建议没有成功。首先,我用结构做了变体。

代码语言:javascript
运行
复制
data = struct();
data.Rotationangle = [raw(:,1)];
data.Measureddistance = [raw(:,2)];
data = cell2mat( struct2cell (data ).' )

但这将导致我的脚本中的结构如下。(不幸的是,结果并不如编辑2所示。不要惊讶,我只使用了原始文件的一小部分来加速脚本的运行,所以这里只有769行。)

代码语言:javascript
运行
复制
  [766,1] = -357,966
  [767,1] = -358,506
  [768,1] = -359,010
  [769,1] = -359,514
  [1,2] = 26,295
  [2,2] = 26,294
  [3,2] = 26,294
  [4,2] = 26,296

此外,我得到以下错误。

代码语言:javascript
运行
复制
error: unary operator '-' not implemented for 'cell' operands
error: called from
    Cloud_reconstruction at line 137 column 11

同样,使用dataframe八度包的方法也不起作用。当我运行以下代码时,会导致以下错误。

代码语言:javascript
运行
复制
dataframe2array = @(df) cell2mat( struct(df).x_data );
pkg load dataframe;
data = dataframe();
data.Rotationangle = [raw(:, 1)];
data.Measureddistance = [raw(:, 2)];
dataframe2array(data)

错误:

代码语言:javascript
运行
复制
warning: Trying to overwrite colum names
warning: called from
    df_matassign at line 147 column 13
    subsasgn at line 172 column 14
    Cloud_reconstruction at line 106 column 20
warning: Trying to overwrite colum names
warning: called from
    df_matassign at line 176 column 13
    subsasgn at line 172 column 14
    Cloud_reconstruction at line 106 column 20
warning: Trying to overwrite colum names
warning: called from
    df_matassign at line 147 column 13
    subsasgn at line 172 column 14
    Cloud_reconstruction at line 107 column 23
warning: Trying to overwrite colum names
warning: called from
    df_matassign at line 176 column 13
    subsasgn at line 172 column 14
    Cloud_reconstruction at line 107 column 23
error: RHS(_,2): but RHS has size 768x1
error: called from
    df_matassign at line 179 column 11
    subsasgn at line 172 column 14
    Cloud_reconstruction at line 107 column 23

这两条错误信息都引用了我的脚本的以下部分,我正在用柱面坐标重建点云。

代码语言:javascript
运行
复制
distLaserCenter = 47; % Distance between the pipe centerline and the blind zone in mm
m = size(data,1);   % Find the length of the first dimension of data
zincr = 0.4/360;   % z increment in mm per deg
data(:,1) = -data(:,1);    

for i = 1:m    
    data(i,2) = data(i,2) + distLaserCenter;    
    if i == 1 
        data(i,3) = 0;
    elseif abs(data(i,1)-data(i-1)) < 100
        data(i,3) = data(i-1,3) + zincr*(data(i,1)-data(i-1));
    else abs(data(i,1)-data(i-1)) > 100;
        data(i,3) = data(i-1,3) + zincr*(data(i,1)-(data(i-1)-360));
    end
end

给出一些背景信息,以便更好地理解。该脚本用于将管道重构为点云。用激光从内部对管道表面进行扫描,每次旋转时激光测量几个点(从激光到管道内壁的距离)。我希望这有助于理解我想用我的脚本做什么。

EN

回答 1

Stack Overflow用户

发布于 2019-11-13 14:01:29

不确定您到底想要做什么,但下面是一个如何以与表相同的方式使用结构的玩具示例:

matlab:

代码语言:javascript
运行
复制
data = table;
data.A = [1;2;3;4;5];
data.B = [10;20;30;40;50];
table2array(data)

八度:

代码语言:javascript
运行
复制
data = struct();
data.A = [1;2;3;4;5];
data.B = [10;20;30;40;50];
cell2mat( struct2cell (data ).' )

在将结果传递给.'之前,请注意换位操作( cell2mat ),因为在表中,“字段名”是水平排列在列中的,而struct2cell则将过去的“字段名”安排为行。

您可能还对dataframe八度包感兴趣,它执行类似于matlab表(或者实际上是R的dataframe对象)的功能:https://octave.sourceforge.io/dataframe/ (您可以通过在控制台中键入pkg install -forge dataframe来安装它)。

不幸的是,将数据显示为数组的方式仍然不理想(请参阅:https://stackoverflow.com/a/55417141/4183191),但您可以轻松地将其转换为一个很小的函数。

代码语言:javascript
运行
复制
dataframe2array = @(df) cell2mat( struct(df).x_data );

然后,您的代码可以变成:

代码语言:javascript
运行
复制
pkg load dataframe;
data = dataframe();
data.A = [1;2;3;4;5];
data.B = [10;20;30;40;50];
dataframe2array(data)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58836086

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档