news 2026/4/15 3:44:29

基于作物生长图像,识别病虫害,输出病虫害类型和防治建议。

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于作物生长图像,识别病虫害,输出病虫害类型和防治建议。

基于图像识别的作物病虫害智能诊断与防治系统

实际应用场景描述

在现代农业生产中,病虫害是影响作物产量和品质的主要因素之一。传统病虫害识别依赖农技专家现场观察,效率低、成本高,且易受专家经验水平影响。许多农民由于缺乏专业知识,往往无法及时准确识别病虫害,导致错失最佳防治时机,造成严重经济损失。

痛点分析

1. 识别难度大:病虫害种类繁多,症状相似,非专业人士难以准确识别

2. 响应不及时:从发现症状到专家诊断周期长,病虫害可能已扩散

3. 防治不精准:盲目用药导致成本增加、环境污染和农药残留

4. 知识获取难:防治知识分散,农民难以获取权威指导

核心逻辑

1. 使用深度学习模型对作物图像进行特征提取

2. 基于提取特征进行病虫害分类

3. 根据病虫害类型匹配防治知识库

4. 输出诊断结果和个性化防治建议

系统架构

├── app.py # 主应用程序

├── config.py # 配置文件

├── models/

│ ├── disease_detector.py # 病虫害检测模型

│ └── classifier.py # 分类器

├── utils/

│ ├── image_processor.py # 图像处理工具

│ └── knowledge_base.py # 知识库模块

├── static/ # 静态资源

├── templates/ # HTML模板

└── README.md # 说明文档

核心代码实现

1. 配置文件 (config.py)

"""

配置文件 - 系统参数和路径配置

"""

import os

from pathlib import Path

class Config:

"""系统配置类"""

# 基础配置

BASE_DIR = Path(__file__).parent

UPLOAD_FOLDER = BASE_DIR / 'static' / 'uploads'

ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'bmp'}

# 模型配置

MODEL_PATH = BASE_DIR / 'models' / 'pretrained' / 'plant_disease_model.h5'

CLASS_NAMES = [

'healthy', # 健康

'powdery_mildew', # 白粉病

'leaf_spot', # 叶斑病

'aphid_infestation', # 蚜虫侵害

'caterpillar_damage', # 毛虫损害

'fungal_infection', # 真菌感染

'nutrient_deficiency' # 营养缺乏

]

# 图像处理参数

IMG_SIZE = (224, 224) # 模型输入尺寸

# 知识库配置

KNOWLEDGE_BASE_FILE = BASE_DIR / 'data' / 'disease_knowledge.json'

@classmethod

def init_directories(cls):

"""初始化必要的目录"""

directories = [cls.UPLOAD_FOLDER]

for directory in directories:

directory.mkdir(parents=True, exist_ok=True)

2. 图像处理器 (utils/image_processor.py)

"""

图像处理模块 - 负责图像预处理和增强

"""

import cv2

import numpy as np

from PIL import Image

import io

class ImageProcessor:

"""图像处理工具类"""

def __init__(self, img_size=(224, 224)):

"""

初始化图像处理器

参数:

img_size: 目标图像尺寸 (宽, 高)

"""

self.img_size = img_size

def load_image(self, image_path):

"""

加载并预处理图像

参数:

image_path: 图像路径或图像字节

返回:

processed_image: 预处理后的图像

"""

# 判断输入类型

if isinstance(image_path, (bytes, bytearray)):

# 从字节流加载

image = Image.open(io.BytesIO(image_path))

image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)

else:

# 从文件路径加载

image = cv2.imread(str(image_path))

if image is None:

raise ValueError("无法加载图像")

return image

def preprocess(self, image):

"""

图像预处理流程

参数:

image: 输入图像

返回:

processed: 预处理后的图像数组

"""

# 1. 调整尺寸

image = cv2.resize(image, self.img_size)

# 2. 颜色空间转换 (BGR -> RGB)

image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 3. 归一化

image = image.astype('float32') / 255.0

# 4. 数据增强(可选)

# 这里可以添加旋转、翻转等增强操作

return image

def extract_features(self, image):

"""

提取图像特征(替代深度学习模型的简化版本)

实际应用中应该使用CNN模型提取特征

参数:

image: 预处理后的图像

返回:

features: 特征向量

"""

# 颜色特征

mean_color = np.mean(image, axis=(0, 1))

# 纹理特征(使用灰度图的LBP简化版)

gray = cv2.cvtColor((image * 255).astype('uint8'), cv2.COLOR_RGB2GRAY)

hist = cv2.calcHist([gray], [0], None, [256], [0, 256])

hist = hist.flatten() / hist.sum() # 归一化

# 形状特征(边缘检测)

edges = cv2.Canny(gray, 100, 200)

edge_density = np.sum(edges > 0) / edges.size

# 组合特征

features = np.concatenate([

mean_color, # 3维

hist[:10], # 取前10个直方图bin

[edge_density] # 1维

])

return features

def diagnose_plant_health(self, image):

"""

基于传统图像处理的植物健康诊断(辅助方法)

参数:

image: 输入图像

返回:

health_metrics: 健康指标

"""

# 转换为HSV颜色空间

hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# 定义健康叶片的颜色范围(绿色)

lower_green = np.array([25, 40, 40])

upper_green = np.array([90, 255, 255])

# 创建掩码

mask = cv2.inRange(hsv, lower_green, upper_green)

# 计算绿色区域比例

green_ratio = np.sum(mask > 0) / mask.size

# 计算颜色变化(病害通常导致颜色变化)

std_color = np.std(image, axis=(0, 1)).mean()

return {

'green_ratio': green_ratio,

'color_variation': std_color,

'is_likely_healthy': green_ratio > 0.3

}

3. 知识库模块 (utils/knowledge_base.py)

"""

知识库模块 - 存储和管理病虫害防治知识

"""

import json

from pathlib import Path

from typing import Dict, List, Optional

class DiseaseKnowledgeBase:

"""病虫害知识库管理类"""

def __init__(self, knowledge_base_file: Path):

"""

初始化知识库

参数:

knowledge_base_file: 知识库文件路径

"""

self.knowledge_base_file = knowledge_base_file

self.knowledge = self._load_knowledge_base()

def _load_knowledge_base(self) -> Dict:

"""

加载知识库数据

返回:

知识库字典

"""

if not self.knowledge_base_file.exists():

# 如果文件不存在,创建默认知识库

return self._create_default_knowledge_base()

with open(self.knowledge_base_file, 'r', encoding='utf-8') as f:

return json.load(f)

def _create_default_knowledge_base(self) -> Dict:

"""

创建默认病虫害知识库

返回:

默认知识库数据

"""

knowledge_base = {

"diseases": {

"healthy": {

"name": "健康植株",

"description": "作物生长状况良好,无明显病虫害症状。",

"symptoms": [

"叶片颜色鲜绿均匀",

"植株生长健壮",

"无异常斑点或虫害痕迹"

],

"prevention": [

"保持合理种植密度",

"定期检查植株健康状况",

"保持良好通风透光"

],

"treatment": "无需特别处理,维持正常管理即可。"

},

"powdery_mildew": {

"name": "白粉病",

"description": "由白粉菌引起的真菌性病害,在叶片表面形成白色粉末状霉层。",

"symptoms": [

"叶片表面白色粉末状霉层",

"叶片褪绿、黄化",

"严重时叶片卷曲、干枯"

],

"prevention": [

"选择抗病品种",

"合理密植,保持通风透光",

"避免过量施用氮肥"

],

"treatment": "使用三唑酮、甲基托布津等药剂喷雾防治,7-10天一次,连续2-3次。"

},

"leaf_spot": {

"name": "叶斑病",

"description": "由真菌或细菌引起的叶片斑点类病害。",

"symptoms": [

"叶片出现圆形或不规则形病斑",

"病斑中心灰白色,边缘褐色",

"严重时病斑连片,叶片枯死"

],

"prevention": [

"及时清除病残体",

"实行轮作制度",

"避免田间积水"

],

"treatment": "使用代森锰锌、多菌灵等药剂防治,注意交替用药。"

},

"aphid_infestation": {

"name": "蚜虫侵害",

"description": "蚜虫吸食植物汁液,传播病毒病,分泌蜜露诱发煤污病。",

"symptoms": [

"叶片卷曲、畸形",

"植株生长迟缓",

"叶片有蜜露分泌物"

],

"prevention": [

"设置黄色粘虫板",

"保护利用天敌(瓢虫、草蛉)",

"及时清除杂草"

],

"treatment": "使用吡虫啉、噻虫嗪等内吸性药剂喷雾防治。"

},

"caterpillar_damage": {

"name": "毛虫损害",

"description": "鳞翅目幼虫取食叶片,造成缺刻或孔洞。",

"symptoms": [

"叶片有缺刻、孔洞",

"叶缘被取食",

"有虫粪残留"

],

"prevention": [

"人工捕捉幼虫",

"使用杀虫灯诱杀成虫",

"清洁田园,减少虫源"

],

"treatment": "使用高效氯氟氰菊酯、阿维菌素等药剂防治。"

}

},

"general_advice": {

"monitoring": "定期检查植株,早发现早防治。",

"prevention": "以预防为主,综合防治。",

"environment": "保持适宜的生长环境,增强植株抗性。"

}

}

# 保存默认知识库

self.save_knowledge_base(knowledge_base)

return knowledge_base

def save_knowledge_base(self, knowledge_data: Dict = None):

"""

保存知识库到文件

参数:

knowledge_data: 知识库数据,为None时保存当前知识库

"""

if knowledge_data is None:

knowledge_data = self.knowledge

with open(self.knowledge_base_file, 'w', encoding='utf-8') as f:

json.dump(knowledge_data, f, ensure_ascii=False, indent=2)

def get_disease_info(self, disease_id: str) -> Optional[Dict]:

"""

获取特定病虫害的详细信息

参数:

disease_id: 病虫害ID

返回:

病虫害信息字典,如果不存在则返回None

"""

return self.knowledge["diseases"].get(disease_id)

def get_prevention_advice(self, disease_id: str) -> List[str]:

"""

获取病虫害预防建议

参数:

disease_id: 病虫害ID

返回:

预防建议列表

"""

disease_info = self.get_disease_info(disease_id)

if disease_info:

return disease_info.get("prevention", [])

return []

def get_treatment_plan(self, disease_id: str) -> str:

"""

获取病虫害治疗方案

参数:

disease_id: 病虫害ID

返回:

治疗方案文本

"""

disease_info = self.get_disease_info(disease_id)

if disease_info:

return disease_info.get("treatment", "暂无具体治疗方案")

return "未知病虫害类型"

def search_by_symptom(self, symptom: str) -> List[Dict]:

"""

根据症状搜索可能的病虫害

参数:

symptom: 症状描述

返回:

匹配的病虫害列表

"""

results = []

for disease_id, info in self.knowledge["diseases"].items():

symptoms = info.get("symptoms", [])

# 简单关键词匹配

if any(symptom.lower() in s.lower() for s in symptoms):

results.append({

"disease_id": disease_id,

"name": info["name"],

"match_symptoms": [s for s in symptoms if symptom.lower() in s.lower()]

})

return results

4. 病害检测模型 (models/disease_detector.py)

"""

病害检测模型 - 基于机器学习的病虫害分类器

"""

import numpy as np

from typing import Dict, Tuple, List

from sklearn.ensemble import RandomForestClassifier

from sklearn.preprocessing import StandardScaler

import joblib

import os

class PlantDiseaseDetector:

"""植物病害检测器"""

def __init__(self, model_path: str = None):

"""

初始化病害检测器

参数:

model_path: 预训练模型路径

"""

self.model = None

self.scaler = StandardScaler()

self.classes = None

self.model_path = model_path

if model_path and os.path.exists(model_path):

self.load_model(model_path)

else:

# 初始化一个简单的随机森林模型

self.model = RandomForestClassifier(

n_estimators=100,

max_depth=10,

random_state=42

)

def train(self, X_train: np.ndarray, y_train: np.ndarray):

"""

训练模型

参数:

X_train: 训练特征

y_train: 训练标签

"""

# 数据标准化

X_train_scaled = self.scaler.fit_transform(X_train)

# 训练模型

self.model.fit(X_train_scaled, y_train)

self.classes = self.model.classes_

# 计算训练准确率

train_accuracy = self.model.score(X_train_scaled, y_train)

print(f"模型训练完成,训练准确率: {train_accuracy:.2f}")

# 保存模型

if self.model_path:

self.save_model(self.model_path)

def predict(self, features: np.ndarray) -> Tuple[str, float]:

"""

预测病虫害类型

参数:

features: 图像特征向量

返回:

tuple: (预测类别, 置信度)

"""

if self.model is None:

raise ValueError("模型未训练或加载")

# 数据标准化

features_scaled = self.scaler.transform(features.reshape(1, -1))

# 预测

probabilities = self.model.predict_proba(features_scaled)[0]

predicted_class_idx = np.argmax(probabilities)

confidence = probabilities[predicted_class_idx]

if self.classes is not None:

predicted_class = self.classes[predicted_class_idx]

else:

predicted_class = str(predicted_class_idx)

return predicted_class, float(confidence)

def predict_with_analysis(self, features: np.ndarray, image_metrics: Dict) -> Dict:

"""

带分析的预测方法

参数:

features: 图像特征

image_metrics: 图像健康指标

返回:

包含详细分析的预测结果

"""

# 基础预测

disease_class, confidence = self.predict(features)

# 基于图像指标进行后处理

if image_metrics.get('is_likely_healthy', False) and confidence < 0.7:

# 如果图像看起来很健康且置信度不高,倾向于判断为健康

if disease_class != 'healthy':

disease_class = 'healthy'

confidence = 0.8 # 调整置信度

return {

'disease_class': disease_class,

'confidence': confidence,

'health_metrics': image_metrics,

'features_used': len(features)

}

def save_model(self, path: str):

"""

保存模型

参数:

path: 模型保存路径

"""

model_data = {

'model': self.model,

'scaler': self.scaler,

'classes': self.classes

}

joblib.dump(model_data, path)

print(f"模型已保存到: {path}")

def load_model(self, path: str):

"""

加载模型

参数:

path: 模型路径

"""

model_data = joblib.load(path)

self.model = model_data['model']

self.scaler = model_data['scaler']

self.classes = model_data['classes']

print(f"模型已从 {path} 加载")

def get_feature_importance(self) -> np.ndarray:

"""

获取特征重要性

返回:

特征重要性数组

"""

if self.model is None:

raise ValueError("模型未训练或加载")

return self.model.feature_importances_

5. 主应用程序 (app.py)

"""

主应用程序 - 病虫害识别系统Web界面

"""

from flask import Flask, render_template, request, jsonify, send_file

import os

from datetime import datetime

import base64

from PIL import Image

import io

from config import Config

from utils.image_processor import ImageProcessor

from models.disease_detector import PlantDiseaseDetector

from utils.knowledge_base import DiseaseKnowledgeBase

# 初始化配置

Config.init_directories()

# 创建Flask应用

app = Flask(__name__)

app.config['UPLOAD_FOLDER'] = Config.UPLOAD_FOLDER

app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB限制

# 初始化各模块

image_processor = ImageProcessor(img_size=Config.IMG_SIZE)

knowledge_base = DiseaseKnowledgeBase(Config.KNOWLEDGE_BASE_FILE)

# 初始化/加载模型

detector = PlantDiseaseDetector()

# 模拟训练数据(实际应用中应该从数据集加载)

def create_training_data():

"""创建模拟训练数据(仅用于演示)"""

# 在实际应用中,这里应该从真实数据集中加载

# 这里使用随机数据模拟

import numpy as np

np.random.seed(42)

n_samples = 100

n_features = 14 # 与ImageProcessor中提取的特征数量一致

# 生成模拟特征

X_train = np.random.randn(n_samples, n_features)

# 生成模拟标签

n_classes = len(Config.CLASS_NAMES)

y_train = np.random.randint(0, n_classes, n_samples)

return X_train, y_train

# 训练模型(实际应用中应该使用预训练模型)

X_train, y_train = create_training_data()

detector.train(X_train, y_train)

@app.route('/')

def index():

"""首页"""

return render_template('index.html')

@app.route('/upload', methods=['POST'])

def upload_image():

"""处理图像上传"""

if 'file' not in request.files:

return jsonify({'error': '没有文件上传'}), 400

file = request.files['file']

if file.filename == '':

return jsonify({'error': '未选择文件'}), 400

if file and allowed_file(file.filename):

# 生成唯一文件名

timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')

filename = f"{timestamp}_{file.filename}"

filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)

# 保存文件

file.save(filepath)

# 处理图像

try:

result = process_image(filepath)

return jsonify(result)

except Exception as e:

return jsonify({'error': f'图像处理失败: {str(e)}'}), 500

return jsonify({'error': '不支持的文件类型'}), 400

@app.route('/analyze_base64', methods=['POST'])

def analyze_base64():

"""处理base64图像数据"""

data = request.json

if not data or 'image' not in data:

return jsonify({'error': '没有图像数据'}), 400

try:

# 解码base64图像

image_data = base64.b64decode(data['image'].split(',')[1])

# 处理图像

result = process_image_bytes(image_data)

return jsonify(result)

except Exception as e:

return jsonify({'error': f'图像分析失败: {str(e)}'}), 500

def allowed_file(filename):

"""检查文件类型是否允许"""

return '.' in filename and \

filename.rsplit('.', 1)[1].lower() in Config.ALLOWED_EXTENSIONS

def process_image(image_path):

"""处理图像文件"""

# 1. 加载和处理图像

image = image_processor.load_image(image_path)

# 2. 预处理图像

processed_image = image_processor.preprocess(image)

# 3. 提取特征

features = image_processor.extract_features(processed_image)

# 4. 获取健康指标

health_metrics = image_processor.diagnose_plant_health(image)

# 5. 预测病虫害

prediction_result = detector.predict_with_analysis(features, health_metrics)

# 6. 获取防治建议

disease_info = knowledge_base.get_disease_info(prediction_result['disease_class'])

if not disease_info:

disease_info = {

'name': '未知病虫害',

'description': '无法识别该病虫害类型',

'treatment': '请咨询专业农技人员'

}

# 准备结果

result = {

'status': 'success',

'prediction': {

'disease_class': prediction_result['disease_class'],

'disease_name': disease_info['name'],

'confidence': prediction_result['confidence'],

'description': disease_info['description']

},

'recommendations': {

'treatment': disease_info.get('treatment', ''),

'prevention': disease_info.get('prevention', []),

'symptoms': disease_info.get('symptoms', [])

},

'health_metrics': prediction_result['health_metrics'],

'image_info': {

'path': image_path,

'size': f"{image.shape[1]}x{image.shape[0]}"

}

}

return result

def process_image_bytes(image_bytes):

"""处理字节流图像"""

# 直接从字节流处理

image = image_processor.load_image(image_bytes)

processed_image = image_processor.preprocess(image)

features = image_processor.extract_features(processed_image)

health_metrics = image_processor.diagnose_plant_health(image)

prediction_result = detector.predict_with_analysis(features, health_metrics)

disease_info = knowledge_base.get_disease_info(prediction_result['disease_class'])

如果你觉得这个工具好用,欢迎关注我!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 3:43:01

WuWa-Mod模组安装配置完全手册:新手到高手的进阶指南

WuWa-Mod模组安装配置完全手册&#xff1a;新手到高手的进阶指南 【免费下载链接】wuwa-mod Wuthering Waves pak mods 项目地址: https://gitcode.com/GitHub_Trending/wu/wuwa-mod 想要在《鸣潮》游戏中获得超凡体验&#xff1f;WuWa-Mod模组为你提供全方位的游戏功能…

作者头像 李华
网站建设 2026/4/13 10:49:58

从平面到立体:钣金设计中的折叠智慧

在现代工业制造领域&#xff0c;从精密的电子产品外壳到稳固的机柜、汽车车身部件&#xff0c;钣金件的身影无处不在。这些看似由多个复杂曲面构成的立体产品&#xff0c;其诞生之初&#xff0c;往往只是一张平整的二维金属板材。实现这一神奇转变的核心&#xff0c;便是专业的…

作者头像 李华
网站建设 2026/4/9 1:59:50

NETSTAT零基础入门:看懂每一列数据的含义

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 制作一个交互式NETSTAT学习应用&#xff0c;包含&#xff1a;1. 命令参数解释器 2. 输出字段可视化说明(悬浮提示) 3. 常见问题解答库 4. 模拟练习环境 5. 知识测试题。使用HTMLJa…

作者头像 李华
网站建设 2026/3/30 18:58:07

一行命令生成日志异常分析报告:Python 生产可用实战(含源码)

你是不是也遇到过&#xff1a; 线上出问题&#xff0c;日志一大堆&#xff0c;靠人肉 grep想统计“最常见异常 / 最频繁报错模块 / 报错时间分布”想把结果发给同事/领导&#xff0c;但复制粘贴太丑 这篇我给你一个生产可用的小工具&#xff1a; ✅ 支持大日志&#xff08;流式…

作者头像 李华
网站建设 2026/4/14 5:14:07

3步突破:海尔智能家居接入HomeAssistant的实战秘诀

3步突破&#xff1a;海尔智能家居接入HomeAssistant的实战秘诀 【免费下载链接】haier 项目地址: https://gitcode.com/gh_mirrors/ha/haier 你是否曾经为了控制家里的海尔设备而需要在多个APP之间切换&#xff1f;是否想要将海尔空调、热水器等设备统一集成到智能家居…

作者头像 李华
网站建设 2026/4/4 11:22:59

GIF动画制作新境界:gifski技术深度解析与实战应用

GIF动画制作新境界&#xff1a;gifski技术深度解析与实战应用 【免费下载链接】gifski GIF encoder based on libimagequant (pngquant). Squeezes maximum possible quality from the awful GIF format. 项目地址: https://gitcode.com/gh_mirrors/gif/gifski 在现代数…

作者头像 李华