C++改写Matlab源码实践一之【显示图片】——————附带详细讲解和示例

2023-05-16

文章目录

  • 0 背景
  • 1 Matlab有用代码提取
  • 2 转换为C++
  • 3 使用纯C++实现mat数据中的图片显示
  • 4 代码封装
  • 5 福利
  • 其他

0 背景

这里以显示Matlab变量struct中的图片程序代码为例,示范如何将其转换为C++代码,并在C++代码中显示图片。由于在Matlab的代码转换中是不支持转换输出图片文件的函数(例如imshow函数),于是只能返回uint8格式的图片数据((8位无符号整数,即1个字节,以此方式存储的图像称作8位图像,相比较默认matlab数据类型双精度浮点double(64位,8个字节),可以节省很大一部分存储空间),然后自己写图片显示函数。

难点就在于显示转换后的C++代码中返回的uint8格式的图片。

下图为Matlab变量struct中的信息(包含多个cell):
请添加图片描述
每个cell中包含400个112923维度的矩阵(即400张三通道的图片数据【高112(行),宽92(列)】):

在这里插入图片描述

下图为uint8格式的图片数据:
在这里插入图片描述
下图为在Matlab中显示的图片数据:

请添加图片描述

在这里插入图片描述

下图为C++改写后显示彩色图片(也就是我们最终实现的结果):

在这里插入图片描述

⚠️:这里预先转换的前提是,需要在转换机器上安装Matlab和opencv(用于图片显示),具体的安装方法在以前的博文中有详细讲解。

1 Matlab有用代码提取

下面的代码为Mtalab的原始代码:

function varargout = untitled(varargin)

gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @untitled_OpeningFcn, ...
                   'gui_OutputFcn',  @untitled_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end

function untitled_OpeningFcn(hObject, eventdata, handles, varargin)

set(handles.Dimension,'String',''); % 属性纬度
set(handles.Numbers,'String',''); % 对象个数
set(handles.Clusters,'String',''); % 训练准确率
set(handles.RecNum,'String',''); % 识别对象

handles.output = hObject;

guidata(hObject, handles);

function varargout = untitled_OutputFcn(hObject, eventdata, handles) 

varargout{1} = handles.output;
% 载入数据
function Load_Callback(hObject, eventdata, handles)
% 数据载入控制
global Myfig;
global Convfig;
global TrFig;
load('Fig.mat');
load('Oliver.mat');
bar = waitbar(0,'读取数据中...');
for i=1:100
    str=['训练中...',num2str(100*i/100),'%'];    % 百分比形式显示处理进程,不需要删掉这行代码就行
    waitbar(i/100,bar,str)                       % 更新进度条bar,配合bar使用
end
close(bar);  
Myfig = gRGB;
Convfig = gRGB1;
TrFig = gRGB2;
% data1 = Data1;
set(handles.Dimension,'String',num2str(size(FigData,2))); % 属性维度
set(handles.Numbers,'String',num2str(size(FigData,1))); % 对象个数
set(handles.Clusters,'String',[num2str(85.50),'%']);

function Exit_Callback(hObject, eventdata, handles)
delete(handles.figure1);
close all;

function Iteration_Callback(hObject, eventdata, handles)

function Dimension_Callback(hObject, eventdata, handles)

function Dimension_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function Numbers_Callback(hObject, eventdata, handles)

function Numbers_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function Clusters_Callback(hObject, eventdata, handles)

function Clusters_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
% 展示图片
function Perform_Callback(hObject, eventdata, handles)

cla reset
global Myfig;
global Convfig;
global TrFig;
Cope = get(handles.RecNum,'String');
   if isempty(Cope)
    pause(0.25);
    h=msgbox('请先选择识别对象(1-400)');
    uiwait(h,5);
   else
    TotG=uint8(Convfig{str2num(Cope)}); % 原始模型
    axes(handles.Net);
    imshow(TotG)
    hold on
    axes(handles.ObjFunction);
    TotG1=uint8(Myfig{str2num(Cope)}); % 改进模型
    imshow(TotG1)
    axes(handles.axes4);
    TotG2=uint8(TrFig{str2num(Cope)}); % 待检测模型
    imshow(TotG2)
    hold off
   end

function RecNum_Callback(hObject, eventdata, handles)

function RecNum_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

提取有用的代码并写可以转换的函数后的结果如下:

function [TotG, TotG1, TotG2]=t2(Cope)

oliver = coder.load('Oliver.mat'); 

Myfig = oliver.gRGB;
Convfig = oliver.gRGB1;
TrFig = oliver.gRGB2;

TotG=uint8(Convfig{Cope});
TotG1=uint8(Myfig{Cope});
TotG2=uint8(TrFig{Cope});

2 转换为C++

使用上一篇博文中提到的转换方法转换后,得到如下代码C++代码(由于我用CLion运行C++程序,而CLion使用CMake进行C++编译运行,所以添加了cmake-build-debug文件夹):

在这里插入图片描述

Matlab转换的成C++代码是无法直接运行,我们需要添加一些额外的Matlab库文件(例如mat.hmatrix.hmex.htmwtypes.hrtwtypes.h),这些文件是从Matlab的库中得到的,在Mac上的地址为/Applications/MATLAB_R2022a.app/extern/include/):

请添加图片描述

我们进入example/main.cpp文件中,这里是Matlab转换时自动写好的示例代码。其中最有用的函数部分的代码如下:

static double argInit_real_T()
{
  return 0.0;
}

static void main_dealImage()
{
  static unsigned char TotG[30912];
  static unsigned char TotG1[30912];
  static unsigned char TotG2[30912];
  // Initialize function 'dealImage' input arguments.
  // Call the entry-point 'dealImage'.
  dealImage(argInit_real_T(), TotG, TotG1, TotG2);
}

如果我们使用open cv 中的Mat构造函数接收unchar参数,那么显示出来的图像将只会是丢掉颜色信息的灰度图像,不会有彩色的图像(CV_8UC3:带有3个通道的8位无符号整数矩阵/图像;CV_8UC1:带有1个通道的8位无符号整数矩阵/图像)。

  uchar* data = TotG;
  //matlab中原矩阵为:112行,92列
  cv::Mat src(92, 112, CV_8UC1, data);//rect_height, rect_width
  imshow("image", src);
  cv::waitKey(0);

⚠️注意:这里传入Mat中的行、列信息和Matlab原数据相反的原因是因为,在MATLAB的二位数组(矩阵)的数据存放顺序默认为列优先(从第一列自上向下存放和访问,再第二列…),而c/c++数据存放顺序默认为行优先。

我们使用如下代码打印输入的数据:

  uchar* data = TotG2;
  int row = 112;//行
  int col = 92;//列
  for (int k = 0; k < 3; ++k) {
    for (int i = 0; i < col; ++i) {
      for (int j = 0; j < row; ++j) {
        std::cout<<(double)data[k*col*row + i*row + j]<<" ";
      }std::cout<<std::endl;
    }std::cout<<std::endl<<std::endl;
  }

数据对比:

matlab(1通道):
在这里插入图片描述

C++(打印出来的1通道):
在这里插入图片描述

matlab(3通道):
在这里插入图片描述

C++(打印出来的3通道):
在这里插入图片描述

CV_8UC1格式的图片显示:
在这里插入图片描述
CV_8UC3格式的图片显示:

在这里插入图片描述

出现这样问题的原因是因为:

  • 在opencv中图像的三通道是BGR(历史原因:早期在相机制造商和软件提供商中很流行),而在Matlab中图像的三通道是RGB,也就是调整接收到的三通道数据的顺序,才能使用CV_8UC3格式来显示图片。不然直接使用就会导致图像信息错乱,而使用CV_8UC1格式,虽然规避了图像信息错位的问题,但是丢失了另外两个通道的颜色信息,矩阵的行列信息也是相反,导致只能显示灰度图像。

我们使用如下方法进行三通道数据的处理(行列转置,三通道顺序调整,思路类似于下图):

在这里插入图片描述

cv::Mat array2cv(uchar* array){
  //int D = mxGetNumberOfDimensions(pic);		// 维度  mxArray* pic
  int M = 112;// mxGetM(pic);						// 行(高)
  int N = 92;//mxGetN(pic) / D;					// 列(宽)
  uchar* picReal = array;
  cv::Mat cvPic(M, N, CV_8UC3);

  for (int i = 0; i < M; i++)//行
  {
    uchar* pData = cvPic.ptr<uchar>(i);

    for (int j = 0; j < N; j++)//列
    {
      pData[3 * j + 0] = picReal[2 * M * N + j * M + i];
      pData[3 * j + 1] = picReal[1 * M * N + j * M + i];
      pData[3 * j + 2] = picReal[0 * M * N + j * M + i];
    }
  }
  return cvPic;
}

然后使用如下代码进行数据显示:

  cv::Mat src(112, 92, CV_8UC3, data);//rect_height, rect_width
  cv::imshow("image", array2cv(data));
  cv::waitKey(0);

3 使用纯C++实现mat数据中的图片显示

g1.cpp文件内容如下:

#include<opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>        //核心模块
#include <opencv2/highgui/highgui.hpp>  //GUI用户界面
#include <opencv2/imgproc/imgproc.hpp> // 图像处理
//using namespace cv;

#include "mat.h"//Matlab中的库

cv::Mat array2cv(mxArray* pic){
    int D = mxGetNumberOfDimensions(pic);		// 维度  mxArray* pic
    int M = mxGetM(pic);//112						// 行(高)
    int N = mxGetN(pic) / D;//92					// 列(宽)
    uchar* picReal = (uchar*)mxGetPr(pic);;
    cv::Mat cvPic(M, N, CV_8UC3);//rect_height, rect_width

    for (int i = 0; i < M; i++)
    {
        uchar* pData = cvPic.ptr<uchar>(i);

        for (int j = 0; j < N; j++)
        {
            pData[3 * j + 0] = picReal[2 * M * N + j * M + i];
            pData[3 * j + 1] = picReal[1 * M * N + j * M + i];
            pData[3 * j + 2] = picReal[0 * M * N + j * M + i];
        }
    }
    return cvPic;
}


void getMatInfo(const char* path, const char* variableName){
//    const char* path = "/Users/mac/CLionProjects/getMatInfo/Fig.mat";

    MATFile* pmatFile = matOpen(path, "r");

    if (pmatFile == NULL)
    {
        printf("mat数据读取失败!");
        return;
    }

    int ndir;
    const char** dir = (const char**)matGetDir(pmatFile, &ndir);

    mxArray* array = matGetVariable(pmatFile, dir[0]);//得到cell
    matClose(pmatFile);

    if (array == NULL)
    {
        printf("结构体中cell数据不存在!");
        return;
    }

    mxArray* pic1 = mxGetCell(array, 5);//得到图片
    imshow("image", array2cv(pic1));
    cv::waitKey(0);
    
}


int main() {
    const char *path = "/Users/mac/CLionProjects/getMatInfo/Oliver.mat";
    const char* variableName = "Myfig"; //FigData

    getMatInfo(path, variableName);
    
    return 0;
}

编译的CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.15)
project(getMatInfo)

set(CMAKE_CXX_STANDARD 11)

include_directories(${PROJECT_SOURCE_DIR})
include_directories(.)

# Matlab的动态链接库
LINK_LIBRARIES("/Applications/MATLAB_R2022a.app/bin/maci64/libeng.dylib"
        "/Applications/MATLAB_R2022a.app/bin/maci64/libmx.dylib"
        "/Applications/MATLAB_R2022a.app/bin/maci64/libmat.dylib"
        "/Applications/MATLAB_R2022a.app/bin/maci64/libmex.dylib")

#找到opencv的包
find_package(OpenCV REQUIRED)
include_directories( ${OpenCV_INCLUDE_DIRS})

# 根据的自己文件路径进行修改
add_executable(getMatInfo
        g1.cpp)
        
#动态链接
target_link_libraries(getMatInfo ${OpenCV_LIBS} )

4 代码封装

这里我们对方法进行封装成动态链接库(供Java或C++调用,主要是供Java调用),让其可以通过传入图片编号和文件存储路径,然后返回保存的图片路径。

头文件dealImage.h为(让编译器以处理 C 语言代码的方式来处理修饰的 C++ 代码。):

#ifndef DEALIMAGE_DEALMATLABDATA_H
#define DEALIMAGE_DEALMATLABDATA_H

#include "rtwtypes.h"
#include <cstddef>
#include <cstdlib>


extern "C"{
void main_dealImage(int index, const char* imgPath, char** saveImgPath);
};

#endif // DEALIMAGE_DEALMATLABDATA_H

源文件dealImage.cpp为(为了可以供Java调用,我们使用JNA来进行C++动态链接库的调用,我们返回的数据结构类型均为C的数据结构):

注意⚠️:
这里为了返回一个Java中的String[]的数据结构,我们C语句中的char**来存储返回的三张图片的保存路径。这里我们在方法中,申请了堆上的空间来初始化char**,如果直接使用传入的行参,而不自己申请空间,在Java调用动态链接库的时候,就会爆Java的垃圾回收异常。

#include "dealMatlabData.h"

#include "dealImage.h"

#include<opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>        //核心模块
#include <opencv2/highgui/highgui.hpp>  //GUI用户界面
#include <opencv2/imgproc/imgproc.hpp> // 图像处理

const int filePathLengthMax =  256;

char convfigStr[filePathLengthMax], myfigStr[filePathLengthMax], trFigStr[filePathLengthMax];

cv::Mat array2cv(uchar*);

cv::Mat array2cv(uchar* array){
  //int D = mxGetNumberOfDimensions(pic);		// 维度  mxArray* pic
  int M = 112;// mxGetM(pic);						// 行(高)
  int N = 92;//mxGetN(pic) / D;					// 列(宽)
  uchar* picReal = array;
  cv::Mat cvPic(M, N, CV_8UC3);

  for (int i = 0; i < M; i++)
  {
    uchar* pData = cvPic.ptr<uchar>(i);

    for (int j = 0; j < N; j++)
    {
      pData[3 * j + 0] = picReal[2 * M * N + j * M + i];
      pData[3 * j + 1] = picReal[1 * M * N + j * M + i];
      pData[3 * j + 2] = picReal[0 * M * N + j * M + i];
    }
  }
  return cvPic;
}


//
// Arguments    : void
// Return Type  : void
//
void main_dealImage(int index, const char* imgPath, char** saveImgPath)
{
  static unsigned char TotG[30912];
  static unsigned char TotG1[30912];
  static unsigned char TotG2[30912];
  //TotG=uint8(Convfig{Cope});% 原始模型
  //TotG1=uint8(Myfig{Cope}); % 改进模型
  //TotG2=uint8(TrFig{Cope}); %待检测模型


  // Initialize function 'dealImage' input arguments.
  // Call the entry-point 'dealImage'.
  dealImage(index, TotG, TotG1, TotG2);


  const char* convfigName = "convfig.jpg";
  const char* myfigName = "myfigfig.jpg";
  const char* trFigName = "trFig.jpg";

  sprintf(convfigStr,"%s%s",imgPath, convfigName);
  sprintf(myfigStr,"%s%s",imgPath, myfigName);
  sprintf(trFigStr,"%s%s",imgPath, trFigName);

  std::string convfigPath = convfigStr, myfigPath =myfigStr, trFigPath = trFigStr;

  cv::imwrite(convfigPath, array2cv(TotG));
  cv::imwrite(myfigPath, array2cv(TotG1));
  cv::imwrite(trFigPath, array2cv(TotG2));

  //char* saveImgPath[3] = {convfigStr, myfigStr, trFigStr};

//  char** saveImgPath  = (char **) malloc(sizeof(char**));
//  saveImgPath[0] = convfigStr;
//  saveImgPath[1] = myfigStr;
//  saveImgPath[2] = trFigStr;

//  char** saveImgPath = new char*[3];
//  char* saveImgPath[3];

  //封装成动态链接库时使用
  saveImgPath = new char *[3];
  for(int i = 0;i < 3;i++){
    saveImgPath[i] = new char[filePathLengthMax];
  }

    saveImgPath[0] = convfigStr;//% 原始模型
    saveImgPath[1] = myfigStr;//% 改进模型
    saveImgPath[2] = trFigStr;// %待检测模型
}

使用cmake动态链接库的方法如下:

(base) mac@macbook dealImage % rm -rf build
(base) mac@macbook dealImage % mkdir build
(base) mac@macbook dealImage % cd build
(base) mac@macbook build % cmake ..
(base) mac@macbook build % make
Scanning dependencies of target dealImage
[ 33%] Building CXX object CMakeFiles/dealImage.dir/dealImage.cpp.o
[ 66%] Building CXX object CMakeFiles/dealImage.dir/dealMatlabData.cpp.o
[100%] Linking CXX shared library libdealImage.dylib
[100%] Built target dealImage

5 福利

matlab原码、c++转换后代码的资源链接,提取码: riig

其他

由opencv的BGR引起的问题,可以让人联想到一些其他有趣的东西:
在这里插入图片描述
想学习C++或者Java调用动态链接库的,可以查看本博客的其他博文。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++改写Matlab源码实践一之【显示图片】——————附带详细讲解和示例 的相关文章

  • 图像增强 - 从书写中清除给定图像

    我需要清理这张照片 删除 清理我 的字样并使其变亮 作为图像处理课程作业的一部分 我可能会使用 matlab 函数 ginput 来查找图像中的特定点 当然 在脚本中您应该对所需的坐标进行硬编码 您可以使用 conv2 fft2 ifft2
  • 使用 java 执行 Matlab 函数

    我正在编写一个应用程序 它使用 matlab 进行图像处理 然后使用 Java 接口显示结果 由于某些原因 我必须同时使用 Java 和 Matlab 如何在java中使用matlab函数 如何创建和访问界面 MATLAB控制 http m
  • opencv中矩阵的超快中值(与matlab一样快)

    我正在 openCV 中编写一些代码 想要找到一个非常大的矩阵数组 单通道灰度 浮点数 的中值 我尝试了几种方法 例如对数组进行排序 使用 std sort 和选择中间条目 但与 matlab 中的中值函数相比 它非常慢 准确地说 在 ma
  • 这是 `min` 和 `nanmin` 之间的区别; Matlab 中的“max”和“nanmax”?

    Matlab描述nanmin and nanmax像这样 NANMIN最小值 忽略NaNs NANMAX最大值 忽略NaNs 但实际上 min and max ignore NaNs too 那我应该使用哪个 根据我的测试 nanmin a
  • 估算缺失数据,同时强制相关系数保持不变

    考虑以下 excel 数据集 m r 2 0 3 3 0 8 4 0 1 3 2 1 5 2 2 3 1 9 2 5 1 2 3 0 2 0 2 6 我的目标是使用以下条件填充缺失值 将上述两列之间的成对相关性表示为 R 大约 0 68 将
  • MATLAB:比较两个不同长度的数组

    我有两个长度不同的数组 由于采样率不同 需要比较 我想对较大的数组进行下采样以匹配较小的数组的长度 但是该因子不是整数而是小数 举个例子 a 1 1 375 1 75 2 125 2 5 2 875 3 25 b 1 2 3 有什么方法可以
  • 在 MATLAB 中定义其他中缀运算符

    有没有办法在 MATLAB 中定义额外的中缀运算符 具体来说 我想定义两个中缀运算符 gt and lt gt 这些符号是理想的 但如果需要 它可以是单个字符 它调用函数implies and iff以同样的方式 calls and and
  • 单元格的 Fieldnames 函数的等效项

    正如标题所说 只是想知道是否有一个函数可以用作字段名 http www mathworks co uk help matlab ref fieldnames html 但适用于单元格 所以如果我有类似的东西 a imread redsqua
  • 为什么 MATLAB 在打印大量 (.png) 图形时速度会变慢?

    我正在将大量数字打印为 png 文件 每个图都是数据矩阵中的一列图 我获取 png 文件并将它们串在一起形成动画 我的问题是 前几百张图像打印得很快 但创建每个新图形的时间却迅速增加 从前几百个 png 文件的约 0 2 秒到第 800 个
  • 如何加载具有可变文件名的 .mat 文件?

    select all mat files oar dir oar mat n oar name loop through files for l 1 length oar load pat oar l lt this is the mat
  • 在Matlab中选择图像上的像素时,索引指的是什么?

    当在Matlab中查看图像的单个像素时 该索引指的是什么 X Y 指的是像素的坐标 RGB 指的是颜色 但是关于索引是什么有什么想法吗 为了澄清一下 当我在 Matlab 中查看图形并使用数据光标选择一个点时 显示的三行是 X Y 指数 R
  • MATLAB 可执行文件太慢

    我使用以下命令将 MATLAB 程序转换为基于控制台的应用程序deploytool在 MATLAB 中 MATLAB m文件执行大约需要 2 秒 但在我将其转换为可执行文件并调用 exe 执行需要45秒 太长了 我想将 MATLAB 程序与
  • matlab部署工具到java包javac错误

    我正在尝试将我的程序包装为与 java 一起使用 我首先尝试了一个简单的 hello world 你好世界 m disp 你好世界 我使用了deploytool并选择了java包 当它到达这一行时 执行命令 javac verbose cl
  • Python 或 C 语言中的 Matlab / Octave bwdist()

    有谁知道 Matlab Octave bwdist 函数的 Python 替代品 此函数返回给定矩阵的每个单元格到最近的非零单元格的欧几里得距离 我看到了一个 Octave C 实现 一个纯 Matlab 实现 我想知道是否有人必须用 AN
  • 如何在Matlab中绘制网络?

    我有一个矩阵AMatlab中的维数mx2每行包含两个节点的标签 显示网络中的直接链接 例如 如果网络有4矩阵的节点A可能A 1 2 1 3 2 1 2 4 3 2 4 1 4 2 其中第一行表示有一个链接来自1 to 2 第二行表示有一个链
  • 如何在向量中的所有点之间绘制线?

    我有一个包含二维空间中一些点的向量 我希望 MATLAB 用从每个点到每个其他点绘制的线来绘制这些点 基本上 我想要一个所有顶点都连接的图 你能用情节来做到这一点吗 如果可以 怎么做 一种解决方案是使用该函数为每个点组合创建一组索引MESH
  • 命令 A(~A) 在 matlab 中的真正作用是什么

    我一直在寻找找到矩阵非零最小值的最有效方法 并在论坛上找到了这个 设数据为矩阵A A A nan minNonZero min A 这是非常短且高效的 至少在代码行数方面 但我不明白当我们这样做时会发生什么 我找不到任何关于此的文档 因为它
  • 以 2 为底的矩阵对数

    Logm 取矩阵对数 并且log2 取矩阵每个元素以 2 为底的对数 我正在尝试计算冯 诺依曼熵 它涉及以 2 为底的矩阵对数 我该怎么做呢 如果将 以 2 为底 的矩阵指数定义为B expm log 2 A 或者如果您类似地通过特征分解直
  • Matlab的导入函数的范围是什么?

    我正在尝试将一些用 Matlab 编写的代码转换为独立的 编译的 Matlab 应用程序 然而 在出现一些奇怪的错误之后 我意识到代码大量使用了从路径中添加和删除的操作 以避免多次使用多个具有相同名称 但结果 计算不同 的函数这一事实 环顾
  • 获取向量幂的有效方法

    我编写了一个代码 在数值上使用勒让德多项式直至某个高 n 阶 例如 case 8 p 6435 x 8 12012 x 6 6930 x 4 1260 x 2 35 128 return case 9 如果向量x太长这会变得很慢 我发现说之

随机推荐