目录
摘 要 Ⅰ
ABstract Ⅱ
第一章 绪论 1
1.1选题背景和意义 1
1.2 国内外研究现状 2
1.2.1 国内外云技术与深度学习研究现状 2
1.2.2 国内外深度学习在作物害虫识别的研究现状 4
1.2.3 国内外智慧农业的行业发展现状 5
1.3 研究目标和内容 7
1.3.1 研究目标 7
1.3.2 研究内容 7
1.4 技术路线图 8
1.5 论文组织结构 9
第二章 数据收集与数据处理 10
2.1 数据获取 10
2.1.1 试验数据获取 10
2.1.2 负样本数据获取 11
2.2 数据处理 12
2.2.1 总体方案 12
2.2.2 视觉显著性 13
2.3 本章小结 17
第三章 深度学习的云训练 17
3.1 深度学习卷积神经网络 17
3.1.1 卷积神经网络概念 17
3.1.2 网络结构 17
3.1.3 超参数 20
3.2 深度学习模型 23
3.2.1 Inception-V3模型 23
3.2.2 MobileNet-V2模型 24
3.2.3 ResNet-50-v2模型 26
3.3 模型训练 27
3.3.1 概述 27
3.3.2 训练思路 28
3.3.3 基于云计算的迁移学习 28
3.4 精度检验 31
3.4.1 正样本检验 31
3.4.2 负样本检验 35
3.4.3 确定模型与阈值 37
3.5 本章小结 40
第四章 需求分析与系统设计 40
4.1 需求分析 40
4.1.1 总体需求分析 41
4.1.2 用户需求分析 41
4.1.3 性能需求分析 42
4.2 系统架构设计 43
4.2.1 客户端识别系统总体设计 43
4.2.2 云服务端系统总体设计 44
4.3 系统功能设计 44
4.4 云服务设计 45
4.4.1 云服务技术概念 45
4.4.2深度学习模型的云部署 47
4.5 性能优化设计 52
4.5.1 Nginx 52
4.5.2 反向代理 53
4.5.3 均衡负载 55
4.6本章小结 57
第五章 客户端系统构建 57
5.1系统开发环境 57
5.1.1 硬件环境 57
5.1.2 软件环境 57
5.1.3 网络环境 58
5.2 首页模块 58
5.3 识别模块 60
5.3.1 拍摄图像、选择图像功能 62
5.3.2 正样本识别结果 63
5.3.3 负样本识别结果 64
5.4百科模块 65
5.5 本章小结 68
第六章 结论与展望 68
6.1 结论 68
6.2 不足与展望 69
参考文献 71
致谢 74
1.3 研究目标和内容
1.3.1 研究目标
根据1.2.3节国内外研究现状可见,农业与AI互联网技术的结合为大势所趋。但高昂的资金成本和较高的技术门槛,阻了碍智能技术在农业领域应用,基于此,提出了以下三点研究目标:
(1)探索出基于云计算对作物害虫数据进行深度学习模型训练的方法,降低智能技术使用门槛和弱化算力垄断。
(2)基于云服务部署农作物害虫识别深度学习模型并提供Restful API服务,大幅降低对用户硬件水平的依赖。
(3)建立一套渐进式Web识别系统,支持跨系统、跨平台访问,提高受众范围的同时降低开发维护成本。
1.3.2 研究内容
本文主要从深度学习技术与云计算技术促进智慧农业发展为出发点,以提供一套完整的开源、便捷、实用、高兼容、低成本的农作物害虫识别技术方案为目标,展开一系列的研究。具体研究内容如下:
(1) 建立高质量农作物害虫数据库的研究。在经过网络爬虫,数据库下载、实地拍摄等方法收集到害虫图像数据后,除了传统的人工筛选清洗数据以外,还基于视觉显著性理论,选定GBVS和GrabCut方法对数据集进行批量分割处理,提高数据集的质量。
(2) 利用云计算与深度学习技术训练高精度害虫识别模型的研究。使用Inception-V3、MobileNet-V2和ResNet-50-V2三种算法作为研究模型,基于TensorFlow框架在Google Colab云服务器上训练,并使用交叉检验和负样本检验对模型进行筛选,使模型的正负样本精度都达到可落地应用的标准。
(3) 使用云服务部署深度学习模型的研究。基于阿里云服务器ECS , Docker容器技术和TensorFlow Serving镜像,部署深度学习模型,以提供可跨平台访问的restful API。
(4) 开发一套Web端作物害虫识别系统,并支持跨平台、跨系统的无差别访问。基于JS,Vue、TensorFlow和OpenCV等框架技术,实现一个网页端的作物害虫智能识别系统,提供给所有操作系统的用户使用,降低开发与维护成本。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>识别图片</title>
<style>
body {
text-align: center;
}
</style>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0" rel="external nofollow"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.0/dist/css/bootstrap.min.css"
integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<div style="margin: 0 auto;text-align: center;">
<!--异步加载 opencv.js,如果成功,'网站加载中..'则会显示“welcome”的内容-->
<div>
<img src="./logo.png" alt="xiaohui" style="margin-top: 40px;">
<!-- <img src="./1605604007.png" alt="" style="height: 100px;width: 100px;"> -->
<h2 id="status" style="margin-top: 20px;">网站加载中...</h2>
</div>
<!--图片读入区域-->
<div class="InputOutput">
<div class="caption">
<input type="file" id="inputFile" name="file" accept="image/*" />
</div>
<img id="srcImg" alt="" style="visibility: hidden;position: absolute;left: 0;" />
</div>
<!--结果展示区域-->
<div class="InputOutput" style="margin-top: 20px;">
<canvas id="dstImg"></canvas>
<div class="spinner-border text-success" role="status" id="wait_circle"
style="visibility: hidden;display: block;margin: 0 auto;">
<span class="sr-only">Loading...</span>
</div>
<div id="results"></div>
</div>
</div>
<script type="text/javascript">
function picStandard(data) {
return (data / 255.0) - 1;
}
// predict函数
function predict() {
// 通过js获取图像数据
let canvas_obj = document.getElementById("dstImg");
let ctx = canvas_obj.getContext("2d");
let imgData_obj = ctx.getImageData(0, 0, canvas_obj.width, canvas_obj.height);
let imgData = imgData_obj.data;
console.log(imgData);
// 将获取到的图像数据去除A通道
let imgArr = [];
for (let i = 0; i < imgData.length; i += 4) {
//imgArr.push( imgData[i], imgData[i + 1], imgData[i + 2])
imgArr.push(picStandard(imgData[i]), picStandard(imgData[i + 1]), picStandard(imgData[i + 2]))
}
// 将js数组转化为tensor数据,并reshape
let imgMat = tf.tensor(imgArr);
let img = imgMat.reshape([224, 224, 3]);
//let url_tf = 'http://localhost/v1/models/incV3:predict';//nginx转发
let url_tf = 'http://39.106.225.96/predict';
let img_list = img.arraySync();
//console.log(img_list);
//sequential_5_input inception_v3_input
let data_tf = JSON.stringify(
{ 'inputs': [img_list] }
)
let res_div = $('#results');
$.ajax({
type: 'post',
url: url_tf,
data: data_tf,
beforeSend: function () {
$('#wait_circle').css('visibility', 'visible');
res_div.empty();
},
success: function (responseText) {
$('#wait_circle').css('visibility', 'hidden');
//const tag = ['aleyrodidae', 'aphididae', 'arctiinae', 'bombyx', 'buprestida', 'cicadellidae', 'coccid', 'cossidae', 'cricket', 'curculionidae', 'cutworm', 'eucleid', 'fulgoridae', 'grub', 'gryllotalpidae', 'inchworm', 'lasiocampidae', 'limax', 'lycaenidae', 'lymantriid', 'millipede', 'noctuidae', 'notodontidae', 'nymphalidae', 'papilionidae', 'pierid', 'platypodidae', 'psychid', 'pyralidid', 'sawfly', 'scarab', 'snail', 'sphingidae', 'termite', 'tetranychidae', 'thripidae', 'tianniu', 'tingidae', 'tortricidae', 'wireworm', 'zygaenidae'];
const tag = [
'白粉虱', '蚜虫', '夜蛾科', '刺蛾', '蜡蝉科',
'蛴螬', '蝼蛄科', '尺蠖(huò)', '枯叶蛾科', '蛞蝓(kuò yú)属',
'灰蝶科', '毒蛾', '灯蛾亚科', '千足虫', '夜蛾科',
'舟蛾科', '蛱蝶科', '凤蝶科', '粉蝶', '长小蠢(chǔn)科',
'蓑蛾', '螟蛾', '叶蜂', '蚕', '金龟子',
'蜗牛', '天蛾科', '白蚁', '蜱螨', '蓟(jì)马科',
'天牛', '网蝽科', '卷蛾科', '铁线虫', '吉丁虫科',
'斑蛾科', '叶蝉科', '介壳虫', '木蠹(dù)蛾科', '蟋蟀',
'象甲科'
];
const tag_en = [
'aleyrodidae', 'aphididae', 'cutworm', 'eucleid', 'fulgoridae',
'grub', 'gryllotalpidae', 'inchworm', 'lasiocampidae', 'limax',
'lycaenidae', 'lymantriid', 'arctiinae', 'millipede', 'noctuidae',
'notodontidae', 'nymphalidae', 'papilionidae', 'pierid', 'platypodidae',
'psychid', 'pyralidid', 'sawfly', 'bombyx', 'scarab',
'snail', 'sphingidae', 'termite', 'tetranychidae', 'thripidae',
'tianniu', 'tingidae', 'tortricidae', 'wireworm', 'buprestida',
'zygaenidae', 'cicadellidae', 'coccid', 'cossidae', 'cricket',
'curculionidae'
];
let rec_result = responseText.outputs[0];
let kv_result = {};
let index_result = [];
res_div.empty();
for (let index = 0; index < rec_result.length; index++) {
const prob = parseFloat(rec_result[index].toFixed(5)) //保留五位小数
if (prob > 0.05) {
kv_result[prob] = index;
index_result.push(prob);
}
}
index_result.sort().reverse(); //可能性降序
//如果最大的可能性小于0.5,则代表可能没有虫
if (index_result[0] < 0.52) {
let results = `<p style="color: crimson;">图片中未检测到农业害虫😕,以下结果仅作参考</p>`;
res_div.append(results);
}
const index_result_length = index_result.length;
for (let index = 0; index < index_result_length; index++) {
const sort_prob = index_result[index];
const element = kv_result[sort_prob];
let results = `
<div style="float:left;border:2px solid skyblue;margin:10px;padding:10px;">
<img src="./showPics/${tag_en[element]}.jpg" style="display: block;margin-left: 20px;height:100px;width:100px;margin:auto"/>
<span>名称:${tag[element]} 可能性:${(sort_prob * 100).toFixed(3)}%</span>
</div>`;
res_div.append(results);
}
}
});
}
let imgElement = document.getElementById("srcImg");
let fileElement = document.getElementById("inputFile");
let s = 1;
let timer = document.getElementById('mytime');
fileElement.addEventListener("change",
(e) => { imgElement.src = URL.createObjectURL(e.target.files[0]); },
false);
//resize
imgElement.onload = function () {
let src = cv.imread(imgElement);
let dst = new cv.Mat();
let dsize = new cv.Size(224, 224);
cv.resize(src, dst, dsize, 0, 0, cv.INTER_AREA);
cv.imshow('dstImg', dst);
src.delete();
predict();
};
function onOpenCvReady() {
$("#status").html('<p>welcome to 农作物害虫识别系统</p>')
}
</script>
<script async src="https://cdn.jsdelivr.net/gh/wallat/compiled-opencvjs/v4.2.0/opencv.js" onload="onOpenCvReady();"
type="text/javascript">
</script>
</body>
</html>















这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总
深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我