【Intel校企合作课程】基于ResNet50的杂草检测

2024-03-20 14:30

本文主要是介绍【Intel校企合作课程】基于ResNet50的杂草检测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


目录

  • 1.项目简介
    • 1.1项目描述
    • 1.2数据集展示
    • 1.3部分图像展示
    • 1.4预期处理方案
  • 2.数据预处理
    • 2.1 数据集结构
    • 2.2数据集提取
    • 2.3构建数据集
  • 3.使用ResNet50残差神经网络识别杂草
    • 3.1ResNet网络简介
    • 3.2ResNet50网络模型简介
    • 3.3查看Pytorch提供的ResNet50模型
    • 3.3自己定义ResNet50网络模型
    • 3.4使用Pytorch提供的ResNet50预训练模型进行训练
    • 3.5使用OneAPI组件进行加速
  • 4.模型训练(迭代二十次)
  • 5.计算推理时间和二分类准确度(F1分数)
  • 6.模型预测
  • 7.OneAPI组件的使用
  • 8.项目总结

1.项目简介

1.1项目描述

杂草是农业经营中不受欢迎的入侵者,它们通过窃取营养、水、土地和其他关键资源来破坏种植,这些入侵者会导致产量下降和资源部署效率低下。一种已知的方法是使用杀虫剂来清除杂草,但杀虫剂会给人类带来健康风险。我们的目标是利用计算机视觉技术可以自动检测杂草的存在,开发一种只在杂草上而不是在作物上喷洒农药的系统,并使用针对性的修复技术将其从田地中清除,从而最小化杂草对环境的负面影响。

1.2数据集展示

数据集链接:https://filerepo.idzcn.com/hack2023/Weed_Detection5a431d7.zip

1.3部分图像展示

杂草图像:
在这里插入图片描述
标签:1 0.508789 0.489258 0.869141 0.861328
作物图像:
在这里插入图片描述
标签:0 0.478516 0.560547 0.847656 0.625000

1.4预期处理方案

我们期待您将其部署到模拟的生产环境中——这里推理时间和二分类准确度(F1分数)将作为评分的主要依据。

2.数据预处理

2.1 数据集结构

本项目数据集共由两部分组成,分别包含文件夹data和classes.txt。
在这里插入图片描述

data文件夹下包含了杂草和作物的图像以及它们的标签数据,如果标签是1开头则它就是杂草是0开头为作物。
在这里插入图片描述

2.2数据集提取

将文件名写入data.txt中:

# 指定图片所在的文件夹路径
image_folder = '../Weed_detection/data'# 获取文件夹下所有以.jpeg结尾的文件
image_files = [f for f in os.listdir(image_folder) if f.endswith('.jpeg') ]# 提取文件名的前缀并保存到data.txt
with open('../Weed_detection/data.txt', 'w') as file:for filename in image_files:# 获取文件名的前缀prefix = os.path.splitext(filename)[0]# 写入前缀到data.txt文件file.write(prefix + '\n')

提取部分结果展示:
在这里插入图片描述
对图片数据进行预处理,并将处理后的数据分为训练集和测试集。

transformer = transforms.Compose([transforms.ToTensor(),transforms.ColorJitter(contrast=0.5),  # 增强对比度transforms.Normalize(mean=[0.5], std=[0.5])  # 归一化
])train_images_tensor = []
with open(r'../Weed_detection/data.txt','r') as f:file_name_url=[i.split('\n')[0] for i in f.readlines()]
for i in range(len(file_name_url)):image = Image.open('../Weed_detection/data/'+file_name_url[i]+'.jpeg')tensor = transformer(image.convert('L')).type(torch.float16)train_images_tensor.append(tensor)
image_train = []
image_test = []
for i in range(len(train_images_tensor)):if i <=len(train_images_tensor)*0.7:image_train.append(train_images_tensor[i])else:image_test.append(train_images_tensor[i])优化代码

读取文本文件中的标签数据,并将其转换为PyTorch张量格式,最后将数据分为训练集和测试集。

transformerlab = transforms.Compose([transforms.ToTensor()
])train_lables_tensor = []
with open(r'../Weed_detection/data.txt','r') as f:file_name_url=[i.split('\n')[0] for i in f.readlines()]
train_lables_tensor = []for i in range(len(file_name_url)):image = open('../Weed_detection/data/' + file_name_url[i] + '.txt')labels = image.readline()[0]labels = float(labels)tensor = torch.tensor(labels, dtype=torch.float16)  # 使用float16数据类型train_lables_tensor.append(tensor)lables_train = []
lables_test = []
for i in range(len(train_lables_tensor)):if i <=len(train_lables_tensor)*0.7:lables_train.append(train_lables_tensor[i])else:lables_test.append(train_lables_tensor[i])

2.3构建数据集

rain_datas_tensor = torch.stack(image_train)
train_labels_tensor = torch.stack(lables_train)
test_datas_tensor = torch.stack(image_test)
test_labels_tensor = torch.stack(lables_test)
train_dataset = TensorDataset(train_labels_tensor, train_datas_tensor)
train_dataloader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_dataset = TensorDataset(test_labels_tensor, test_datas_tensor)
test_dataloader = DataLoader(test_dataset, batch_size=32, shuffle=True)

3.使用ResNet50残差神经网络识别杂草

3.1ResNet网络简介

残差连接通常以跳跃连接的形式实现,即将某一层的输出直接连接到下一层的输入。通过这种方式,网络的每一层都可以得到其输入和上一层输出的组合,从而增加了网络的非线性表达能力。如下图所示,假设输入图像为 x,输出为H(x),中间经过卷积之后的输出为F(x)的非线性函数,那最终的输出为H(x) = F(x) + x,这样的输出仍然可以进行非线性变换,残差指的是“差”,也就是F(x),而网络也就转化为求残差函数F(x) = H(x) - x,这样残差函数要比 F(x) = H (x) 更加容易优化。残差神经网络具有易于优化、能够有效训练深层的优点,因此在计算机视觉、自然语言处理等领域得到了广泛应用。
在这里插入图片描述

3.2ResNet50网络模型简介

如下图所展示的网络模型所示,ResNet50网络总共有50层分别是49层卷积层和1层全连接层。网络的输入是224x224x3,经过前面5部分的卷积计算可以得到7x7x2048,因为全连接层的输入不能直接是多维图像所以要将其转化为一个一维的特征向量,最后分类器对这个特征向量进行计算并输出类别的概率。
在这里插入图片描述

3.3查看Pytorch提供的ResNet50模型

model = models.resnet50(pretrained=True)
model.eval() # 设置模型为评估模式  # 打印模型结构  
print(model)

残差网络结构:输入➡ 卷积层 ➡ 标准化层 ➡ 激活层 ➡ 最大池化层 ➡ 4个残差网络模块 ➡ 全局平均池化层 ➡ 全连接层 ➡输出
Pytorch提供的ResNet50网络结构:
在这里插入图片描述
卷积层:
卷积层
标准化层:
在这里插入图片描述
激活层:
在这里插入图片描述
最大池化层:
在这里插入图片描述
Stage1有3个残差块:
在这里插入图片描述
Stage2有4个残差块:
在这里插入图片描述
在这里插入图片描述
Stage3有6个残差块:
在这里插入图片描述
在这里插入图片描述
Stage4有3个残差块:
在这里插入图片描述
全局平均池化层:
在这里插入图片描述
全连接层:
在这里插入图片描述

3.3自己定义ResNet50网络模型

import torch  
import torch.nn as nn  
import torch.nn.functional as F  class BasicBlock(nn.Module):  expansion = 1  def __init__(self, in_channels, out_channels, stride=1):  super(BasicBlock, self).__init__()  self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)  self.bn1 = nn.BatchNorm2d(out_channels)  self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)  self.bn2 = nn.BatchNorm2d(out_channels)  self.shortcut = nn.Sequential()  if stride != 1 or in_channels != self.expansion*out_channels:  self.shortcut = nn.Sequential(  nn.Conv2d(in_channels, self.expansion*out_channels, kernel_size=1, stride=stride, bias=False),  nn.BatchNorm2d(self.expansion*out_channels)  )  def forward(self, x):  out = F.relu(self.bn1(self.conv1(x)))  out = self.bn2(self.conv2(out))  out += self.shortcut(x)  out = F.relu(out)  return out  class ResNet(nn.Module):  def __init__(self, block, num_blocks, num_classes=1000):  super(ResNet, self).__init__()  self.in_channels = 64  self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)  self.bn1 = nn.BatchNorm2d(64)  self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)  self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)  self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)  self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)  self.fc = nn.Linear(512*block.expansion, num_classes)  def _make_layer(self, block, out_channels, num_blocks, stride):  layers = []  layers.append(block(self.in_channels, out_channels, stride))  self.in_channels = out_channels * block.expansion  for i in range(1, num_blocks):  layers.append(block(self.in_channels, out_channels))  return nn.Sequential(*layers)  def forward(self, x):  out = F.relu(self.bn1(self.conv1(x)))  out = self.layer1(out)  out = self.layer2(out)  out = self.layer3(out)  out = self.layer4(out)  out = F.avg_pool2d(out, 4) # change to global pooling if needed  out = out.view(out.size(0), -1) # flatten the tensor to pass to fully connected layer  out = self.fc(out) # fully connected layer (output layer) with softmax activation (if needed)  return out

3.4使用Pytorch提供的ResNet50预训练模型进行训练

首先加载预训练的ResNet-50模型,更改第一个卷积层

# 加载预训练的ResNet-50模型  
net = models.resnet50(pretrained=True)  # 更改第一个卷积层的输入通道数  
net.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)  # 获取最后一个全连接层的输入特征数  
num_features = net.fc.in_features  # 替换最后一层全连接层为2个输出单元  
net.fc = nn.Linear(num_features, 2)  # 添加Softmax激活函数  
net.add_module("softmax", nn.Softmax(dim=1))  device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")  
net.to(device)  
net.float()  criterion = nn.CrossEntropyLoss()  
# 使用Adam优化器  
optimizer = torch.optim.Adam(net.parameters(), lr=0.001)  

3.5使用OneAPI组件进行加速

# 使用IPEX优化器优化模型  
net,optimizer = ipex.optimize(net,optimizer=optimizer)

4.模型训练(迭代二十次)

for epoch in range(1, 20):running_loss = 0.0num_images = 0loop = tqdm(enumerate(train_dataloader, 0))for step, data in loop:labels, inputs = data[0].float(), data[1].float()optimizer.zero_grad()inputs = inputs.float()outputs = net(inputs)# 创建包含相同数量的目标值的示例目标张量target = labels  # 使用实际标签作为目标# 使用 MSE 损失函数loss = criterion(outputs, target.long())loss.backward()optimizer.step()num_images += inputs.size(0)running_loss += loss.item()loop.set_description(f'Epoch [{epoch}/10]')loop.set_postfix(loss=running_loss / (step + 1))print('Compete training!!!')

在这里插入图片描述

5.计算推理时间和二分类准确度(F1分数)

因为电脑不是NVIDIA显卡不支持cuda环境所以无法使用GPU进行训练,只能用CPU训练时间较长。

from sklearn.metrics import f1_score
import time
correct = 0
total = 0
all_predictions = []
all_labels = []                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
# 开始推理
start_time = time.time()
with torch.no_grad():for data in test_dataloader:images, labels = data[1].to('cpu').float(), data[0].to('cpu').long()  # 将标签转换为整数类型net = net.float() outputs = net(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item() all_predictions.extend(predicted.cpu().numpy())all_labels.extend(labels.cpu().numpy())
accuracy = 100 * correct / total
# 计算推理时间
inference_time = time.time() - start_time
print(f'Accuracy on test set: {accuracy:.2f}%')
print(f"Inference Time: {inference_time} seconds")
f1 = f1_score(all_labels, all_predictions, average='binary')  # 适用于二分类问题
print(f'F1分数为: {f1:.4f}')

平均精度在97%以上
在这里插入图片描述

6.模型预测

from PIL import Image  
import matplotlib.pyplot as plt  
import numpy as np  
import torchvision.transforms.functional as TF  
import torch 
import matplotlib.image as mpimg# 保存模型  
PATH = './model_weights.pth'  
net.load_state_dict(torch.load(PATH))  # 加载一张图片进行测试  
image_path = 'data/agri_0_9952.jpeg'
image = Image.open(image_path).convert('L')  # 替换为你的图片路径  
image = TF.to_tensor(image)  # 将图片转换为tensor  
image = image.unsqueeze(0)  # 添加批处理维度  
image = image.to('cpu')  # 转移到GPU上  # 在图片上进行预测  
with torch.no_grad():  outputs = net(image)  # outputs为预测结果,即各个类别的概率分布  _, predicted = torch.max(torch.abs(outputs), 1)# 获取概率最高的类别作为预测结果  print('Predicted:', predicted.item())  # 打印预测结果  if predicted.item() == 0:  print('判断结果:作物')  elif predicted.item() == 1:  print('判断结果:杂草')  else:  print('预测结果不在0和1之间,可能存在错误')# 读取图片  
img = mpimg.imread(image_path)  # 显示图片  
plt.imshow(img)  
plt.show()

预测结果与标签一致
在这里插入图片描述

在这里插入图片描述

7.OneAPI组件的使用

OneAPI Math Kernel Library (MKL):ntel的数学核心函数库,包含一系列优化的数学函数,用于高性能计算和机器学习应用。
OneDNN:这是Intel的另一个高性能计算库,专门为深度学习应用提供优化。它提供了各种深度学习相关的操作,如卷积、池化、归一化等,都经过优化以提高运行速度。

8.项目总结

有很多模型都可以运用到杂草检测的案例中,本次使用的模型是ResNet50。通过自己重新搭建ResNet50的网络结构,对于这个模型也更加了解。使用了OneAPI组件进行加速,让推理时间有了一个很明显的减少。这次涉及到的组件主要是OneAPI Math Kernel Library和OneDNN,还有很多其它的组件没有使用到,后面也会去深入学习其他组件将它们更好的运用在项目中。

这篇关于【Intel校企合作课程】基于ResNet50的杂草检测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/829753

相关文章

基于CTPN(tensorflow)+CRNN(pytorch)+CTC的不定长文本检测和识别

转发来源:https://swift.ctolib.com/ooooverflow-chinese-ocr.html chinese-ocr 基于CTPN(tensorflow)+CRNN(pytorch)+CTC的不定长文本检测和识别 环境部署 sh setup.sh 使用环境: python 3.6 + tensorflow 1.10 +pytorch 0.4.1 注:CPU环境

【图像识别系统】昆虫识别Python+卷积神经网络算法+人工智能+深度学习+机器学习+TensorFlow+ResNet50

一、介绍 昆虫识别系统,使用Python作为主要开发语言。通过TensorFlow搭建ResNet50卷积神经网络算法(CNN)模型。通过对10种常见的昆虫图片数据集(‘蜜蜂’, ‘甲虫’, ‘蝴蝶’, ‘蝉’, ‘蜻蜓’, ‘蚱蜢’, ‘蛾’, ‘蝎子’, ‘蜗牛’, ‘蜘蛛’)进行训练,得到一个识别精度较高的H5格式模型文件,然后使用Django搭建Web网页端可视化操作界面,实现用户上传一

基于深度学习的轮廓检测

基于深度学习的轮廓检测 轮廓检测是计算机视觉中的一项关键任务,旨在识别图像中物体的边界或轮廓。传统的轮廓检测方法如Canny边缘检测和Sobel算子依赖于梯度计算和阈值分割。而基于深度学习的方法通过训练神经网络来自动学习图像中的轮廓特征,能够在复杂背景和噪声条件下实现更精确和鲁棒的检测效果。 深度学习在轮廓检测中的优势 自动特征提取:深度学习模型能够自动从数据中学习多层次的特征表示,而不需要

自动驾驶---Perception之Lidar点云3D检测

1 背景         Lidar点云技术的出现是基于摄影测量技术的发展、计算机及高新技术的推动以及全球定位系统和惯性导航系统的发展,使得通过激光束获取高精度的三维数据成为可能。随着技术的不断进步和应用领域的拓展,Lidar点云技术将在测绘、遥感、环境监测、机器人等领域发挥越来越重要的作用。         目前全球范围内纯视觉方案的车企主要包括特斯拉和集越,在达到同等性能的前提下,纯视觉方

YOLOv9摄像头或视频实时检测

1、下载yolov9的项目 地址:YOLOv9 2、使用下面代码进行检测 import torchimport cv2from models.experimental import attempt_loadfrom utils.general import non_max_suppression, scale_boxesfrom utils.plots import plot_o

Java内存泄漏检测和分析介绍

在Java中,内存泄漏检测和分析是一个重要的任务,可以通过以下几种方式进行:   1. 使用VisualVM VisualVM是一个可视化工具,可以监控、分析Java应用程序的内存消耗。它可以显示堆内存、垃圾收集、线程等信息,并且可以对内存泄漏进行分析。 2. 使用Eclipse Memory Analyzer Eclipse Memory Analyzer(MAT)是一个强大的工具,可

基于CDMA的多用户水下无线光通信(3)——解相关多用户检测

继续上一篇博文,本文将介绍基于解相关的多用户检测算法。解相关检测器的优点是因不需要估计各个用户的接收信号幅值而具有抗远近效应的能力。常规的解相关检测器有运算量大和实时性差的缺点,本文针对异步CDMA的MAI主要来自干扰用户的相邻三个比特周期的特点,给出了基于相邻三个匹配滤波器输出数据的截断解相关检测算法。(我不知道怎么改公式里的字体,有的字母在公式中重复使用了,请根据上下文判断字母含义) 1

前景检测算法_3(GMM)

因为监控发展的需求,目前前景检测的研究还是很多的,也出现了很多新的方法和思路。个人了解的大概概括为以下一些: 帧差、背景减除(GMM、CodeBook、 SOBS、 SACON、 VIBE、 W4、多帧平均……)、光流(稀疏光流、稠密光流)、运动竞争(Motion Competition)、运动模版(运动历史图像)、时间熵……等等。如果加上他们的改进版,那就是很大的一个家族了。

2023-2024 学年第二学期小学数学六年级期末质量检测模拟(制作:王胤皓)(90分钟)

word效果预览: 一、我会填 1. 1.\hspace{0.5em} 1. 一个多位数,亿位上是次小的素数,千位上是最小的质数的立方,十万位是 10 10 10 和 15 15 15 的最大公约数,万位是最小的合数,十位上的数既不是质数也不是合数,这个数是 ( \hspace{4em} ),约等于 ( \hspace{1em} ) 万 2. 2.\hspace{0.5em} 2.

【目标检测】DAB-DETR

一、引言 论文: DAB-DETR: Dynamic Anchor Boxes are Better Queries for DETR 作者: IDEA 代码: DAB-DETR 注意: 该算法是对DETR的改进,在学习该算法前,建议掌握多头注意力、Sinusoidal位置编码、DETR等相关知识。 特点: 将Decoder中Query的角色解耦为图像内容和物体位置,明确了DETR收敛慢的原因在