当前位置: 首页 > news >正文

基于深度学习的猫狗识别系统【深度学习课设】

🏆 作者简介:席万里
⚡ 个人网站:https://dahua.bloggo.chat/
✍️ 一名后端开发小趴菜,同时略懂Vue与React前端技术,也了解一点微信小程序开发。
🍻 对计算机充满兴趣,愿意并且希望学习更多的技术,接触更多的大神,提高自己的编程思维和解决问题的能力。

文章目录

  • 作品演示
    • 代码
      • 1.train_and_test.py
      • 2、view.py(可视化界面)

作品演示

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

代码

采用模型VGG16、ALEXNet、Resnet18,训练测试。python版本3.10.11 。

数据集:和鲸社区猫狗图像数据集。https://www.heywhale.com/mw/project/631aedb893f47b16cb062b2a

1.train_and_test.py

# 导入 PyTorch 库和相关模块
import torch                                 # PyTorch 的核心库,提供张量计算和自动求导功能
import torchvision.transforms as transforms  # 提供图像数据增强和预处理的功能
from torch.utils.data import Dataset         # 用于自定义数据集
from torch import nn, optim                  # nn 用于构建神经网络,optim 用于优化算法
from PIL import Image                        # 用于加载和处理图像文件
import time                                  # 用于记录训练时长和其他时间相关操作
import torchvision.models as models          # 包含一些预训练模型,如 AlexNet、ResNet 等
import os                                    # 用于与操作系统交互,如文件路径处理、创建目录等
import matplotlib.pyplot as plt              # 用于绘制图表,如准确率曲线、损失曲线等
from tqdm import tqdm                        # 用于显示训练过程中的进度条
from sklearn.metrics import confusion_matrix # 用于计算混淆矩阵,评估分类性能
import seaborn as sns                        # 用于绘制混淆矩阵的热图,提供美观的图表风格device = torch.device('cpu')# 数据预处理:缩放到224x224大小,并转换为Tensor
transformer = transforms.Compose([transforms.Resize((224, 224)), transforms.ToTensor()])# 加载训练数据集
DogTrainImageList = os.listdir(r"./catsdogs/train/Dog")  # 加载训练集中的狗图片列表
CatTrainImageList = os.listdir(r"./catsdogs/train/Cat")  # 加载训练集中的猫图片列表
train_label = []  # 存储训练数据的标签
train_data = []  # 存储训练数据的图像数据
dog_train_data_dir = r"./catsdogs/train/Dog/"  # 狗的图片目录路径
cat_train_data_dir = r"./catsdogs/train/Cat/"  # 猫的图片目录路径# 将狗的图片加载进训练数据集
for i in range(len(DogTrainImageList)):train_label.append(1)  # 狗的标签为1dog_img = Image.open(dog_train_data_dir + DogTrainImageList[i]).convert('RGB')  # 打开图片并转换为RGBdog_img = transformer(dog_img)  # 进行预处理train_data.append(dog_img)  # 添加到训练数据# 将猫的图片加载进训练数据集
for i in range(len(CatTrainImageList)):train_label.append(0)  # 猫的标签为0cat_img = Image.open(cat_train_data_dir + CatTrainImageList[i]).convert('RGB')  # 打开图片并转换为RGBcat_img = transformer(cat_img)  # 进行预处理train_data.append(cat_img)  # 添加到训练数据# 加载测试数据集(与训练集类似)
DogTestImageList = os.listdir(r"./catsdogs/train/Dog")
CatTestImageList = os.listdir(r"./catsdogs/train/Cat")
test_label = []  # 存储测试数据的标签
test_data = []  # 存储测试数据的图像数据
dog_test_data_dir = r"./catsdogs/train/Dog/"  # 狗的测试图片目录路径
cat_test_data_dir = r"./catsdogs/train/Cat/"  # 猫的测试图片目录路径# 将狗的测试图片加载进测试数据集
for i in range(len(DogTestImageList)):test_label.append(1)  # 狗的标签为1dog_img = Image.open(dog_test_data_dir + DogTestImageList[i]).convert('RGB')dog_img = transformer(dog_img)test_data.append(dog_img)# 将猫的测试图片加载进测试数据集
for i in range(len(CatTestImageList)):test_label.append(0)  # 猫的标签为0cat_img = Image.open(cat_test_data_dir + CatTestImageList[i]).convert('RGB')cat_img = transformer(cat_img)test_data.append(cat_img)# 自定义的数据集类,用于加载图像数据
class DealDataset(Dataset):def __init__(self, data, label, transform=None):self.data = data  # 图像数据self.label = label  # 图像标签self.transform = transform  # 图像预处理def __getitem__(self, index):data, label = self.data[index], int(self.label[index])  # 获取指定索引的数据和标签return data, label  # 返回数据和标签def __len__(self):return len(self.data)  # 返回数据集的大小# 将训练数据集和测试数据集包装为DealDataset对象
TrainDataSet = DealDataset(train_data, train_label, transform=transformer)
TestDataSet = DealDataset(test_data, test_label, transform=transformer)# 定义AlexNet模型
class AlexNet(nn.Module):def __init__(self):super(AlexNet, self).__init__()# 定义卷积层部分self.conv = nn.Sequential(nn.Conv2d(3, 64, kernel_size=11, stride=4),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.BatchNorm2d(64),nn.Conv2d(64, 192, kernel_size=5, padding=2),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.BatchNorm2d(192),nn.Conv2d(192, 384, kernel_size=3, padding=1),nn.ReLU(),nn.Conv2d(384, 256, kernel_size=3, padding=1),nn.ReLU(),nn.Conv2d(256, 256, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.BatchNorm2d(256))# 定义全连接层部分self.fc = nn.Sequential(nn.Linear(256 * 5 * 5, 4096),nn.ReLU(),nn.Dropout(0.5),nn.Linear(4096, 4096),nn.ReLU(),nn.Dropout(0.5),nn.Linear(4096, 2)  # 输出2个类别:猫或狗)def forward(self, img):feature = self.conv(img)  # 通过卷积层提取特征output = self.fc(feature.view(img.shape[0], -1))  # 展开特征并通过全连接层进行分类return output# 使用预训练的VGG16模型,并修改最后的全连接层以适应2个输出类别
class VGG16(nn.Module):def __init__(self, num_classes=2):super(VGG16, self).__init__()self.model = models.vgg16(pretrained=True)  # 加载预训练的VGG16模型self.model.classifier[-1] = nn.Linear(self.model.classifier[-1].in_features, num_classes)  # 修改输出层def forward(self, x):return self.model(x)  # 返回模型的输出# 使用ResNet18模型,并修改最后的全连接层以适应2个输出类别
class ResNet18(nn.Module):def __init__(self):super(ResNet18, self).__init__()self.model = models.resnet18(pretrained=False)  # 加载ResNet18模型self.model.fc = nn.Linear(self.model.fc.in_features, 2)  # 修改输出层为2个类别def forward(self, x):return self.model(x)  # 返回模型的输出# 绘制混淆矩阵的函数
def plot_combined_confusion_matrix(true_labels_dict, predicted_labels_dict, classes,save_path='combined_confusion_matrix.png'):# 创建一个子图,用来显示多个模型的混淆矩阵fig, axes = plt.subplots(1, len(true_labels_dict), figsize=(15, 5))# 遍历每个模型并绘制其混淆矩阵for i, (model_name, true_labels) in enumerate(true_labels_dict.items()):predicted_labels = predicted_labels_dict[model_name]cm = confusion_matrix(true_labels, predicted_labels)  # 计算混淆矩阵# 使用Seaborn绘制热图sns.heatmap(cm, annot=True, fmt="d", cmap="Blues", xticklabels=classes, yticklabels=classes,ax=axes[i], cbar=False, annot_kws={"size": 14})axes[i].set_xlabel('Predicted labels', fontsize=12)axes[i].set_ylabel('True labels', fontsize=12)axes[i].set_title(f'{model_name} Confusion Matrix', fontsize=14)# 调整布局并保存图像plt.tight_layout()plt.savefig(save_path)plt.show()# 计算模型在测试集上的准确率
def evaluate_accuracy(data_iter, net, device=None):if device is None and isinstance(net, torch.nn.Module):device = list(net.parameters())[0].device  # 获取模型的设备acc_sum, n = 0.0, 0predicted_labels = []true_labels = []with torch.no_grad():  # 在测试时不需要计算梯度for X, y in tqdm(data_iter, desc="加载中:", leave=True):net.eval()  # 将模型设置为评估模式outputs = net(X.to(device))  # 获取模型输出predicted = outputs.argmax(dim=1)  # 获取预测的标签true_labels.extend(y.cpu().numpy())  # 存储真实标签predicted_labels.extend(predicted.cpu().numpy())  # 存储预测标签acc_sum += (predicted == y.to(device)).float().sum().cpu().item()  # 累加准确的样本数n += y.shape[0]  # 累加样本总数return acc_sum / n, true_labels, predicted_labels  # 返回准确率,真实标签和预测标签# 训练和评估模型
def train_and_evaluate_models(models, model_names, train_iter, test_iter, batch_size, optimizer_dict, device,num_epochs, save_model_paths, plot_path):train_acc_history = {name: [] for name in model_names}  # 存储训练过程中每个模型的训练准确率test_acc_history = {name: [] for name in model_names}  # 存储测试过程中每个模型的测试准确率train_loss_history = {name: [] for name in model_names}  # 存储每个模型的训练损失# 存储每个模型的混淆矩阵数据true_labels_dict = {name: [] for name in model_names}predicted_labels_dict = {name: [] for name in model_names}# 迭代训练周期for epoch in range(num_epochs):for model, model_name in zip(models, model_names):  # 遍历每个模型model.train()optimizer = optimizer_dict[model_name]  # 获取当前模型的优化器loss_fn = torch.nn.CrossEntropyLoss()  # 定义损失函数scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=3, gamma=0.7)  # 学习率衰减策略train_l_sum, train_acc_sum, n, batch_count, start = 0.0, 0.0, 0, 0, time.time()# 训练每个模型for X, y in train_iter:X, y = X.to(device), y.to(device)y_hat = model(X)  # 获取模型预测loss = loss_fn(y_hat, y)  # 计算损失optimizer.zero_grad()  # 清空梯度loss.backward()  # 反向传播optimizer.step()  # 更新参数train_l_sum += loss.item()  # 累加损失train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item()  # 累加准确的样本数n += y.shape[0]batch_count += 1scheduler.step()  # 学习率衰减# 计算训练集和测试集的准确率train_acc = train_acc_sum / ntest_acc, true_labels, predicted_labels = evaluate_accuracy(test_iter, model, device)# 存储每个模型的混淆矩阵数据true_labels_dict[model_name].extend(true_labels)predicted_labels_dict[model_name].extend(predicted_labels)train_acc_history[model_name].append(train_acc)test_acc_history[model_name].append(test_acc)train_loss_history[model_name].append(train_l_sum / batch_count)print(f'{model_name} epoch {epoch + 1}, loss {train_l_sum / batch_count:.4f}, 'f'train acc {train_acc:.3f}, test acc {test_acc:.3f}, time {time.time() - start:.1f} sec')# 保存模型torch.save(model.state_dict(), save_model_paths[model_name])  # 保存模型的权重print(f"{model_name} Model saved to {save_model_paths[model_name]} after epoch {epoch + 1}")# 在所有训练完成后生成混淆矩阵的综合图plot_combined_confusion_matrix(true_labels_dict, predicted_labels_dict, ['Cat', 'Dog'],save_path=os.path.join(plot_path, 'combined_confusion_matrix.png'))return train_acc_history, test_acc_history, train_loss_history# 可视化训练结果并保存
def plot_and_save_results(train_acc_history, test_acc_history, train_loss_history, num_epochs, save_plots_path):plt.figure(figsize=(10, 5))# 绘制每个模型的训练与测试准确率曲线for model_name in ['AlexNet', 'ResNet18', 'VGG16']:if model_name in train_acc_history and model_name in test_acc_history:plt.plot(range(num_epochs), train_acc_history[model_name], label=f'{model_name} Train Accuracy')plt.plot(range(num_epochs), test_acc_history[model_name], label=f'{model_name} Test Accuracy')plt.xlabel('Epochs')plt.ylabel('Accuracy')plt.title('AlexNet, ResNet18, VGG16 - Training and Test Accuracy Comparison')plt.legend()plt.grid(True)plt.savefig(os.path.join(save_plots_path, 'accuracy_plot.png'))  # 保存准确率图像plt.show()plt.figure(figsize=(10, 5))# 绘制每个模型的训练损失曲线for model_name in ['AlexNet', 'ResNet18', 'VGG16']:if model_name in train_loss_history:plt.plot(range(num_epochs), train_loss_history[model_name], label=f'{model_name} Train Loss')plt.xlabel('Epochs')plt.ylabel('Loss')plt.title('Training Loss Comparison')plt.legend()plt.grid(True)plt.savefig(os.path.join(save_plots_path, 'loss_plot.png'))  # 保存损失图像plt.show()if __name__ == '__main__':# 设置训练参数num_epochs = 25  # 设置为可配置参数batch_size = 16  # 设置为可配置参数learning_rate = 0.009  # 设置为可配置参数save_model_paths = {'AlexNet': 'AlexNet.pth','ResNet18': 'ResNet18.pth','VGG16': 'VGG16.pth'}save_plots_path = './python'os.makedirs(save_plots_path, exist_ok=True)  # 创建保存模型和图像的文件夹# 创建模型实例alexnet_model = AlexNet().to(device)resnet_model = ResNet18().to(device)vgg_model = VGG16().to(device)# 创建数据加载器train_iter = torch.utils.data.DataLoader(TrainDataSet, batch_size=batch_size, shuffle=True, num_workers=2)test_iter = torch.utils.data.DataLoader(TestDataSet, batch_size=batch_size, shuffle=False, num_workers=2)# 优化器字典optimizer_dict = {'AlexNet': torch.optim.SGD(alexnet_model.parameters(), lr=learning_rate),'ResNet18': torch.optim.SGD(resnet_model.parameters(), lr=learning_rate),'VGG16': torch.optim.SGD(vgg_model.parameters(), lr=learning_rate)}# 训练并评估models = [alexnet_model, resnet_model, vgg_model]model_names = ['AlexNet', 'ResNet18', 'VGG16']train_acc_history, test_acc_history, train_loss_history = train_and_evaluate_models(models, model_names, train_iter, test_iter, batch_size, optimizer_dict, device, num_epochs, save_model_paths, save_plots_path)# 绘制并保存准确率和损失曲线plot_and_save_results(train_acc_history, test_acc_history, train_loss_history, num_epochs, save_plots_path)

2、view.py(可视化界面)

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QFileDialog, QVBoxLayout, QGridLayout, \QTextEdit, QComboBox, QSpacerItem, QSizePolicy
from PyQt5.QtGui import QPixmap, QFont, QTextCursor
import torch
import torch.nn as nn
import torchvision.transforms as transforms
from PIL import Image
import torchvision.models as modelsclass AnimalClassifierApp(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):self.setWindowTitle('猫狗识别系统')self.resize(600, 400)  # 更小的窗口尺寸# 创建布局grid = QGridLayout()grid.setContentsMargins(10, 10, 10, 10)  # 设置间距grid.setSpacing(5)  # 设置控件间距# 显示图像的标签self.image_label = QLabel(self)self.image_label.setFixedSize(250, 250)  # 调整图像显示尺寸self.image_label.setAlignment(Qt.AlignCenter)grid.addWidget(self.image_label, 1, 0, 2, 1)# 识别结果的标签self.result_label = QTextEdit(self)self.result_label.setFixedSize(250, 80)self.result_label.setReadOnly(True)self.result_label.setStyleSheet("color: red; font-size: 14px;")self.result_label.setAlignment(Qt.AlignCenter)grid.addWidget(self.result_label, 1, 1, 1, 2)# 模型选择下拉框self.model_selector = QComboBox(self)self.model_selector.addItem("AlexNet")self.model_selector.addItem("VGG16")self.model_selector.addItem("ResNet18")grid.addWidget(self.model_selector, 2, 0, 1, 2)# 按钮布局button_layout = QVBoxLayout()button_layout.setSpacing(5)  # 设置按钮间距# 上传图像按钮upload_btn = QPushButton('上传', self)upload_btn.clicked.connect(self.load_image)button_layout.addWidget(upload_btn)# 识别按钮recognize_btn = QPushButton('识别', self)recognize_btn.clicked.connect(self.classify_image)button_layout.addWidget(recognize_btn)# 添加按钮布局button_layout.addSpacerItem(QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding))grid.addLayout(button_layout, 3, 1, 1, 2)self.setLayout(grid)# 加载模型self.device = torch.device('cpu')# 定义数据转换self.transform = transforms.Compose([transforms.Resize((148, 148)),transforms.ToTensor(),transforms.Normalize(mean=[0.4, 0.4, 0.4], std=[0.2, 0.2, 0.2])])self.image_path = ''self.model = None  # 模型初始化为空def load_image(self):options = QFileDialog.Options()options |= QFileDialog.ReadOnlyfile_name, _ = QFileDialog.getOpenFileName(self, "上传图片", "", "图片文件 (*.jpg *.jpeg *.png)",options=options)if file_name:self.image_path = file_namepixmap = QPixmap(file_name)pixmap = pixmap.scaled(self.image_label.width(), self.image_label.height(), Qt.KeepAspectRatio)self.image_label.setPixmap(pixmap)self.result_label.setText('识别结果: ')def classify_image(self):if self.image_path:# 根据选择的模型加载相应的模型selected_model = self.model_selector.currentText()if selected_model == "AlexNet":self.model = self.load_alexnet_model()elif selected_model == "VGG16":self.model = self.load_vgg16_model()elif selected_model == "ResNet18":self.model = self.load_resnet18_model()image = Image.open(self.image_path).convert('RGB')image_tensor = self.transform(image).unsqueeze(0).to(self.device)with torch.no_grad():output = self.model(image_tensor)probabilities = torch.nn.functional.softmax(output, dim=1)confidence, predicted = torch.max(probabilities, 1)label = 'cat' if predicted.item() == 0 else 'dog'confidence = confidence.item()# 将图像转换为QPixmappixmap = QPixmap(self.image_path)pixmap = pixmap.scaled(self.image_label.width(), self.image_label.height(), Qt.KeepAspectRatio)self.image_label.setPixmap(pixmap)# 设置识别结果字体颜色和对齐方式self.result_label.setText(f'识别结果: {label} \n\n置信度: {confidence:.2f}')self.result_label.setAlignment(Qt.AlignCenter)cursor = self.result_label.textCursor()cursor.select(QTextCursor.Document)self.result_label.setTextCursor(cursor)def load_alexnet_model(self):model = models.alexnet(pretrained=True)model.classifier[6] = nn.Linear(model.classifier[6].in_features, 2)  # 修改最后一层model = model.to(self.device)model.eval()return modeldef load_vgg16_model(self):model = models.vgg16(pretrained=True)model.classifier[6] = nn.Linear(model.classifier[6].in_features, 2)  # 修改最后一层model = model.to(self.device)model.eval()return modeldef load_resnet18_model(self):model = models.resnet18(pretrained=True)model.fc = nn.Linear(model.fc.in_features, 2)  # 修改最后一层model = model.to(self.device)model.eval()return modelif __name__ == '__main__':app = QApplication(sys.argv)ex = AnimalClassifierApp()ex.show()sys.exit(app.exec_())

相关文章:

基于深度学习的猫狗识别系统【深度学习课设】

🏆 作者简介:席万里 ⚡ 个人网站:https://dahua.bloggo.chat/ ✍️ 一名后端开发小趴菜,同时略懂Vue与React前端技术,也了解一点微信小程序开发。 🍻 对计算机充满兴趣,愿意并且希望学习更多的技…...

字体子集化实践探索

最近项目rust生成PDF组件printpdf需要内嵌完整字体导致生成的PDF很大,需要做压缩,但是rust的类库allsorts::subset::subset不支持windows,所以做了一些windows下字体子集化的尝试 方案一:node.js做子集化 fontmin 缺点是也需要集…...

A1017 基于Java+JSP+SQL Server+servlet的二手购物平台的设计与实现

二手购物平台 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 摘 要 计算机以及网络技术的飞速发展,网络的应用在全国乃至全球日益普及,随着人们的思想水平和生活水平的提高,网络已经是人们必不可少的一部分。人们的…...

Simdroid-EC:液冷仿真新星,助力新能源汽车电机控制器高效散热

近年来,新能源电动车的销量呈现出快速增长的态势。据统计,2024 年1-10月中国新能源汽车销量达728万辆,同比增长37.8%。 电机控制器在新能源汽车中对于保障动力和安全性能扮演着至关重要的角色,其核心部件IGBT(绝缘栅双…...

C语言——实现并求出两个数的最大公约数

问题描述&#xff1a;求出两个数的最大公约数 //求两个数的最大公约数 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<time.h>int main() {int a,b;printf("请您输入两个数 a 和 b\n");scanf…...

今天你学C++了吗?——C++中的类与对象(日期类的实现)——实践与知识的碰撞❤

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...

享元模式的理解和实践

在软件开发中&#xff0c;性能优化是一个永恒的话题。在追求高性能的过程中&#xff0c;减少内存的使用是一项重要的任务。享元模式&#xff08;Flyweight Pattern&#xff09;就是一种用于减少内存使用量的设计模式&#xff0c;它特别适用于存在大量重复对象的场景。本文将详细…...

Unreal Engine 中的UI界面开发

推荐的使用方式 轻量级 HUD:使用 Canvas 绘制简单的文本、调试信息或基础 UI(如准星、血量条等)。 复杂 UI:使用 UMG(Unreal Motion Graphics)和 Slate 进行布局和交互,避免手动管理 Canvas 绘制。 避免遮挡场景:仅绘制必要的内容,并利用透明度(如 FLinearColor(1, 1…...

Docker在Ubuntu和CentOS系统下的安装

目录 1. 各版本平台支持情况2. 在Ubuntu系统下安装docker3. 常见报错4. Docker的镜像源修改5. Docker目录修改6. 在CentOS系统下安装docker 1. 各版本平台支持情况 &#xff08;1&#xff09;平台支持情况如下&#xff1a; Server 版本 桌面版本 2. 在Ubuntu系统下安装docker…...

EXCEL 关于plot 折线图--频度折线图的一些细节

目录 0 折线图有很多 1 频度折线图 1.1 直接用原始数据做的频度折线图 2 将原始数据生成数据透视表 3 这样可以做出了&#xff0c;频度plot 4 做按某字段汇总&#xff0c;成为累计plot分布 5 修改上面显示效果&#xff0c;做成百分比累计plot频度分布 0 折线图有很多 这…...

Hive操作案例

目录 idea/dg远程连接导入数据建表数据导入 idea/dg远程连接 hive的详细安装不多展示&#xff0c;自行搜索即可。 依次启动zookeeper&#xff0c;hadoop 在zookeeper的节点上启动如下指令&#xff08;我的是1个主节点和2个备用节点&#xff09; 启动Hive的metastore&#xff0…...

C++ 内存管理和模板与STL

此篇目是之后各种C库的基础 目录 内存管理 内存分布 内存管理方式 new和delete operator new 与 operator delete函数 实现原理 定位new表达式(placement-new) 模板基础 泛型编程 模板 函数模板 类模板 STL 组成部分 内存管理 内存分布 int globalVar 1; //全局变量 静…...

JDK8新特性:Stream

JDK8最大的改变&#xff1a; 1. lambda表达式 2. Stream 1. Steam流的入门 什么是Stream&#xff1f; 也叫Stream流&#xff0c;是jdk8开始的一套API&#xff0c;用于操作集合或者数组中的数据 优点&#xff1a; Stream流大量结合了Lambda的语法风格来创建&#xff0c;提…...

前端传入Grule,后端保存到 .grl 文件中

前端传入Grule&#xff0c;后端保存到 .grl 文件中 通过简单的输入框&#xff0c;将Grule的部分拆解成 规则名称 规则描述 规则优先级 规则条件 规则逻辑Grule关键字 when Then 模拟了 if 判断的条件和逻辑部分 类似于 shell 和 ruby 之类的脚本语言&#xff0c;有 then 关键字…...

探索《Crypto Rumble》 游戏:经济模型篇

《Crypto Rumble》是一款基于 Zypher Network 游戏引擎打造的卡牌 RPG三消品类的 Web3 游戏&#xff0c;通过引人入胜的游戏设计以及轻量化的游戏玩法&#xff0c;《Crypto Rumble》不仅能够为玩家带来引人入胜的沉浸式游戏体验&#xff0c;同时基于 AI Bot 的游戏编辑器&#…...

【CSS in Depth 2 精译_072】第 12 章 CSS 排版与间距概述 + 12.1 间距设置(上):究竟该用 em 还是 px

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 12 章 CSS 排版与间距】 ✔️ 12.1 间距设置 ✔️ 12.1.1 使用 em 还是 px ✔️12.1.2 对行高的深入思考12.1.3 行内元素的间距设置 文章目录 第 12 章 排版与间距…...

Elasticsearch对象映射

Spring Data Elasticsearch对象映射是将Java对象&#xff08;域实体&#xff09;映射到存储在Elasticsearchs中的JSON表示形式并返回的过程。内部用于此映射的类是MappingElasticsearchConverter。 元模型对象映射 基于元模型的方法使用域类型信息对Elasticsearch进行读写操作…...

Oracle 19c rac 补丁升级,从19.7 to19.22-集群

1. 补丁包概述 数据库环境 角色 数据库 IP地址 数据库版本 主机名 数据库名称 源端 RAC 172.30.21.166/167 19.7 hfcwdb66/hfcwdb67 hfdb 将以下补丁包上传到/soft下 上传到两个节点的soft目录下&#xff1a;p6880880_190000_Linux-x86-64.zip &#xff08;更新o…...

机器学习--Kaggle的使用

机器学习–Kaggle的使用 打开Kaggle: Your Machine Learning and Data Science Community并点击Sign In登录账号 kaggle中自带了很多的数据集 在点击Datasets之后&#xff0c;单点Notebook&#xff0c;如果有适用的数据集可以单击Copy and Edit复制其Notebook&#xff0c;之后…...

客户服务新突破,天润融通助力电动车企业实现数智化转型

近年来&#xff0c;两轮电动车成为年轻人喜爱的出行新方式&#xff0c;借着这种潮流&#xff0c;许多新兴品牌迅速发展&#xff0c;并跻身行业头部。 但问题也随之而来&#xff0c;由于业务快速发展&#xff0c;各类服务问题也开始增多。 比如天润融通服务的一家头部两轮电动…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...