目录
摘 要 Ⅰ
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/[email protected]" rel="external nofollow"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/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('welcome to 农作物害虫识别系统
')
}
</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>