毕设 基于机器视觉的害虫种类及数量检测(源码+论文)


0 项目说明

基于机器视觉的害虫种类及数量检测

提示:适合用于课程设计或毕业设计,工作量达标,源码开放


1 研究目的

研究的目的在于建立一套远程病虫害自动识别系统,有助于缓解农业植保人员和病虫害鉴定专家的人力资源紧张,有助于病虫害知识有限的农业人员进行及时的病虫害检测,并且,通过害虫种类数目的监测和信息收集,定期对昆虫数据进行整理和分析,建立病虫害爆发的规律模型,进而预测判断病虫害爆发的时间,及时通知农业植物保护人员和农户进行合理地科学地预防。提高农作物产量和质量。

2 研究内容及结论

(1) 设计实现了一套可适用于野外的害虫捕获和图像采集装置。该装置放置在农业种植区域,24 小时进行害虫的诱杀和图像采集,同时,装置可以通过无线网络将害虫图像上传至农业监控中心虫类鉴别服务器,并进行害虫种类的识别,进行产区内害虫种类数目的信息收集。

(2) 开发了一套基于机器视觉的昆虫计数工作方法。开发了一套的适用于苍蝇粘板等包含多数昆虫设备的图像的基于机器视觉的昆虫计数工作方法。该方法首先对包含多数昆虫的图片进行二值化预处理,然后进行轮廓的查找,并进行轮廓的计数,得到的数目反映了图片中的昆虫数目的数量级。该方法适用于苍蝇粘板图像等包含多数昆虫虫体的图像上。

(3) 开发了一套基于机器视觉的昆虫识别工作方法和流程。该方法在参考已有研究成果的基础山,选取了昆虫形态特征中的昆虫矩形度、昆虫延长度、昆虫圆形度、昆虫球状性、昆虫叶状性等 5 个特征,进行昆虫图像的特征提取。之后,采用逻辑斯蒂回归模型、线性 SVM 模型和 K 邻近分类器分别进行训练,并测试比较训练结果,以进行分类器算法的筛选。该方法适用于本套图像采集装置。

(4) 设计了一套远程害虫自动识别系统。结合上述三个功能,该系统可以实现:在图像采集节点进行害虫捕获和昆虫图像采集,在虫类鉴别服务器进行昆虫图像的识别和分类。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3 文件介绍

用户界面
MainWindow.ui———————–PyQtDesigner设计的主界面文件
MainWindow.py———————-PyUIC转换而成的主界面程序

运行逻辑
VideoMainWindow.py————–PyQt结合OpenCV实现在界面中显示视频画面
PreProcess.py————————-对源数据样本进行预处理

特征提取
P_circle.py——————————似圆度
P_extend.py—————————-延长度
P_leaf.py——————————–叶状性
P_rect.py——————————–矩形度
P_spherical.py————————球形度
GetFeatures.py———————–提取特征的模块
GetFiveFeatures.py—————–五个特征提取的测试代码
FeatureExtract.py——————-提取样本库特征保存到CSV文件

机器学习模块
LinearSVM.py————————-线性SVM分类器的训练和模型保存
LinearRegression.py—————逻辑回归分类器的训练和模型保存
KneiborsClassfier.py—————KNN分类器的训练和模型保存
Predict.py——————————加载预训练模型,对特征进行预测
Thresholding.py—————————大津法程序实现和OpenCV大津法函数的效果对比
Count.py————————————-实现加载图片,二值化(大津法),查找轮廓进行计数的效果
GetChineseName.py——————–分类中英文转换

4 论文目录

摘 要 
ABSTRACT 
目 录 
第 1 章 绪论 
1.1 课题研究的背景和意义
1.2 国内外研究现状 
1.2.1 国内研究现状 
1.2.2 国外研究现状 
1.3 研究的内容和目的
1.3.1 研究内容 
1.3.2 研究目的 
1.4 章节安排 
第 2 章 系统总体设计 
2.1 系统设计目标 
2.2 系统总体架构 
2.3 图像采集节点 
2.3.1 装置总体设计 
2.3.2 运行流程 
2.4 虫类鉴别服务器和虫类信息数据库设计
2.4.1 服务器设计 
2.4.2 服务器虫类分类器实现 
2.4.3 PC 上的昆虫分类识别软件 
第 3 章 昆虫图像预处理与计数研究
3.1 昆虫图像的采集 
3.2 昆虫图像的预处理 
III3.2.1 图像的灰度化,高斯滤波和尺度变换
3.2.2 二值化 
3.2.3 大津法 OTSU 在昆虫图像二值化上的应用 
3.3 昆虫图像的计数
3.3.1 检测轮廓 
3.3.2 昆虫计数 
第 4 章 昆虫图像特征提取与识别研究 
4.1 特征的选取 
4.2 特征描述以及提取方式
4.3 分类器的选择和训练
4.4 机器学习结果分析 
4.4.1 性能评价指标 
4.4.2 三种分类器的性能比较 
第 5 章 总结与展望 
5.1 总结 
5.1.1 完成的工作
5.1.2 创新点和不足之处 
5.2 展望 
致谢

5 项目源码

# coding=utf-8
# 先读图,然后二值化,
# 延长度

import cv2
import math
import numpy as np
from matplotlib import pyplot as plt

#  此处读入图片,作为接口
origin = cv2.imread('dataset/fly6.jpg')
grayimage = cv2.imread('dataset/fly6.jpg', 0)

#  高斯滤波
blur = cv2.GaussianBlur(grayimage, (5, 5), 0)

#  二值化:用大津法,此处选项若是THRESH_BINARY_INV,则同意选用白色背景的图片样本
ret, otsu = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 找轮廓
contours = cv2.findContours(otsu, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 轮廓集数目

largest_area = 0
largest_contour_index = 0
num = len(contours[1])
for i in range(num):
    area = cv2.contourArea(contours[1][i], False)
    if area > largest_area:
        largest_area = area
        largest_contour_index = i

maxContour = contours[1][largest_contour_index]
# 画轮廓
cv2.drawContours(origin, maxContour, -1, (0, 0, 255), 2)
print "最大面积" + str(largest_area)

# 质心计算
M = cv2.moments(maxContour)
Centroid_x = int(M['m10'] / M['m00'])
Centroid_y = int(M['m01'] / M['m00'])
print "质心" + str(Centroid_x) + " " + str(Centroid_y)
cv2.circle(origin, (Centroid_x, Centroid_y), 8, (255, 255, 255), -1)

# 获取长轴
Major_Axis_Length = 0
Major_Axis_Angle = 0
Major_Axis_End_x = 0
Major_Axis_End_y = 0
Major_Axis_Begin_x = 0
Major_Axis_Begin_y = 0

# 此处需要注意质心是否在轮廓内
# 找长轴
for angle in range(180):
    theta = angle * 3.14 / 180.0
    lengthBackward = 0
    lengthForward = 0
    point_End_x = Centroid_x
    point_End_y = Centroid_y
    point_Begin_x = Centroid_x
    point_Begin_y = Centroid_y

    # 步进越小准确率越高,设置成1可以先找到准确的直线角度,再根据角度和质心得到的直线计算出正确的长轴和轮廓交点
    while cv2.pointPolygonTest(maxContour, (point_End_x, point_End_y), False) > 0:
        lengthForward = lengthForward + 0.1
        point_End_x = int(round(point_End_x + lengthForward * math.cos(theta)))
        point_End_y = int(round(point_End_y + lengthForward * math.sin(theta)))

    while cv2.pointPolygonTest(maxContour, (point_Begin_x, point_Begin_y), False) > 0:
        lengthBackward = lengthBackward + 0.1
        point_Begin_x = int(round(point_Begin_x - lengthBackward * math.cos(theta)))
        point_Begin_y = int(round(point_Begin_y - lengthBackward * math.sin(theta)))

    if lengthForward + lengthBackward >= Major_Axis_Length:
        Major_Axis_Length = lengthForward + lengthBackward
        Major_Axis_Angle = angle
        Major_Axis_End_x = point_End_x
        Major_Axis_End_y = point_End_y
        Major_Axis_Begin_x = point_Begin_x
        Major_Axis_Begin_y = point_Begin_y

# 计算实际长轴长度
Real_Major_Axis_Length = math.sqrt(
    math.pow((Major_Axis_End_x - Major_Axis_Begin_x), 2) + math.pow((Major_Axis_End_y - Major_Axis_Begin_y), 2))

Real_Major_Axis_Length = round(Real_Major_Axis_Length, 1)
print "长轴长度 = " + str(Real_Major_Axis_Length)
print "长轴角度 = " + str(Major_Axis_Angle)
# print "起点 = " + "x: " + str(Major_Axis_Begin_x) + "  y: " + str(Major_Axis_Begin_y)
# print "起点 = " + "x: " + str(Major_Axis_End_x) + "  y: " + str(Major_Axis_End_y)

# 画长轴
cv2.line(origin, (Major_Axis_Begin_x, Major_Axis_Begin_y), (Major_Axis_End_x, Major_Axis_End_y), (255, 0, 0), 2)

# 找短轴
# 1. 先得到长轴直线的表达式y=k*x+b,用来计算点到直线距离和判断点在直线上方还是下方
Major_Axis_k = math.tan(Major_Axis_Angle * 3.14 / 180.0)
Major_Axis_b = Centroid_y - Major_Axis_k * Centroid_x

# 2. 点(x0,y0)到直线(Ax+By+C=0)的距离为d =abs (A*x0+B*y0+C)/sqrt(A^2+B^2)
Minor_Axis_A = Major_Axis_k
Minor_Axis_B = -1
Minor_Axis_C = Major_Axis_b

# 3. 遍历轮廓上的点
Minor_Axis_Under_length = 0
Minor_Axis_Above_length = 0
Minor_Axis_Under_End_x = 0
Minor_Axis_Under_End_y = 0
Minor_Axis_Above_End_x = 0
Minor_Axis_Above_End_y = 0

# 轮廓点集
ContourItems = maxContour.shape[0]
for item in range(ContourItems):
    point_x = maxContour[item][0][0]
    point_y = maxContour[item][0][1]
    # 判断点在直线哪一侧
    # 上侧
    if point_y > int(Major_Axis_k * point_x + Major_Axis_b):
        # 点到直线距离
        dis = abs((Minor_Axis_A * point_x + Minor_Axis_B * point_y + Minor_Axis_C) / math.sqrt(
            Minor_Axis_A * Minor_Axis_A + Minor_Axis_B * Minor_Axis_B))
        if dis >= Minor_Axis_Above_length:
            Minor_Axis_Above_length = dis
            Minor_Axis_Above_End_x = point_x
            Minor_Axis_Above_End_y = point_y
    # 下侧
    elif point_y < int(Major_Axis_k * point_x + Major_Axis_b):
        # 点到直线距离
        dis = abs((Minor_Axis_A * point_x + Minor_Axis_B * point_y + Minor_Axis_C) / math.sqrt(
            Minor_Axis_A * Minor_Axis_A + Minor_Axis_B * Minor_Axis_B))
        if dis >= Minor_Axis_Under_length:
            Minor_Axis_Under_length = dis
            Minor_Axis_Under_End_x = point_x
            Minor_Axis_Under_End_y = point_y
            # 第三种可能就是轮廓与直线的交点

# # 标记两个点,可以忽略
cv2.circle(origin, (Minor_Axis_Above_End_x, Minor_Axis_Above_End_y), 4, (255, 255, 255), -1)
cv2.circle(origin, (Minor_Axis_Under_End_x, Minor_Axis_Under_End_y), 4, (255, 255, 255), -1)
# 画出两点直线
cv2.line(origin, (Minor_Axis_Under_End_x, Minor_Axis_Under_End_y), (Minor_Axis_Above_End_x, Minor_Axis_Above_End_y),
         (0, 255, 255), 3)

# 计算实际短轴长度
Real_Minor_Axis_Length = math.sqrt(
    math.pow((Minor_Axis_Above_End_x - Minor_Axis_Under_End_x), 2) + math.pow(
        (Minor_Axis_Above_End_y - Minor_Axis_Under_End_y), 2))

Real_Minor_Axis_Length = round(Real_Minor_Axis_Length, 1)
print "短轴长度 = " + str(Real_Minor_Axis_Length)

P_extend = Real_Minor_Axis_Length * 1.0 / Real_Major_Axis_Length
P_extend = round(P_extend, 3)

print "延长度 = " + str(P_extend)
# 画出与长轴距离最远的两点的辅助线,使用时可以不用,画图用作论文使用
# 画出长轴右方
line_above_k = math.tan((Major_Axis_Angle - 90) * 3.14 / 180.0)
line_above_b = Minor_Axis_Above_End_y - line_above_k * Minor_Axis_Above_End_x
Minor_Axis_Above_Begin_x = int((line_above_b - Major_Axis_b) / (Major_Axis_k - line_above_k))
Minor_Axis_Above_Begin_y = int(line_above_k * Minor_Axis_Above_Begin_x + line_above_b)
cv2.line(origin, (Minor_Axis_Above_Begin_x, Minor_Axis_Above_Begin_y), (Minor_Axis_Above_End_x, Minor_Axis_Above_End_y),
         (255, 0, 255), 3)

line_under_k = math.tan((Major_Axis_Angle - 90) * 3.14 / 180.0)
line_under_b = Minor_Axis_Under_End_y - line_under_k * Minor_Axis_Under_End_x
Minor_Axis_Under_Begin_x = int((line_under_b - Major_Axis_b) / (Major_Axis_k - line_under_k))
Minor_Axis_Under_Begin_y = int(line_under_k * Minor_Axis_Under_Begin_x + line_under_b)
cv2.line(origin, (Minor_Axis_Under_Begin_x, Minor_Axis_Under_Begin_y), (Minor_Axis_Under_End_x, Minor_Axis_Under_End_y),
         (255, 255, 0), 3)


cv2.putText(origin, 'Major_Axis : ' + str(Real_Major_Axis_Length), (280, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 155), 2, cv2.LINE_AA)
cv2.putText(origin, 'Minor_Axis : ' + str(Real_Minor_Axis_Length), (280, 85), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 155), 2, cv2.LINE_AA)
cv2.putText(origin, 'P_Rect: ' + str(P_extend), (280, 120), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 155), 2, cv2.LINE_AA)


# 显示
cv2.namedWindow('Butterfly', cv2.WINDOW_AUTOSIZE)
cv2.imshow('Butterfly', origin)
cv2.imwrite('picture/p-extend.png',origin)

k = cv2.waitKey(0)

# 'ESC'
if k == 27:
    cv2.destroyAllWindows()

6 最后

**项目分享: ** https://gitee.com/asoonis/htw

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值