精准识别花生豆:基于EfficientNetB0的深度学习检测与分类项目
精准检测花生豆:基于EfficientNet的深度学习分类项目
在现代农业生产中,作物的质量检测和分类是确保产品质量的重要环节。针对花生豆的检测与分类需求,我们开发了一套基于深度学习的解决方案,利用EfficientNetB0模型实现高效、准确的花生豆分类。本博客将详细介绍该项目的背景、数据处理、模型架构、训练过程、评估方法及预测应用。
目录
- 项目背景
- 项目概述
- 数据处理
- 数据集结构
- 数据增强与规范化
- 模型架构
- 训练过程
- 训练脚本 (
train.py
)
- 训练脚本 (
- 模型评估
- 评估脚本 (
evaluate.py
)
- 评估脚本 (
- 预测与应用
- 预测脚本 (
predict.py
)
- 预测脚本 (
- 项目成果
- 结论与未来工作
项目背景
花生豆作为一种重要的经济作物,其品质直接影响到市场价值和消费者满意度。传统的人工检测方法不仅耗时耗力,而且易受主观因素影响,难以实现大规模、精准的分类。因此,开发一种高效、准确的自动化检测系统显得尤为重要。
项目概述
本项目旨在利用深度学习技术,构建一个能够自动检测和分类花生豆的系统。通过收集和处理大量花生豆图像数据,训练一个高性能的卷积神经网络模型,实现对不同类别花生豆的精准分类。项目主要包括以下几个部分:
- 数据处理:图像数据的加载、预处理与增强。
- 模型架构:基于EfficientNetB0的分类模型设计。
- 训练过程:模型的训练与优化,包括断点续训与学习率调度。
- 模型评估:在测试集上的性能评估。
- 预测应用:对新图像进行花生豆分类与标注。
数据处理
数据集结构
项目使用的数据集分为训练集、验证集和测试集,具体结构如下:
./data/dataset/
├── train/
│ ├── baiban/
│ ├── bandian/
│ ├── famei/
│ ├── faya/
│ ├── hongpi/
│ ├── qipao/
│ ├── youwu/
│ └── zhengchang/
├── validation/
│ ├── baiban/
│ ├── bandian/
│ ├── famei/
│ ├── faya/
│ ├── hongpi/
│ ├── qipao/
│ ├── youwu/
│ └── zhengchang/
└── test/├── baiban/├── bandian/├── famei/├── faya/├── hongpi/├── qipao/├── youwu/└── zhengchang/
每个子文件夹对应一种花生豆类别,包含相应的图像数据。
数据增强与规范化
为了提高模型的泛化能力,训练过程中对图像数据进行了多种数据增强操作,如随机裁剪、水平翻转、旋转和颜色抖动。同时,使用ImageNet的均值和标准差对图像进行了归一化处理,与预训练模型的输入要求保持一致。
# utils/dataLoader.pytrain_transform = transforms.Compose([transforms.Resize((image_size, image_size)),transforms.RandomResizedCrop(image_size, scale=(0.8, 1.0)),transforms.RandomHorizontalFlip(),transforms.RandomRotation(15),transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),transforms.ToTensor(),transforms.Normalize(*stats)
])validation_transform = transforms.Compose([transforms.Resize((image_size, image_size)),transforms.CenterCrop(image_size),transforms.ToTensor(),transforms.Normalize(*stats)
])test_transform = transforms.Compose([transforms.Resize((image_size, image_size)),transforms.CenterCrop(image_size),transforms.ToTensor(),transforms.Normalize(*stats)
])
模型架构
本项目采用了EfficientNetB0作为基础模型。EfficientNet系列通过系统性地平衡网络的宽度、深度和分辨率,在模型性能和计算效率之间取得了优异的平衡。具体来说:
- 预训练权重:使用在ImageNet上预训练的权重,帮助模型在较小的数据集上快速收敛。
- 冻结特征提取部分:根据需要,可以选择冻结模型的特征提取层,仅训练最后的分类器,适用于数据量较小的情况。
- 分类器设计:在原有分类器前添加了Dropout层,减少过拟合风险。
# utils/model.pyclass EfficientNetB0(nn.Module):def __init__(self, num_classes, pretrained=True, freeze_features=False):super(EfficientNetB0, self).__init__()if pretrained:self.model = models.efficientnet_b0(weights=models.EfficientNet_B0_Weights.IMAGENET1K_V1)else:self.model = models.efficientnet_b0(weights=None)if freeze_features:for param in self.model.features.parameters():param.requires_grad = Falsein_features = self.model.classifier[1].in_featuresself.model.classifier = nn.Sequential(nn.Dropout(p=0.4, inplace=True),nn.Linear(in_features, num_classes))def forward(self, x):return self.model(x)
训练过程
训练脚本 (train.py
)
训练脚本负责模型的训练与验证,包括数据加载、模型初始化、训练循环、学习率调度、模型保存和训练曲线绘制等功能。
关键功能包括:
- 训练与验证循环:每个epoch包括训练阶段和验证阶段,记录损失与准确率。
- 优化与调度:使用Adam优化器和
ReduceLROnPlateau
学习率调度器,根据验证损失动态调整学习率。 - 模型保存:保存验证集准确率最高的模型,并定期自动保存模型检查点。
- 断点续训:支持从保存的检查点继续训练,避免重复计算。
- 训练曲线绘制:训练结束后,生成并保存训练与验证的准确率和损失曲线。
# train.pyimport torch
import torch.nn as nn
from utils.dataLoader import load_data
from utils.model import EfficientNetB0
from tqdm import tqdm
import time
import matplotlib.pyplot as plt
import osdef accuracy(predictions, labels):pred = torch.argmax(predictions, dim=1)correct = (pred == labels).sum().item()return correctdef train(net, start_epoch, epochs, train_loader, validation_loader, device, criterion, optimizer, scheduler, model_path, auto_save):# 初始化train_acc_list, validation_acc_list = [], []train_loss_list, validation_loss_list = [], []best_validation_acc = 0net = net.to(device)if start_epoch > 0:print(f"从 epoch {start_epoch} 开始训练。")for epoch in range(start_epoch, epochs):# 训练阶段net.train()train_correct, train_loss, total = 0, 0, 0with tqdm(train_loader, ncols=100, colour='green', desc=f"Train Epoch {epoch+1}/{epochs}") as pbar:for images, labels in pbar:images, labels = images.to(device), labels.to(device)optimizer.zero_grad()outputs = net(images)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item() * images.size(0)train_correct += accuracy(outputs, labels)total += labels.size(0)pbar.set_postfix({'loss': f"{train_loss / total:.4f}", 'acc': f"{train_correct / total:.4f}"})train_acc = train_correct / totaltrain_loss = train_loss / totaltrain_acc_list.append(train_acc)train_loss_list.append(train_loss)# 验证阶段net.eval()validation_correct, validation_loss, total_validation = 0, 0, 0with torch.no_grad():with tqdm(validation_loader, ncols=100, colour='blue', desc=f"Validation Epoch {epoch+1}/{epochs}") as pbar:for images, labels in pbar:images, labels = images.to(device), labels.to(device)outputs = net(images)loss = criterion(outputs, labels)validation_loss += loss.item() * images.size(0)validation_correct += accuracy(outputs, labels)total_validation += labels.size(0)pbar.set_postfix({'loss': f"{validation_loss / total_validation:.4f}", 'acc': f"{validation_correct / total_validation:.4f}"})validation_acc = validation_correct / total_validationvalidation_loss = validation_loss / total_validationvalidation_acc_list.append(validation_acc)validation_loss_list.append(validation_loss)# 更新学习率scheduler.step(validation_loss)# 保存最佳模型if validation_acc > best_validation_acc:best_validation_acc = validation_acccheckpoint = {'epoch': epoch,'model_state_dict': net.state_dict(),'optimizer_state_dict': optimizer.state_dict(),'scheduler_state_dict': scheduler.state_dict(),'validation_acc': best_validation_acc}torch.save(checkpoint, model_path)print(f"保存最佳模型,验证准确率: {best_validation_acc:.4f}")# 自动保存模型if (epoch + 1) % auto_save == 0:save_path = model_path.replace('.pth', f'_epoch{epoch+1}.pth')checkpoint = {'epoch': epoch,'model_state_dict': net.state_dict(),'optimizer_state_dict': optimizer.state_dict(),'scheduler_state_dict': scheduler.state_dict(),'validation_acc': best_validation_acc}torch.save(checkpoint, save_path)print(f"自动保存模型到 {save_path}")# 绘制训练曲线def plot_training_curves(train_acc_list, validation_acc_list, train_loss_list, validation_loss_list, epochs):plt.figure(figsize=(12, 5))plt.subplot(1, 2, 1)plt.plot(range(1, epochs+1), train_acc_list, 'bo-', label="训练准确率")plt.plot(range(1, epochs+1), validation_acc_list, 'ro-', label="验证准确率")plt.title("训练准确率 vs 验证准确率")plt.xlabel("轮次")plt.ylabel("准确率")plt.legend()plt.subplot(1, 2, 2)plt.plot(range(1, epochs+1), train_loss_list, 'bo-', label="训练损失")plt.plot(range(1, epochs+1), validation_loss_list, 'ro-', label="验证损失")plt.title("训练损失 vs 验证损失")plt.xlabel("轮次")plt.ylabel("损失")plt.legend()os.makedirs('logs', exist_ok=True)plt.savefig('logs/training_curve.png')plt.show()plot_training_curves(train_acc_list, validation_acc_list, train_loss_list, validation_loss_list, epochs)if __name__ == '__main__':batch_size = 64image_size = 224classes_num = 8num_epochs = 100auto_save = 10lr = 1e-4weight_decay = 1e-4device = 'cuda' if torch.cuda.is_available() else 'cpu'classify = {'baiban': 0, 'bandian': 1, 'famei': 2, 'faya': 3, 'hongpi': 4, 'qipao': 5, 'youwu': 6, 'zhengchang': 7}train_loader, validation_loader, test_loader = load_data(batch_size, image_size, classify)net = EfficientNetB0(classes_num, pretrained=True, freeze_features=False)model_path = 'model_weights/EfficientNetB0.pth'os.makedirs('model_weights', exist_ok=True)criterion = nn.CrossEntropyLoss()optimizer = torch.optim.Adam(net.parameters(), lr=lr, weight_decay=weight_decay)scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=True)# 检查点续训start_epoch = 0best_validation_acc = 0if os.path.exists(model_path):try:checkpoint = torch.load(model_path, map_location=device)required_keys = ['model_state_dict', 'optimizer_state_dict', 'scheduler_state_dict', 'epoch', 'validation_acc']if all(key in checkpoint for key in required_keys):net.load_state_dict(checkpoint['model_state_dict'])optimizer.load_state_dict(checkpoint['optimizer_state_dict'])scheduler.load_state_dict(checkpoint['scheduler_state_dict'])start_epoch = checkpoint['epoch'] + 1best_validation_acc = checkpoint['validation_acc']print(f"从 epoch {checkpoint['epoch']} 继续训练,最佳验证准确率: {best_validation_acc:.4f}")else:print(f"检查点文件缺少必要的键,开始从头训练。")except Exception as e:print(f"加载检查点时发生错误: {e}")print("开始从头训练。")print("训练开始")time_start = time.time()train(net, start_epoch, num_epochs, train_loader, validation_loader, device=device, criterion=criterion, optimizer=optimizer, scheduler=scheduler, model_path=model_path, auto_save=auto_save)time_end = time.time()seconds = time_end - time_startm, s = divmod(seconds, 60)h, m = divmod(m, 60)print("训练结束")print("本次训练时长为:%02d:%02d:%02d" % (h, m, s))
主要特点:
- 进度条可视化:使用
tqdm
库实时展示训练和验证进度。 - 断点续训:支持从上一次中断的epoch继续训练,确保训练过程的连续性。
- 自动保存:定期保存模型检查点,防止意外中断导致的训练损失。
- 训练曲线:生成并保存训练与验证的准确率和损失曲线,便于后续分析与调优。
模型评估
评估脚本 (evaluate.py
)
评估脚本用于在测试集上评估训练好的模型性能,计算准确率和损失,并将结果保存到文件中。
# evaluate.pyimport torch
import torch.nn as nn
from utils.dataLoader import load_data
from utils.model import EfficientNetB0
from tqdm import tqdm
import osdef accuracy(predictions, labels):pred = torch.argmax(predictions, dim=1)correct = (pred == labels).sum().item()return correctdef evaluate(net, test_loader, device, criterion, output_path):net.eval()test_correct, test_loss, total_test = 0, 0, 0with torch.no_grad():with tqdm(test_loader, ncols=100, colour='blue', desc=f"Evaluating on Test Set") as pbar:for images, labels in pbar:images, labels = images.to(device), labels.to(device)outputs = net(images)loss = criterion(outputs, labels)test_loss += loss.item() * images.size(0)test_correct += accuracy(outputs, labels)total_test += labels.size(0)pbar.set_postfix({'loss': f"{test_loss / total_test:.4f}", 'acc': f"{test_correct / total_test:.4f}"})test_acc = test_correct / total_testtest_loss = test_loss / total_testresult = f"测试集准确率: {test_acc:.4f}, 测试集损失: {test_loss:.4f}"print(result)# 保存结果到文件os.makedirs(os.path.dirname(output_path), exist_ok=True)with open(output_path, 'a') as f:f.write(result + '\n')if __name__ == '__main__':batch_size = 64image_size = 224classes_num = 8device = 'cuda' if torch.cuda.is_available() else 'cpu'classify = {'baiban': 0, 'bandian': 1, 'famei': 2, 'faya': 3, 'hongpi': 4, 'qipao': 5, 'youwu': 6, 'zhengchang': 7}_, _, test_loader = load_data(batch_size, image_size, classify)net = EfficientNetB0(classes_num, pretrained=False)model_path = 'model_weights/EfficientNetB0.pth'if not os.path.exists(model_path):print(f"模型权重文件 {model_path} 不存在,请先训练模型。")exit()net.load_state_dict(torch.load(model_path, map_location=device))net.to(device)criterion = nn.CrossEntropyLoss()evaluation_output_path = 'outputs/evaluation_results.txt'# 清空之前的评估结果if os.path.exists(evaluation_output_path):os.remove(evaluation_output_path)print("评估开始")evaluate(net, test_loader, device=device, criterion=criterion, output_path=evaluation_output_path)print("评估结束")
评估流程:
- 加载模型:从保存的权重文件中加载训练好的模型。
- 模型评估:在测试集上计算模型的准确率和损失。
- 结果保存:将评估结果保存到指定的输出文件中,便于后续查看与分析。
预测与应用
预测脚本 (predict.py
)
预测脚本用于对新图像进行花生豆分类,并在图像上标注分类结果和边框。
# predict.pyimport os
import cv2
import numpy as np
import torch
from PIL import Image
from utils.model import EfficientNetB0
from torchvision import transformsdef delet_contours(contours, delete_list):delta = 0for i in range(len(delete_list)):del contours[delete_list[i] - delta]delta += 1return contoursdef main():input_path = 'data/pic'output_dir = 'outputs/predicted_images'os.makedirs(output_dir, exist_ok=True)image_files = os.listdir(input_path)classify = {0: 'baiban', 1: 'bandian', 2: 'famei', 3: 'faya', 4: 'hongpi', 5: 'qipao', 6: 'youwu', 7: 'zhengchang'}# 与训练时相同的预处理transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize(mean=(0.485, 0.456, 0.406), # ImageNet均值std=(0.229, 0.224, 0.225)) # ImageNet标准差])device = 'cuda' if torch.cuda.is_available() else 'cpu'net = EfficientNetB0(8, pretrained=False)model_path = 'model_weights/EfficientNetB0.pth'if not os.path.exists(model_path):print(f"模型权重文件 {model_path} 不存在,请先训练模型。")returnnet.load_state_dict(torch.load(model_path, map_location=device))net.to(device)net.eval()min_size = 30max_size = 400for img_name in image_files:img_path = os.path.join(input_path, img_name)img = cv2.imread(img_path)if img is None:print(f"无法读取图像: {img_path}")continuehsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 转换到HSV颜色空间# 根据HSV颜色范围进行掩膜操作(根据实际情况调整颜色范围)lower_blue = np.array([100, 100, 8])upper_blue = np.array([255, 255, 255])mask = cv2.inRange(hsv, lower_blue, upper_blue) # 创建掩膜result = cv2.bitwise_and(img, img, mask=mask) # 应用掩膜result = result.astype(np.uint8)# 转换为灰度图并二值化gray = cv2.cvtColor(result, cv2.COLOR_BGR2GRAY)_, binary_image = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)# 查找轮廓contours, _ = cv2.findContours(binary_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)contours = list(contours)# 过滤轮廓delete_list = []for idx, contour in enumerate(contours):perimeter = cv2.arcLength(contour, True)if perimeter < min_size or perimeter > max_size:delete_list.append(idx)contours = delet_contours(contours, delete_list)# 对每个轮廓进行分类for contour in contours:x, y, w, h = cv2.boundingRect(contour)crop = img[y:y+h, x:x+w]if crop.size == 0:continuecrop_pil = Image.fromarray(cv2.cvtColor(crop, cv2.COLOR_BGR2RGB))crop_tensor = transform(crop_pil).unsqueeze(0).to(device)with torch.no_grad():output = net(crop_tensor)pred = torch.argmax(output, dim=1).item()label = classify[pred]# 标注图像cv2.putText(img, label, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)# 保存结果图像到outputs/predicted_images/output_image_path = os.path.join(output_dir, f"{os.path.splitext(img_name)[0]}_predicted.jpg")cv2.imwrite(output_image_path, img)print(f"保存预测结果到 {output_image_path}")print("所有图像的预测和标注已完成并保存到 ./outputs/predicted_images/")if __name__ == '__main__':main()
预测流程:
- 图像预处理:将输入图像转换到HSV颜色空间,应用颜色掩膜提取花生豆区域。
- 轮廓检测与过滤:查找并过滤不符合大小要求的轮廓,确保只处理有效的花生豆区域。
- 分类与标注:对每个有效轮廓进行裁剪、预处理,并使用训练好的模型进行分类。在图像上标注分类结果和边框。
- 结果保存:将标注后的图像保存到指定的输出目录。
预测结果
项目成果
通过本项目,我们成功构建了一个能够高效、准确地检测和分类花生豆的深度学习模型。主要成果包括:
- 高准确率:模型在测试集上达到了令人满意的分类准确率。
- 自动化检测:实现了对新图像的自动检测与分类,大大提高了检测效率。
- 可视化结果:通过图像标注,直观展示了分类结果,便于用户理解和应用。
训练与验证的准确率和损失曲线示例
开源的程序及数据集
git clone https://gitee.com/songaoxiangsoar/peanut-bean-testing.git
结论与未来工作
本项目展示了基于深度学习的花生豆检测与分类的可行性与有效性。通过采用预训练的EfficientNetB0模型,并结合数据增强与优化策略,模型在花生豆分类任务中表现出色。
未来的工作方向包括:
- 模型优化:尝试更深更复杂的模型,如EfficientNetB7,以进一步提升分类性能。
- 数据扩展:收集更多多样化的花生豆图像,增强模型的泛化能力。
- 实时检测:优化模型推理速度,实现实时花生豆检测与分类。
- 部署应用:将模型集成到移动设备或嵌入式系统,便于现场检测与应用。
通过持续的优化与扩展,我们相信这一系统将在农业生产中发挥更大的价值,助力智能农业的发展。
感谢阅读本博客!如果您对本项目有任何疑问或建议,欢迎在下方留言交流。
相关文章:

精准识别花生豆:基于EfficientNetB0的深度学习检测与分类项目
精准检测花生豆:基于EfficientNet的深度学习分类项目 在现代农业生产中,作物的质量检测和分类是确保产品质量的重要环节。针对花生豆的检测与分类需求,我们开发了一套基于深度学习的解决方案,利用EfficientNetB0模型实现高效、准…...

【UE5 C++课程系列笔记】13——GameInstanceSubsystem的简单使用
目录 概念 基本使用案例 效果 步骤 概念 UGameInstanceSubsystem 类继承自 USubsystem,它与 GameInstance 紧密关联,旨在为游戏提供一种模块化、可方便扩展和管理的功能单元机制。在整个游戏运行期间,一个 GameInstance 可以包含多个 UGa…...

实用工具推荐----Doxygen使用方法
目录 目录 1 软件介绍 2 Doxygen软件下载方法 3 Doxygen软件配置方法 4 标准注释描述 4.1 块注释 和 特殊描述字符 4.1.1 函数描述示例 4.1.2结构体数组变量示例 特别注意: 4.2单行注释 4.2.1 单个变量注释示例 特别注意: 4.2.2对于枚举变量…...
js垃圾回收机制详细讲解
JavaScript 垃圾回收机制(Garbage Collection, GC)负责自动管理内存的分配和释放,确保程序在运行时不会因为内存泄漏而崩溃。它的主要任务是回收不再使用的内存空间,防止内存泄漏。JavaScript 的垃圾回收通常由引擎自动完成&#…...

【Linux/踩坑】Linux中启动eclipse或HDFS因JAVA_HOME设置报错
Linux中启动eclipse或hadoop因JAVA_HOME设置报错 eclipseHadoop eclipse 错误提示: A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. No Java virtual machine was found after searching the follo…...

百度千帆平台构建AI APP的基础概念梳理
百度千帆平台构建AI APP的基础概念梳理 如果想制作大语言模型(LLM)相关的APP, 将利用百度的千帆平台在国内可能是最便捷的途径,因为百度开发了成熟的工作流,前些年还有些不稳定,现在固定下来了,…...
Unity3D Huatuo技术原理剖析详解
前言 在游戏开发领域,Unity3D凭借其强大的跨平台能力和丰富的功能,成为了众多开发者的首选工具。而在Unity3D的生态系统中,Huatuo作为一款重要的插件,为游戏开发带来了极大的便利。本文将深入剖析Huatuo的技术原理,并…...

记Fastjson2的一个报ConcurrentModificationException的bug
错误背景:fastjson2的parseObject方法,在spring webflux项目中被调用,有时会报java.util.ConcurrentModificationException错误。报错处的代码如下图: 改了半天与并发安全相关的代码,还是会报此错误。后来改变思路搜…...
使用TimesFM 对车辆销售进行预测
代码功能概述 导入相关包与设置环境变量: 首先导入了如 os、numpy、pandas 等常用的 Python 库,同时设置了一些与特定库(如 XLA_PYTHON_CLIENT_PREALLOCATE 和 JAX_PM AP_USE_TENSORSTORE)相关的环境变量,用于优化计算…...
OpenEuler 22.03 不依赖zookeeper安装 kafka 3.3.2集群
零:规划 本次计划安装三台OpenEuler 22.03 版本操作系统的服务器,用于搭建 kafka和flink 集群。因为从kafka 2.8 版本以后开始不依赖 zookeeper ,同时考虑到需要找一个发布时间早于 flink 1.17 的kafka 版本且应尽量稳定,综合考虑…...

ubuntu 将python3.8 升级为python3.10并进行版本切换
ubuntu 将python3.8 升级为python3.10并进行版本切换 前言将python3.8 升级为3.10安装pippython版本切换 前言 有一个功能包编译环境需要为python3.10 ,但是当前环境为python3.8 ,所以需要进行版本升级,编译完还需要把环境切换回来。 将pyt…...

3. Kafka入门—安装与基本命令
Kafka基础操作 一. 章节简介二. kafka简介三. Kafka安装1. 准备工作2. Zookeeper安装2.1 配置文件2.2 启动相关命令3. Kafka安装3.1 配置文件3.2 启动相关命令-------------------------------------------------------------------------------------------------------------…...

如何使用 python创建图片格式转换器
在本篇博客中,我们将通过一个简单的实例来展示如何使用 wxPython 创建一个图形用户界面(GUI)应用程序,用于将图片从一种格式转换为另一种格式。我们将通过以下几个步骤实现这一目标: C:\pythoncode\new\imageconvertty…...

命令行之巅:Linux Shell编程的至高艺术(上)
文章一览 前言一、shell概述1.1 shell的特点和类型1.1.1 **shell的特点:**1.1.2 常用shell类型 1.2 shell脚本的建立和执行1.2.1 建立shell脚本1.2.2 执行shell脚本的方式1.2.3 shell程序实例 二、shell变量与算数运算2.1 简单shell变量2.1.1 简单变量定义和赋值2.1…...
【gulp】gulp 的基本使用
gulp 是一个基于node的自动化打包构建工具,前端开发者可以使用它来处理常见任务: 创建项目 进入项目 npm init -ynpm i gulp -g (使用命令 gulp)npm i gulp -D # 开发依赖(前端工具都是开发依赖 本地安装 代…...
Linux 下处理 ^M 字符的最佳实践
Linux 下处理 ^M 字符的最佳实践 一、快速解决方案 按照优先级排序的三种解决方案: 1. 使用 dos2unix(推荐) # 安装 sudo apt-get install dos2unix # Ubuntu/Debian sudo yum install dos2unix # CentOS# 使用 dos2unix 文件名2. 使用 sed sed...

【优选算法】—复写零(双指针算法)
云边有个稻草人-CSDN博客 每天至少一道算法题,接着干,以额现在的实力想完成那个目标确实难。算法题确实烧脑,挺煎熬的,但脑子烧多了是不是就该好些了?。。。 记得那句话,必须有为成功付出代价的决心&#x…...
2024国赛A问题三和四
问题三 最小螺距单目标优化模型的建立 问题二考虑了在螺距固定的条件下计算舞龙队盘入的终止时间,问题三在第二问的基础提出了改变螺距的要求,即求解在螺距最小为多少时,龙头前把手能够沿着相应的螺线盘入到调头空间的边界。故可将其转换为…...

asp.net 高校学生勤工俭学系统设计与实现
博主介绍:专注于Java(springboot ssm 等开发框架) vue .net php python(flask Django) 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找…...

《计算机组成及汇编语言原理》阅读笔记:p116-p120
《计算机组成及汇编语言原理》学习第 7 天,p116-p120 总结,总计 5 页。 一、技术总结 1.CPU优化 (1)increase overall performance number 例如:16位电脑提升到32位电脑。 (2)multiprocessing One way to make computers more useful i…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...