精准识别花生豆:基于EfficientNetB0的深度学习检测与分类项目

news2025/1/3 7:55:34

精准检测花生豆:基于EfficientNet的深度学习分类项目

在现代农业生产中,作物的质量检测和分类是确保产品质量的重要环节。针对花生豆的检测与分类需求,我们开发了一套基于深度学习的解决方案,利用EfficientNetB0模型实现高效、准确的花生豆分类。本博客将详细介绍该项目的背景、数据处理、模型架构、训练过程、评估方法及预测应用。

目录

  1. 项目背景
  2. 项目概述
  3. 数据处理
    • 数据集结构
    • 数据增强与规范化
  4. 模型架构
  5. 训练过程
    • 训练脚本 (train.py)
  6. 模型评估
    • 评估脚本 (evaluate.py)
  7. 预测与应用
    • 预测脚本 (predict.py)
  8. 项目成果
  9. 结论与未来工作

项目背景

花生豆作为一种重要的经济作物,其品质直接影响到市场价值和消费者满意度。传统的人工检测方法不仅耗时耗力,而且易受主观因素影响,难以实现大规模、精准的分类。因此,开发一种高效、准确的自动化检测系统显得尤为重要。

项目概述

本项目旨在利用深度学习技术,构建一个能够自动检测和分类花生豆的系统。通过收集和处理大量花生豆图像数据,训练一个高性能的卷积神经网络模型,实现对不同类别花生豆的精准分类。项目主要包括以下几个部分:

  • 数据处理:图像数据的加载、预处理与增强。
  • 模型架构:基于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.py

train_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.py

class 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 = False

        in_features = self.model.classifier[1].in_features
        self.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.py

import 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 os

def accuracy(predictions, labels):
    pred = torch.argmax(predictions, dim=1)
    correct = (pred == labels).sum().item()
    return correct

def 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 = 0
    net = 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, 0
        with 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 / total
        train_loss = train_loss / total
        train_acc_list.append(train_acc)
        train_loss_list.append(train_loss)

        # 验证阶段
        net.eval()
        validation_correct, validation_loss, total_validation = 0, 0, 0
        with 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_validation
        validation_loss = validation_loss / total_validation
        validation_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_acc
            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, 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 = 64
    image_size = 224
    classes_num = 8
    num_epochs = 100
    auto_save = 10
    lr = 1e-4
    weight_decay = 1e-4
    device = '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 = 0
    best_validation_acc = 0
    if 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'] + 1
                best_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_start
    m, s = divmod(seconds, 60)
    h, m = divmod(m, 60)
    print("训练结束")
    print("本次训练时长为:%02d:%02d:%02d" % (h, m, s))

主要特点:

  • 进度条可视化:使用tqdm库实时展示训练和验证进度。
  • 断点续训:支持从上一次中断的epoch继续训练,确保训练过程的连续性。
  • 自动保存:定期保存模型检查点,防止意外中断导致的训练损失。
  • 训练曲线:生成并保存训练与验证的准确率和损失曲线,便于后续分析与调优。

模型评估

评估脚本 (evaluate.py)

评估脚本用于在测试集上评估训练好的模型性能,计算准确率和损失,并将结果保存到文件中。

# evaluate.py

import torch
import torch.nn as nn
from utils.dataLoader import load_data
from utils.model import EfficientNetB0
from tqdm import tqdm
import os

def accuracy(predictions, labels):
    pred = torch.argmax(predictions, dim=1)
    correct = (pred == labels).sum().item()
    return correct

def evaluate(net, test_loader, device, criterion, output_path):
    net.eval()
    test_correct, test_loss, total_test = 0, 0, 0
    with 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_test
    test_loss = test_loss / total_test
    result = 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 = 64
    image_size = 224
    classes_num = 8
    device = '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("评估结束")

评估流程:

  1. 加载模型:从保存的权重文件中加载训练好的模型。
  2. 模型评估:在测试集上计算模型的准确率和损失。
  3. 结果保存:将评估结果保存到指定的输出文件中,便于后续查看与分析。

预测与应用

预测脚本 (predict.py)

预测脚本用于对新图像进行花生豆分类,并在图像上标注分类结果和边框。

# predict.py

import os
import cv2
import numpy as np
import torch
from PIL import Image
from utils.model import EfficientNetB0
from torchvision import transforms

def delet_contours(contours, delete_list):
    delta = 0
    for i in range(len(delete_list)):
        del contours[delete_list[i] - delta]
        delta += 1
    return contours

def 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} 不存在,请先训练模型。")
        return
    net.load_state_dict(torch.load(model_path, map_location=device))
    net.to(device)
    net.eval()
    
    min_size = 30
    max_size = 400
    
    for 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}")
            continue
        
        hsv = 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:
                continue
            crop_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()

预测流程:

  1. 图像预处理:将输入图像转换到HSV颜色空间,应用颜色掩膜提取花生豆区域。
  2. 轮廓检测与过滤:查找并过滤不符合大小要求的轮廓,确保只处理有效的花生豆区域。
  3. 分类与标注:对每个有效轮廓进行裁剪、预处理,并使用训练好的模型进行分类。在图像上标注分类结果和边框。
  4. 结果保存:将标注后的图像保存到指定的输出目录。

预测结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

项目成果

通过本项目,我们成功构建了一个能够高效、准确地检测和分类花生豆的深度学习模型。主要成果包括:

  • 高准确率:模型在测试集上达到了令人满意的分类准确率。
  • 自动化检测:实现了对新图像的自动检测与分类,大大提高了检测效率。
  • 可视化结果:通过图像标注,直观展示了分类结果,便于用户理解和应用。

训练与验证的准确率和损失曲线示例
在这里插入图片描述

开源的程序及数据集

git clone https://gitee.com/songaoxiangsoar/peanut-bean-testing.git

结论与未来工作

本项目展示了基于深度学习的花生豆检测与分类的可行性与有效性。通过采用预训练的EfficientNetB0模型,并结合数据增强与优化策略,模型在花生豆分类任务中表现出色。

未来的工作方向包括:

  • 模型优化:尝试更深更复杂的模型,如EfficientNetB7,以进一步提升分类性能。
  • 数据扩展:收集更多多样化的花生豆图像,增强模型的泛化能力。
  • 实时检测:优化模型推理速度,实现实时花生豆检测与分类。
  • 部署应用:将模型集成到移动设备或嵌入式系统,便于现场检测与应用。

通过持续的优化与扩展,我们相信这一系统将在农业生产中发挥更大的价值,助力智能农业的发展。


感谢阅读本博客!如果您对本项目有任何疑问或建议,欢迎在下方留言交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2268456.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用套接字创建一个服务端,创建一个客户端然后相互通讯

以下是对上述代码的详细解释&#xff1a; #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>#include <stdio.h> #include <stdlib.h> #include <string.h&…

ES 磁盘使用率检查及处理方法

文章目录 1. 检查原因2. 检查方法3. 处理方法3.1 清理数据3.2 再次检查磁盘使用率 1. 检查原因 磁盘使用率在 85%以下&#xff0c;ES 可正常运行&#xff0c;达到 85%及以上会影响 PEIM 数据存储。 在 ES 磁盘分配分片控制策略中&#xff0c;为了保护数据节点的安全&#xff0…

[cg] android studio 无法调试cpp问题

折腾了好久&#xff0c;native cpp库无法调试问题&#xff0c;原因 下面的Deploy 需要选Apk from app bundle!! 另外就是指定Debug type为Dual&#xff0c;并在Symbol Directories 指定native cpp的so路径 UE项目调试&#xff1a; 使用Android Studio调试虚幻引擎Android项目…

Flutter中添加全局防护水印的实现

随着版权意识的加强&#xff0c;越来越多的应用开始在应用内部增加各种各样的水印信息&#xff0c;防止核心信息泄露&#xff0c;便于朔源。 效果如下&#xff1a; 在Flutter中增加全局水印的方式&#xff0c;目前有两种实现。 方案一&#xff0c;在native层添加一个遮罩层&a…

MQTT——客户端安装使用(图文详解)

目录 一. 下载安装MQTT 1. 下载MQTT 2. 安装MQTT 二. MQTT客户端使用 1. 连接MQTT服务 2. MQTT发布消息 3. MQTT 消息订阅 4. 断开MQTT服务器连接 三. 使用Jmeter给MQTT发数据 一. 下载安装MQTT 1. 下载MQTT &#xff08;1&#xff09;官网下载地址&#xff1a;MQTTX…

2- 位段式结构体

文章目录 1 结构体内存对齐2 位段式结构体2.1 格式2.2 成员类型2.3 空间开辟2.4 示例2.4.1 示例12.4.2 示例2 1 结构体内存对齐 首成员对齐规则 结构体的第一个成员从偏移量为0的地址处开始存放&#xff0c;即与结构体的首地址对齐。 其他成员对齐规则 其他成员变量的存放地址…

Milvus×EasyAi:如何用java从零搭建人脸识别应用

如何从零搭建一个人脸识别应用&#xff1f;不妨试试原生Java人工智能算法&#xff1a;EasyAi Milvus 的组合拳。 本文将使用到的软件和工具包括&#xff1a; EasyAi&#xff1a;人脸特征向量提取Milvus&#xff1a;向量数据库用于高效存储和检索数据。 01. EasyAi&#xff1a;…

AWS K8s 部署架构

Amazon Web Services&#xff08;AWS&#xff09;提供了一种简化的Kubernetes&#xff08;K8s&#xff09;部署架构&#xff0c;使得在云环境中管理和扩展容器化应用变得更加容易。这个架构的核心是AWS EKS&#xff08;Elastic Kubernetes Service&#xff09;&#xff0c;它是…

[Pro Git#2] 分支管理 | branch fix_bug , feature | 处理合并冲突

目录 一、Issue模板文件 二、Pull Requests模板文件 分支管理 1. 理解分支 2. 创建与管理分支 1. 切换分支与提交历史 2. 合并分支 3. 删除分支 4. 解决合并冲突 6. 查看分支合并情况 快速创建并切换分支 分支管理策略 分支合并模式 分支管理原则 日常开发环境 …

Acwing 基础算法课 数学知识 筛法求欧拉函数

【G09 筛法求欧拉函数】https://www.bilibili.com/video/BV1VP411p7Bs?vd_source57dbd16b8c7c2ad258cccce5966c5be8 闫总真是把听者当数学系转cs的来讲&#xff0c;菜逼完全听不懂&#xff0c;只能其他地再搜 欧拉函数 φ ( n ) \varphi(n) φ(n)&#xff1a;1~n中与n互质的数…

SpringCloudAlibaba技术栈-Higress

1、什么是Higress? 云原生网关&#xff0c;干啥的&#xff1f;用通俗易懂的话来说&#xff0c;微服务架构下Higress 就像是一个智能的“交通警察”&#xff0c;它站在你的网络世界里&#xff0c;负责指挥和调度所有进出的“车辆”&#xff08;也就是数据流量&#xff09;。它的…

# 光速上手 - JPA 原生 sql DTO 投影

前言 使用 JPA 时&#xff0c;我们一般通过 Entity 进行实体类映射&#xff0c;从数据库中查询出对象。然而&#xff0c;在实际开发中&#xff0c;有时需要自定义查询结果并将其直接映射到 DTO&#xff0c;而不是实体类。这种需求可以通过 JPA 原生 SQL 查询和 DTO 投影 来实现…

智能故障诊断和寿命预测期刊推荐

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 基于FFT CNN - BiGRU-Attention 时域、频域特征注意力融合的轴承故障识别模型-CSDN博客 基于FFT CNN - Transformer 时域、频域特征融合的轴承故障识别模型-CSDN博客 P…

MTK抓log方法log机制以及如何抓取log

目录 离线log抓取&#xff1a; adb命令打开mtklog的方法 &#xff1a; 实时log抓取&#xff1a; 设置log等级和打开平台log: 实时抓取&#xff0c;两种方式&#xff1a; Kernel Log: LOG 优先级 logcat 离线log抓取&#xff1a; 1.手机先进入开发者模式 2.进入拨号页面…

人工智能与云计算的结合:如何释放数据的无限潜力?

引言&#xff1a;数据时代的契机 在当今数字化社会&#xff0c;数据已成为推动经济与技术发展的核心资源&#xff0c;被誉为“21世纪的石油”。从个人消费行为到企业运营决策&#xff0c;再到城市管理与国家治理&#xff0c;每个环节都在生成和积累海量数据。然而&#xff0c;数…

如何在 Ubuntu 22.04 上安装 Varnish HTTP 教程

简介 在本教程中&#xff0c;我们将学习如何在 Ubuntu 22.04 服务器上安装和配置 Varnish HTTP。 Varnish 是一款高性能的 HTTP 加速器&#xff0c;旨在提高内容密集型动态网站的速度。它通过将网页缓存在内存中来工作&#xff0c;从而减少 Web 服务器的负载&#xff0c;并显…

AI辅助编码提高病案首页主要诊断编码正确率数据优化方法(2025增量优化版附python源代码)

一、引言 1.1 研究背景与意义 在医疗信息化进程中,病案首页作为病历信息的核心浓缩,承载着疾病分类、医疗统计、医保结算等关键任务,其主要诊断编码的准确性至关重要。准确的编码不仅是医疗质量评估、科研数据分析的基石,更是合理分配医疗资源、保障医保精准支付的关键依…

CSES-1135 Distance Queries

题目传送门https://vjudge.net/problem/CSES-1135#authorGPT_zh 解题思路 题目让我们求树上两个点的距离。 那么就可以转化为两点到其 LCA 的距离之和。 代码 #include<bits/stdc.h> using namespace std;int n,q; vector<int> g[200001]; int dis[200001],dep…

「Mac畅玩鸿蒙与硬件49」UI互动应用篇26 - 数字填色游戏

本篇教程将带你实现一个数字填色小游戏&#xff0c;通过简单的交互逻辑&#xff0c;学习如何使用鸿蒙开发组件创建趣味性强的应用。 关键词 UI互动应用数字填色动态交互逻辑判断游戏开发 一、功能说明 数字填色小游戏包含以下功能&#xff1a; 数字选择&#xff1a;用户点击…

001__VMware软件和ubuntu系统安装(镜像)

[ 基本难度系数 ]:★☆☆☆☆ 一、Vmware软件和Ubuntu系统说明&#xff1a; a、Vmware软件的说明&#xff1a; 官网&#xff1a; 历史版本&#xff1a; 如何下载&#xff1f; b、Ubuntu系统的说明&#xff1a; 4、linux系统的其他版本&#xff1a;红旗(redhat)、dibian、cent…