OpenCV 学习探秘之三:从图像读取到特征识别,再到机器学习等函数接口的全面实战应用与解析

一、引言

1.1介绍

OpenCV(Open Source Computer Vision Library)是一个功能强大的开源计算机视觉库,广泛应用于图像和视频处理、目标检测、机器学习等领域。本文将全面解析 OpenCV 中常用的函数接口,帮助读者快速掌握 OpenCV 的核心功能。
本文将按照功能模块分类,详细介绍 OpenCV 中的各类函数接口,并提供丰富的 C++ 代码示例。内容涵盖图像读取与显示、图像处理、特征提取、视频处理、机器学习等多个方面。

1.2 准备

  • 开发环境:
    Qt5.14.2;OpenCV4.5.4
    附:点击下载本文所用例子中使用的OpenCV4.5.4版本编译好的库
  • 引入依赖库
INCLUDEPATH += "D:/opencv/opencv-4.5.4/build/include"
INCLUDEPATH += "D:/opencv/opencv-4.5.4/build/include/opencv2"
DEPENDPATH += "D:/opencv/opencv-4.5.4/build/x64/vc15/lib"
LIBS += "D:/opencv/opencv-4.5.4/build/x64/vc15/lib/opencv_world454d.lib"
  • 引入头文件
//引入opencv头文件和命名空间
#include <opencv.hpp>
using namespace cv;

附带说明:后面的特征提取如SURF算法等高阶调用,要依赖带有opencv_contrib模块的opencv库,并添加头文件

//引入头文件和命名空间,在opencv_contrib模块里
#include <opencv2/xfeatures2d.hpp>
using namespace cv::xfeatures2d;

二、OpenCV 基础:图像读取、显示与保存

2.1 图像读取:imread 函数

imread函数用于从文件中读取图像,支持多种图像格式,如 JPEG、PNG、BMP 等。

//图像读,显示,写
void MainWindow::on_bt1_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("无法读取图像!");return;}imshow(QString("TestSrc").toStdString(), image);// 修改图像(例如,转换为灰度图)Mat grayImage;cvtColor(image, grayImage, COLOR_BGR2GRAY);// 保存图像bool saved = imwrite("gray_test.jpg", grayImage);imshow(QString("TestDsc").toStdString(), grayImage);if (saved) {qDebug()  << QString("图像保存成功!");} else {qDebug()  << QString("图像保存失败!");}return;
}

imread函数的第二个参数是一个标志,指定图像的读取方式:

  • IMREAD_COLOR:读取彩色图像,忽略透明度(默认值);
  • IMREAD_GRAYSCALE:以灰度模式读取图像;
  • IMREAD_UNCHANGED:读取包含 Alpha 通道的图像

测试结果:
在这里插入图片描述

2.2 图像显示:imshow 和 namedWindow 函数

imshow函数用于在窗口中显示图像,而namedWindow函数用于创建一个窗口。

    QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// 创建窗口namedWindow(QString("TestSrc").toStdString(), WINDOW_AUTOSIZE); // 创建一个自动调整大小的窗口// 显示图像imshow(QString("TestSrc").toStdString(), image);// 等待按键事件waitKey(0); // 0表示无限等待,直到用户按下任意键return;
}

namedWindow函数的第二个参数可以是:

  • WINDOW_AUTOSIZE:窗口大小自动适应图像大小
  • WINDOW_NORMAL:窗口大小可手动调整

在这里插入图片描述

2.3 图像保存:imwrite 函数

imwrite函数用于将图像保存到文件中。

//测试写入
void MainWindow::on_bt3_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// 修改图像(例如,转换为灰度图)Mat grayImage;cvtColor(image, grayImage, COLOR_BGR2GRAY);// 保存图像bool saved = imwrite("gray_test.jpg", grayImage);if (saved) {qDebug()  << QString("图像保存成功!");} else {qDebug()  << QString("图像保存失败!");}return;
}

mwrite函数的第二个参数是要保存的图像,第三个参数是一个可选的参数向量,用于指定特定格式的保存选项。
在这里插入图片描述

三、图像处理:滤波、边缘检测与形态学操作

3.1 图像滤波:平滑与降噪

图像滤波是图像处理中常用的操作,用于平滑图像、降噪或增强特定特征。

3.1.1 均值滤波:blur 函数

均值滤波是一种简单的线性滤波方法,它用邻域内像素的平均值代替中心像素的值。

//均值滤波
void MainWindow::on_bt4_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// 均值滤波Mat blurredImage;blur(image, blurredImage, Size(5, 5)); // 5x5的均值滤波器// 显示原始图像和滤波后的图像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), blurredImage);waitKey(0);return;
}

在这里插入图片描述

3.1.2 高斯滤波:GaussianBlur 函数

高斯滤波是一种常用的线性滤波方法,它用高斯核来对图像进行卷积,能够有效抑制高斯噪声。

    QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// 高斯滤波Mat gaussianImage;GaussianBlur(image, gaussianImage, Size(5, 5), 0, 0); // 5x5的高斯滤波器// 显示原始图像和滤波后的图像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), gaussianImage);waitKey(0);return;
}

在这里插入图片描述

3.1.3 中值滤波:medianBlur 函数

中值滤波是一种非线性滤波方法,它用邻域内像素的中值代替中心像素的值,能够有效去除椒盐噪声。

//中值滤波
void MainWindow::on_bt6_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// 中值滤波Mat medianImage;medianBlur(image, medianImage, 5); // 5x5的中值滤波器// 显示原始图像和滤波后的图像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), medianImage);waitKey(0);return;
}
}

在这里插入图片描述

3.2 边缘检测

边缘检测是计算机视觉中的重要任务,用于识别图像中亮度变化明显的区域。

3.2.1 Canny 边缘检测:Canny 函数

Canny 边缘检测是一种多阶段的边缘检测算法,包括高斯平滑、梯度计算、非极大值抑制和双阈值处理。

//Canny边缘检测
void MainWindow::on_bt7_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// Canny边缘检测Mat edges;Canny(image, edges, 50, 150); // 低阈值50,高阈值150// 显示原始图像和处理后的图像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), edges);waitKey(0);return;
}

测试结果:
在这里插入图片描述

3.2.2 Sobel 边缘检测:Sobel 函数

Sobel 算子是一种常用的边缘检测算子,用于计算图像灰度函数的近似梯度。

// Sobel边缘检测
void MainWindow::on_bt8_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// Sobel边缘检测Mat sobelx, sobely, sobel;// 计算x和y方向的梯度Sobel(image, sobelx, CV_64F, 1, 0, 3);Sobel(image, sobely, CV_64F, 0, 1, 3);// 合并梯度convertScaleAbs(sobelx, sobelx);convertScaleAbs(sobely, sobely);addWeighted(sobelx, 0.5, sobely, 0.5, 0, sobel);// 显示原始图像和处理后的图像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), sobely);waitKey(0);return;
}

测试结果:
在这里插入图片描述

3.3 形态学操作

形态学操作是基于图像形状的一系列图像处理操作,主要包括腐蚀、膨胀、开运算和闭运算。

3.3.1 腐蚀:erode 函数

腐蚀操作会减小图像中的前景区域,常用于去除小的噪声点。

//腐蚀
void MainWindow::on_bt9_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// 创建结构元素Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));// 腐蚀操作Mat eroded;erode(image, eroded, element);// 显示原始图像和处理后的图像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), eroded);waitKey(0);return;
}

测试结果:
在这里插入图片描述

3.3.2 膨胀:dilate 函数

膨胀操作会增大图像中的前景区域,常用于连接断裂的物体。

//膨胀
void MainWindow::on_bt10_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// 创建结构元素Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));// 膨胀操作Mat dilated;dilate(image, dilated, element);// 显示原始图像和处理后的图像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), dilated);waitKey(0);return;
}

测试结果:
在这里插入图片描述

3.3.3 开运算和闭运算:morphologyEx 函数

开运算和闭运算都是复合操作,开运算先腐蚀后膨胀,闭运算先膨胀后腐蚀。

//开闭运算
void MainWindow::on_bt12_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// 创建结构元素Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));// 开运算Mat opened;morphologyEx(image, opened, MORPH_OPEN, element);// 闭运算Mat closed;morphologyEx(image, closed, MORPH_CLOSE, element);// 显示原始图像和处理后的图像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_Open").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_Close").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc_Open").toStdString(), opened);imshow(QString("Dsc_Close").toStdString(), closed);waitKey(0);return;
}

测试结果如下:
在这里插入图片描述

四、颜色空间转换与操作

4.1 颜色空间转换:cvtColor 函数

cvtColor函数用于在不同颜色空间之间进行转换,如 BGR 到灰度、BGR 到 HSV 等。

//颜色转换
void MainWindow::on_bt13_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// BGR到灰度Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);// BGR到HSVMat hsv;cvtColor(image, hsv, COLOR_BGR2HSV);// 显示原始图像和处理后的图像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_Gray").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_HSV").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc_Gray").toStdString(), gray);imshow(QString("Dsc_HSV").toStdString(), hsv);waitKey(0);return;}

测试结果显示:
在这里插入图片描述

4.2 颜色分割:inRange 函数

inRange函数用于在图像中找到特定颜色范围的区域,常用于颜色分割。

//颜色分割
void MainWindow::on_bt14_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件对话框"),"E:/test/QtTest/WidgetTest/TestOpencv/bin/debug64/Out/OutImg/",QString("图片(*.jpg *.png);"));// 读取图像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug()  << QString("无法读取图像!");return;}// 转换到HSV颜色空间Mat hsv;cvtColor(image, hsv, COLOR_BGR2HSV);// 定义蓝色的HSV范围Scalar lower_blue = Scalar(100, 150, 0);Scalar upper_blue = Scalar(140, 255, 255);// 创建掩码Mat mask;inRange(hsv, lower_blue, upper_blue, mask);// 应用掩码Mat result;bitwise_and(image, image, result, mask);// 显示原始图像和处理后的图像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_Mask").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_Result").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc_Mask").toStdString(), mask);imshow(QString("Dsc_Result").toStdString(), result);waitKey(0);return;
}

运行结果如下:
在这里插入图片描述
OK,以上通过十几个示例代码展示了OpenCV图像读写及一些基本变换的应用,由于篇幅有限,下一篇,再将一些实际应用比如角点检测,特征提取,人脸检测等功能演示出来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/91180.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/91180.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Umi从零搭建Ant Design Pro项目(3)集成 openapi 插件

1. 安装插件 pnpm add umijs/max-plugin-openapi pnpm add swagger-ui-dist如果不安装swagger-ui-dist&#xff0c;不会影响运行。但会报错。 2.配置文件export default defineConfig({// umi插件配置plugins: [umijs/max-plugin-openapi],// openAPI配置openAPI: {requestLibP…

Flutter开发实战之状态管理深入解析

第4章:状态管理深入解析 前言 想象一下,你正在开发一个购物车应用。用户在商品页面添加商品,然后去购物车页面查看,最后到结算页面付款。在这个过程中,购物车的数据需要在多个页面之间保持同步和一致。这就是状态管理要解决的核心问题。 状态管理是Flutter开发中最重要…

组件化(一):重新思考“组件”:状态、视图和逻辑的“最佳”分离实践

组件化(一)&#xff1a;重新思考“组件”&#xff1a;状态、视图和逻辑的“最佳”分离实践 引子&#xff1a;组件的“内忧”与“外患” 至此&#xff0c;我们的前端内功修炼之旅已经硕果累累。我们掌握了组件化的架构思想&#xff0c;拥有了高效的渲染引擎&#xff0c;还探索…

【Redis】Redis 协议与连接

一、Redis 协议 1.1 RESP RESP 是 Redis 客户端与服务器之间的通信协议&#xff0c;采用文本格式&#xff08;基于 ASCII 字符&#xff09;&#xff0c;支持多种数据类型的序列化和反序列化 RESP 通过首字符区分数据类型&#xff0c;主要支持 5 种类型&#xff1a; 类型首字…

Android通知(Notification)全面解析:从基础到高级应用

一、Android通知概述通知(Notification)是Android系统中用于在应用之外向用户传递信息的重要机制。当应用需要告知用户某些事件或信息时&#xff0c;可以通过通知在状态栏显示图标&#xff0c;用户下拉通知栏即可查看详细信息。这种机制几乎被所有现代应用采用&#xff0c;用于…

VUE3(四)、组件通信

1、props作用&#xff1a;子组件之间的通信。父传子&#xff1a;属性值的非函数。子传父&#xff1a;属性值是函数。父组件&#xff1a;<template><div>{{ childeData }}</div>——————————————————————————————<child :pare…

【数据结构与算法】数据结构初阶:详解二叉树(六)——二叉树应用:二叉树选择题

&#x1f525;个人主页&#xff1a;艾莉丝努力练剑 ❄专栏传送门&#xff1a;《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题 &#x1f349;学习方向&#xff1a;C/C方向 ⭐️人生格言&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为…

Android广播实验

【实验目的】了解使用Intent进行组件通信的原理&#xff1b;了解Intent过滤器的原理和匹配机制&#xff1b;掌握发送和接收广播的方法【实验内容】任务1、普通广播&#xff1b;任务2、系统广播&#xff1b;任务3、有序广播&#xff1b;【实验要求】1、练习使用静态方法和动态方…

html转word下载

一、插件使用//转html为wordnpm i html-docx-js //保存文件到本地npm i file-saver 注&#xff1a;vite 项目使用esm模式会报错&#xff0c;with方法错误&#xff0c;修改如下&#xff1a;//直接安装修复版本npm i html-docx-fixed二、封装导出 exportWord.jsimport htmlDocx f…

北方公司面试记录

避免被开盒&#xff0c;先称之为“北方公司”&#xff0c;有确定结果后再更名。 先说流程&#xff0c;线下面试&#xff0c;时间非常急&#xff0c;下午两点钟面试&#xff0c;中午十二点打电话让我去&#xff0c;带两份纸质简历。 和一般的菌工单位一样&#xff0c;先在传达室…

linux——ps命令

PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND0 1 1 1 ? -1 Ss 0 0:01 /usr/lib/systemd/systemd1 123 123 123 ? -1 S 0 0:00 /usr/sbin/sshd -D123 456 456 456 pts/0 456 R 10…

C#.NET 依赖注入详解

一、是什么 在 C#.NET 中&#xff0c;依赖注入&#xff08;Dependency Injection&#xff0c;简称 DI&#xff09; 是一种设计模式&#xff0c;用于实现控制反转&#xff08;Inversion of Control&#xff0c;IoC&#xff09;&#xff0c;以降低代码耦合、提高可测试性和可维护…

Vue监视数据的原理和set()的使用

在 Vue 中&#xff0c;Vue.set()&#xff08;或 this.$set()&#xff09;是用于解决响应式数据更新检测的重要方法&#xff0c;其底层与 Vue 的数据监视原理紧密相关。以下从使用场景和实现原理两方面详细说明&#xff1a;一、Vue.set () 的使用场景与用法1. 为什么需要 Vue.se…

在 Vue 中,如何在回调函数中正确使用 this?

在 Vue 组件中&#xff0c;this 指向当前组件实例&#xff0c;但在回调函数&#xff08;如定时器、异步请求、事件监听等&#xff09;中&#xff0c;this 的指向可能会丢失或改变&#xff0c;导致无法正确访问组件的属性和方法。以下是在回调函数中正确使用 this 的几种常见方式…

第4章唯一ID生成器——4.4 基于数据库的自增主键的趋势递增的唯一ID

基于数据库的自增主键也可以生成趋势递增的唯一 ID&#xff0c;且由于唯一ID不与时间戳关联&#xff0c;所以不会受到时钟回拨问题的影响。 4.4.1 分库分表架构 数据库一般都支持设置自增主键的初始值和自增步长&#xff0c;以MySQL为例&#xff0c;自增主键的自增步长由auto_i…

设计模式:Memento 模式详解

Memento 模式详解Memento&#xff08;备忘录&#xff09;模式是一种行为型设计模式&#xff0c;用于在不破坏封装性的前提下&#xff0c;捕获并外部化一个对象的内部状态&#xff0c;以便在之后能够将该对象恢复到原先保存的状态。它广泛应用于需要实现撤销&#xff08;Undo&am…

数据结构(6)单链表算法题(下)

一、环形链表Ⅰ 1、题目描述 https://leetcode.cn/problems/linked-list-cycle 2、算法分析 思路&#xff1a;快慢指针 根据上图所示的流程&#xff0c;我们可以推测出这样一个结论&#xff1a;若链表带环&#xff0c;快慢指针一定会相遇。 那么&#xff0c;这个猜测是否正…

智能制造,从工厂建模,工艺建模,柔性制造,精益制造,生产管控,库存,质量等多方面讲述智能制造的落地方案。

智能制造&#xff0c;从工厂建模&#xff0c;工艺建模&#xff0c;柔性制造&#xff0c;精益制造&#xff0c;生产管控&#xff0c;库存&#xff0c;质量等多方面讲述智能制造的落地方案。

Qt 分裂布局:QSplitter 使用指南

在 GUI 开发中&#xff0c;高效管理窗口空间是提升用户体验的关键。QSplitter 作为 Qt 的核心布局组件&#xff0c;让动态分割窗口变得简单直观。一、QSplitter 核心功能解析 QSplitter 是 Qt 提供的布局管理器&#xff0c;专用于创建可调节的分割区域&#xff1a; 支持水平/垂…

R语言与作物模型(DSSAT模型)技术应用

R语言在DSSAT模型的气候、土壤、管理措施等数据准备&#xff0c;自动化模拟和结果分析上都发挥着重要的作用。一&#xff1a;DSSAT模型的高级应用 1.作物模型的概念 2.DSSAT模型发展现状 3.DSSAT与R语言的安装 4.DSSAT模型的高级应用案例 5.R语言在作物模型参数优化中的应用 6.…