kaggle竞赛系列基于图像对水稻分类代码案例

目录

依赖环境

代码

导入依赖包

定义数据集路径:

创建训练集、验证集和测试集的文件夹:

代码的作用:

设置新的数据集路径与类别名称

代码的作用:

定义数据预处理和增强变换:

代码的作用:

定义数据集评估划分与batch大小

代码的作用:

可视化

代码的作用:

 评估可视化

代码的作用:

网络结构定义

代码的作用:

定义损失函数和优化器,并训练模型

 模型可视化评估

代码的作用:

下载地址:

python深度学习pytorch水稻图像分类完整案例


依赖环境

!pip install split-folders
!pip install torch-summary
!pip install torch matplotplib

代码

导入依赖包

import os
import pathlib
import numpy as np
import splitfolders
import itertools
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from termcolor import colored 
from datetime import datetime
import warnings
from tqdm.notebook import tqdm
from sklearn.metrics import confusion_matrix, classification_report
from torchsummary import summary
from numpy import asarray
from PIL import Image
  • ospathlib 用于文件和目录操作。
  • numpy 用于数组和数值计算。
  • splitfolders 用于分割数据集。
  • itertools 提供迭代生成器。
  • matplotlib.pyplot 用于绘图和数据可视化。
  • torchtorch.nntorch.nn.functionaltorch.optimtorchvisiontorchvision.transforms 用于构建和训练神经网络模型。
  • termcolor 用于终端中的彩色输出。
  • datetime 用于时间操作。
  • warnings 用于忽略警告信息。
  • tqdm.notebook 用于显示进度条。
  • sklearn.metrics 提供评估指标,包括混淆矩阵和分类报告。
  • torchsummary 用于总结模型结构。
  • numpy.asarrayPIL.Image 用于图像处理。

定义数据集路径

data = './Rice_Image_Dataset'
data = pathlib.Path(data)

创建训练集、验证集和测试集的文件夹

splitfolders.ratio(input=data, output='rice_imgs', seed=42, ratio=(0.7, 0.15, 0.15))
  • 使用 splitfolders.ratio 函数将数据集按照 7:1.5:1.5 的比例划分为训练集、验证集和测试集。
  • input 参数指定输入数据集的路径。
  • output 参数指定输出文件夹的名称 'rice_imgs',划分后的数据集将保存在这个文件夹中。
  • seed 参数设置随机种子,以确保划分结果的可重复性。
  • ratio 参数指定训练集、验证集和测试集的比例,分别为 70%、15% 和 15%。

代码的作用:

这段代码通过 splitfolders 库将原始的水稻图像数据集划分为训练集、验证集和测试集,以便在模型训练、验证和测试过程中使用不同的数据子集,从而提高模型的泛化能力和评估准确性。

设置新的数据集路径与类别名称

root_dir = './rice_imgs'
root_dir = pathlib.Path(root_dir)
Arborio='./Rice_Image_Dataset/Arborio'Arborio_classes=os.listdir(Arborio)
Rice_classes = os.listdir(root_dir)
batchsize=8from colorama import Fore, Styleprint(Fore.GREEN +str(Rice_classes))
print(Fore.YELLOW +"\nTotal number of classes are: ", len(Rice_classes))
  • root_dir 定义为之前划分后的数据集路径 './rice_imgs',并转换为路径对象。
  • Arborio 定义为原始数据集中某个类别的路径。
  • 使用 os.listdir(Arborio) 获取 Arborio 类别中的所有文件和文件夹名称。
  • 使用 os.listdir(root_dir) 获取新的数据集路径中的所有类别名称。
  • 导入 colorama 库中的 ForeStyle,用于终端输出的颜色设置。

代码的作用:

这段代码的主要作用是设置新的数据集路径,并获取数据集中各个类别的名称,以便在后续的数据加载和处理过程中使用。此外,代码还打印出了类别名称和总数,以便进行检查和验证。

定义数据预处理和增强变换

transform = transforms.Compose([transforms.Resize((250,250)),transforms.ToTensor(),transforms.Normalize((0),(1)),transforms.RandomHorizontalFlip(),transforms.RandomRotation(30),]
)
  • transforms.Compose:将多个变换操作组合在一起。
  • transforms.Resize((250,250)):将图像调整为 250x250 的固定尺寸。
  • transforms.ToTensor():将图像转换为 PyTorch 的张量格式,并将像素值归一化到 [0,1] 的范围。
  • transforms.Normalize((0),(1)):标准化图像,使图像的每个通道均值为 0,标准差为 1。
  • transforms.RandomHorizontalFlip():随机水平翻转图像,用于数据增强,以增加模型的泛化能力。
  • transforms.RandomRotation(30):随机旋转图像最多 30 度,用于数据增强。

代码的作用:

这段代码通过定义一个数据预处理和增强的变换流水线,在加载图像数据时自动对图像进行调整大小、转换为张量、标准化、随机水平翻转和随机旋转等操作。这些预处理和增强操作有助于提高模型的训练效果和泛化能力。

定义数据集评估划分与batch大小

import torch.utils.data
batch_size = 32# Read train images as a dataset
train_set = torchvision.datasets.ImageFolder(os.path.join(root_dir, 'train'), transform=transform
)
# Create a Data Loader
train_loader = torch.utils.data.DataLoader(train_set,  batch_size = batch_size, shuffle=True
)
print(colored(f'Train Folder :\n ', 'green', attrs=['bold']))
print(train_set)
print('_'*100)############################################################## Read validation images as a dataset
val_set = torchvision.datasets.ImageFolder(os.path.join(root_dir, 'val'), transform=transform
)
# Create a Data Loader
val_loader = torch.utils.data.DataLoader(val_set,  batch_size = batch_size, shuffle=True
)
print(colored(f'Validation Folder :\n ', 'red', attrs=['bold']))
print(val_set)
print('_'*100)############################################################## Read test images as a dataset
test_set = torchvision.datasets.ImageFolder(os.path.join(root_dir, 'test'), transform=transform
)
# Create a Data Loader
test_loader = torch.utils.data.DataLoader(test_set,  batch_size = batch_size, shuffle=True
)
print(colored(f'Test Folder :\n ', 'yellow', attrs=['bold']))
print(test_set)
  1. 设置批量大小

    • 首先导入 torch.utils.data,并设置批量大小为 32,用于后续的数据加载器中。
  2. 加载训练集数据并创建数据加载器

    • 使用 torchvision.datasets.ImageFolder 函数加载训练集图像数据,并应用之前定义的变换 transformos.path.join(root_dir, 'train') 指定了训练集数据的路径。
    • 创建一个数据加载器 train_loader,它从 train_set 中以批量的形式读取数据,batch_size 设置为 32,并启用了随机打乱 shuffle=True
  3. 打印训练集信息

    • 使用 colored 函数将输出文本设置为绿色,并打印训练集文件夹的信息和训练集数据集对象。
  4. 加载验证集数据并创建数据加载器

    • 类似于加载训练集,使用 torchvision.datasets.ImageFolder 函数加载验证集图像数据,并应用相同的变换 transformos.path.join(root_dir, 'val') 指定了验证集数据的路径。
    • 创建一个数据加载器 val_loader,从 val_set 中以批量的形式读取数据,batch_size 设置为 32,并启用了随机打乱 shuffle=True
  5. 打印验证集信息

    • 使用 colored 函数将输出文本设置为红色,并打印验证集文件夹的信息和验证集数据集对象。
  6. 加载测试集数据并创建数据加载器

    • 类似于加载训练集和验证集,使用 torchvision.datasets.ImageFolder 函数加载测试集图像数据,并应用相同的变换 transformos.path.join(root_dir, 'test') 指定了测试集数据的路径。
    • 创建一个数据加载器 test_loader,从 test_set 中以批量的形式读取数据,batch_size 设置为 32,并启用了随机打乱 shuffle=True
  7. 打印测试集信息

    • 使用 colored 函数将输出文本设置为黄色,并打印测试集文件夹的信息和测试集数据集对象。

代码的作用:

这段代码通过加载和处理训练集、验证集和测试集的数据,创建了相应的数据加载器。这些加载器将在模型训练和评估过程中使用,以批量的形式高效地读取和处理图像数据,从而提高模型训练和评估的效率。

可视化

# 可视化数据集以进行检查
# 首先创建一个包含标签名称的字典
labels_map = {0: "Arborio",1: "Basmati",2: "Ipsala",3: "Jasmine",4: "Karacadag",
}figure = plt.figure(figsize=(10, 10))
cols, rows = 5, 5
for i in range(1, cols * rows + 1):sample_idx = torch.randint(len(train_set), size=(1,)).item()img, label = train_set[sample_idx]figure.add_subplot(rows, cols, i)plt.title(labels_map[label])plt.axis("off")img_np = img.numpy().transpose((1, 2, 0))# 将像素值剪辑到 [0, 1] 范围内img_valid_range = np.clip(img_np, 0, 1)plt.imshow(img_valid_range)plt.suptitle('Rice Images', y=0.95)
plt.show()
  1. 创建标签字典

    • 创建一个字典 labels_map,将类别索引映射到类别名称,方便后续的可视化和检查。
  2. 创建可视化图形

    • 使用 plt.figure 创建一个图形对象,设置图形大小为 10x10。
    • 设置图形的列数和行数为 5,意味着将显示 25 个图像样本。
  3. 可视化图像样本

    • 使用 torch.randint 随机选择训练集中图像样本的索引。
    • train_set 中获取图像和对应的标签。
    • 将图像添加到图形的子图中,并设置子图的标题为对应的类别名称。
    • 关闭子图的坐标轴显示。
    • 将图像从张量格式转换为 NumPy 数组格式,并进行转置以匹配 plt.imshow 的输入格式。
    • 使用 np.clip 将图像的像素值限制在 [0, 1] 范围内,以确保显示的图像颜色正常。
    • 显示图像样本,并设置图形的整体标题为 "Rice Images"。

代码的作用:

这段代码通过随机选择并显示训练集中的图像样本,以及相应的类别名称,帮助检查数据是否正确加载,并提供对数据分布的直观理解。可视化的图像可以帮助确认图像增强和预处理步骤是否按照预期执行。

 评估可视化

def train(model, train_loader, validation_loader, device,loss_fn, optimizer, num_epochs, patience=3):"""训练模型:model: 创建的模型train_loader: 使用DataLoader加载的训练集validation_loader: 使用DataLoader加载的验证集device: 训练模型可用的设备(CPU或CUDA)loss_fn: 定义的损失函数optimizer: 定义的优化器num_epochs (int): 训练的轮数patience (int): 用于早停的耐心参数"""history = {'train_loss': [],'val_loss': [],'train_acc': [],'val_acc': []}epoch = 0best_val_loss = float('inf')best_model_weights = Noneearly_stopping_counter = 0while epoch < num_epochs and early_stopping_counter < patience:model.train()train_loss = 0.0correct = 0total = 0pbar = tqdm(enumerate(train_loader), ncols=600, total=len(train_loader))for batch_idx, (inputs, labels) in pbar:pbar.set_description(f'Epoch {epoch+1}/{num_epochs} ')inputs, labels = inputs.to(device), labels.to(device)optimizer.zero_grad()outputs = model(inputs)loss = loss_fn(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()_, predicted = outputs.max(1)total += labels.size(0)correct += predicted.eq(labels).sum().item()train_loss /= len(train_loader)train_acc = correct / totalhistory['train_loss'].append(train_loss)history['train_acc'].append(train_acc)val_loss, val_acc = evaluate(model, validation_loader, device, loss_fn)history['val_loss'].append(val_loss)history['val_acc'].append(val_acc)# 打印进度print(f'train_loss: {train_loss:.4f} | 'f'train_acc: {train_acc:.4f} | ' +f'val_loss: {val_loss:.4f} | ' +f'val_acc: {val_acc:.4f}', '\n')if history['val_loss'][-1] < best_val_loss:best_model_weights = model.state_dict()early_stopping_counter = 0else:early_stopping_counter += 1best_val_loss = history['val_loss'][-1]epoch += 1return history, best_model_weights# ---------------------------------------------------------------def evaluate(model, data_loader, device, loss_fn):"""评估模型并返回损失和准确率:model: 创建的模型data_loader: 测试或验证集加载器device: 训练模型可用的设备(CPU或CUDA)loss_fn: 定义的损失函数"""model.eval()total_loss = 0.0correct = 0total = 0with torch.no_grad():for inputs, labels in data_loader:inputs, labels = inputs.to(device), labels.to(device)outputs = model(inputs)loss = loss_fn(outputs, labels)total_loss += loss.item()_, predicted = outputs.max(1)total += labels.size(0)correct += predicted.eq(labels).sum().item()val_loss = total_loss / len(data_loader)val_acc = correct / totalreturn val_loss, val_acc# -------------------------------------------------------------------def plot_comparision_result(model):"""绘制训练和验证集准确率和损失的对比图:model: 创建的模型"""fig, axs = plt.subplots(2, 1, figsize=(10, 12))# 绘制训练和验证集的准确率axs[0].plot(model['history']['train_acc'], color="red", marker="o")axs[0].plot(model['history']['val_acc'], color="blue", marker="h")axs[0].set_title('训练集和验证集准确率对比')axs[0].set_ylabel('准确率')axs[0].set_xlabel('轮次')axs[0].legend(['训练集', '验证集'], loc="lower right")# 绘制训练和验证集的损失axs[1].plot(model['history']['train_loss'], color="red", marker="o")axs[1].plot(model['history']['val_loss'], color="blue", marker="h")axs[1].set_title('训练集和验证集损失对比')axs[1].set_ylabel('损失')axs[1].set_xlabel('轮次')axs[1].legend(['训练集', '验证集'], loc="upper right")plt.tight_layout()plt.show()# -------------------------------------------------------------------# 定义函数以创建包含实际标签和预测标签的两个列表
def get_ture_and_pred_labels(dataloader, model):"""获取包含实际标签和预测标签的两个列表,用于混淆矩阵:dataloader: 数据加载器model: 创建的模型"""i = 0y_true = []y_pred = []for images, labels in dataloader:images = images.to(device)labels = labels.numpy()outputs = model(images)_, pred = torch.max(outputs.data, 1)pred = pred.detach().cpu().numpy()y_true = np.append(y_true, labels)y_pred = np.append(y_pred, pred)return y_true, y_pred# ------------------------------------------------------------------def plot_confusion_matrix(cm, classes,title='Confusion matrix',cmap=plt.cm.Blues):"""绘制混淆矩阵:cm(array): 混淆矩阵classes(dictionary): 目标类别(key=分类类型,value=数值类型)"""plt.figure(figsize=(10,7))plt.grid(False)plt.imshow(cm, interpolation='nearest', cmap=cmap)plt.title(title)plt.colorbar()tick_marks = np.arange(len(classes))plt.xticks(tick_marks, [f"{value}={key}" for key , value in classes.items()], rotation=45)plt.yticks(tick_marks, [f"{value}={key}" for key , value in classes.items()])thresh = cm.max() / 2.for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):plt.text(j, i, f"{cm[i,j]}\n{cm[i,j]/np.sum(cm)*100:.2f}%",horizontalalignment="center",color="white" if cm[i, j] > thresh else "black")plt.ylabel('实际值')plt.xlabel('预测值')plt.tight_layout()plt.show()

代码的作用:

  1. train 函数

    • 训练模型并记录训练和验证集的损失和准确率。
    • 实现早停机制以防止过拟合。
  2. evaluate 函数

    • 评估模型在给定数据集上的表现,返回损失和准确率。
  3. plot_comparision_result 函数

    • 绘制训练和验证集的准确率和损失随训练轮次变化的对比图。
  4. get_ture_and_pred_labels 函数

    • 获取实际标签和预测标签的列表,用于计算混淆矩阵。
  5. plot_confusion_matrix 函数

    • 绘制混淆矩阵以评估分类模型的性能,显示分类结果的准确性。

网络结构定义

# 定义第二个卷积神经网络模型:包含两个卷积层和两个池化层
class Model(nn.Module):def __init__(self, dim_output):super().__init__()self.conv1 = nn.Conv2d(3, 6, 5)  # 第一个卷积层,输入通道数为3(RGB图像),输出通道数为6,卷积核大小为5x5self.pool = nn.MaxPool2d(2, 2)  # 最大池化层,窗口大小为2x2self.conv2 = nn.Conv2d(6, 16, 5)  # 第二个卷积层,输入通道数为6,输出通道数为16,卷积核大小为5x5self.fc1 = nn.Linear(16 * 59 * 59, 120)  # 第一个全连接层,输入维度为16*59*59,输出维度为120self.fc2 = nn.Linear(120, 84)  # 第二个全连接层,输入维度为120,输出维度为84self.fc3 = nn.Linear(84, dim_output)  # 第三个全连接层,输入维度为84,输出维度为类别数def forward(self, x):x = self.pool(F.relu(self.conv1(x)))  # 第一个卷积层后接ReLU激活函数和池化层x = self.pool(F.relu(self.conv2(x)))  # 第二个卷积层后接ReLU激活函数和池化层x = torch.flatten(x, 1)  # 展平操作,展平所有维度除了批量维度x = F.relu(self.fc1(x))  # 第一个全连接层后接ReLU激活函数x = F.relu(self.fc2(x))  # 第二个全连接层后接ReLU激活函数x = self.fc3(x)  # 第三个全连接层return xmodel_ = Model(5)  # 实例化模型,类别数为5summary(model_, (3, 250, 250))  # 打印模型结构和参数信息,输入图像尺寸为3x250x250
  1. 定义卷积神经网络模型

    • __init__ 方法中定义了两个卷积层、两个池化层和三个全连接层。
    • conv1:第一个卷积层,输入通道数为3,输出通道数为6,卷积核大小为5x5。
    • pool:最大池化层,窗口大小为2x2。
    • conv2:第二个卷积层,输入通道数为6,输出通道数为16,卷积核大小为5x5。
    • fc1:第一个全连接层,输入维度为165959,输出维度为120。
    • fc2:第二个全连接层,输入维度为120,输出维度为84。
    • fc3:第三个全连接层,输入维度为84,输出维度为类别数(即输出维度)。
  2. 定义前向传播

    • forward 方法定义了前向传播过程。
    • 输入图像依次通过卷积层、激活函数、池化层、展平操作和全连接层。
    • 最后输出的结果用于分类任务。
  3. 实例化模型

    • model_ = Model(5):实例化模型,类别数为5。
  4. 显示模型结构和参数信息

    • summary(model_, (3, 250, 250)):使用 torchsummary 显示模型的结构和参数信息,输入图像尺寸为3x250x250。

代码的作用:

这段代码定义了一个用于图像分类的卷积神经网络模型,并显示了模型的结构和参数信息。这有助于了解模型的层次结构和参数量,为后续的模型训练和评估做准备。

定义损失函数和优化器,并训练模型

# define a Loss function and optimizer for model_2
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.Adam(model_.parameters(), lr=0.001)# train model_
history_2, best_model_weights_2 = train(model_, train_loader, val_loader,device, loss_fn, optimizer, num_epochs=5, patience=5)

 模型可视化评估

size_histories = {}# 存储训练结果
size_histories['Model_'] = {'history': history_2, 'weights': best_model_weights_2}# 绘制模型在每个训练轮次的准确率和损失图
plot_comparision_result(size_histories['Model_'])# 检查混淆矩阵进行错误分析
y_true, y_pred = get_ture_and_pred_labels(val_loader, model_)print(classification_report(y_true, y_pred), '\n\n')
cm = confusion_matrix(y_true, y_pred)classes = {"Arborio": 0,"Basmati": 1,"Ipsala": 2,"Jasmine": 3,"Karacadag": 4,
}plot_confusion_matrix(cm, classes, title='Confusion matrix', cmap=plt.cm.Blues)
  • 存储训练结果

    • 初始化一个字典 size_histories 用于存储不同模型的训练结果。
    • Model_ 模型的训练历史记录和最佳模型权重存储在 size_histories['Model_'] 中。
  • 绘制模型的准确率和损失图

    • 调用 plot_comparision_result 函数,绘制模型在每个训练轮次的准确率和损失图。该函数将绘制训练集和验证集的准确率和损失随训练轮次变化的对比图,以便直观地评估模型的性能。
  • 检查混淆矩阵进行错误分析

    • 使用 get_ture_and_pred_labels 函数获取验证集中真实标签和预测标签的列表 y_truey_pred
    • 打印分类报告 classification_report(y_true, y_pred),显示每个类别的精度、召回率和F1分数。
    • 计算混淆矩阵 cm,显示模型在验证集上的分类错误情况。
    • 定义类别名称和对应的数值标签字典 classes
    • 调用 plot_confusion_matrix 函数,绘制混淆矩阵图,显示各类别的分类结果。

代码的作用:

这段代码将模型的训练结果进行存储,并通过绘制准确率和损失图帮助评估模型在训练过程中的表现。通过分类报告和混淆矩阵,可以详细分析模型在验证集上的分类效果,识别模型在不同类别上的分类准确性以及存在的错误,从而为模型的优化提供依据。这种详细的错误分析对于提高模型的性能和泛化能力具有重要意义。

 

 

下载地址:

python深度学习pytorch水稻图像分类完整案例

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

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

相关文章

【源码】多语言H5聊天室/thinkphp多国语言即时通讯/H5聊天室源码/在线聊天/全开源

多语言聊天室系统&#xff0c;可当即时通讯用&#xff0c;系统默认无需注册即可进入群聊天&#xff0c;全开源 【海外聊天室】多语言H5聊天室/thinkphp多国语言即时通讯/H5聊天室源码/在线聊天/全开源 - 吾爱资源网

每日5题Day13 - LeetCode 61 - 65

每一步向前都是向自己的梦想更近一步&#xff0c;坚持不懈&#xff0c;勇往直前&#xff01; 第一题&#xff1a;61. 旋转链表 - 力扣&#xff08;LeetCode&#xff09; /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;…

STM32学习和实践笔记(32):电容触摸按键实验

1.电容触摸按键原理介绍 触摸按键与传统的机械按键相比&#xff0c;不仅美观而且耐用、寿命长&#xff0c;它颠覆了传统意义上的机械按键控制&#xff0c;只要轻轻触摸&#xff0c;就可以实现按键开关的控制、量化调节甚至方向控制。触摸按键已广泛应用于手机、DVD、洗衣机等消…

宿舍管理系统带文档java项目基于springboot+vue的宿舍管理系统

文章目录 宿舍管理系统一、项目演示二、项目介绍三、八千字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码和8000字论文参考&#xff08;9.9&#xffe5;带走&#xff09; 宿舍管理系统 一、项目演示 宿舍管理系统 二、项目介绍 基于springbootvue的前后端分…

MVC、MVP 和 MVVM 架构总结

MVC、MVP 和 MVVM 是常见的软件架构模式&#xff0c;主要用于组织应用程序的结构&#xff0c;特别是在用户界面和业务逻辑之间进行分离。以下是对它们的详细解释&#xff0c;包括它们的差异、优缺点。 MVC&#xff08;Model-View-Controller&#xff09; 结构 Model&#xf…

在长窗口时代,RAG技术是否仍然必要?

自从谷歌推出 Gemini 1.5 Pro&#xff0c;行业内部对于 RAG 的讨论就不绝于耳。 Gemini 1.5 Pro 的性能确实令人瞩目。根据谷歌公布的技术文档&#xff0c;该系统能够稳定处理长达 100 token 的内容&#xff0c;相当于一小时的视频、十一小时的音频、超过三万行的代码或七十万…

【VTKExamples::Utilities】第十七期 ZBuffer

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例ZBuffer,并解析接口vtkWindowToImageFilter,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ…

C语言文件操作:打开关闭,读写

程序文件 源程序文件&#xff08;后缀为.c&#xff09; 目标文件&#xff08;Windows环境后缀为.obj&#xff09; 可执行文件&#xff08;Windows环境后缀为.exe&#xff09; fputc FILE* pf fopen("test.txt","w");if (pf NULL){printf("%s\n"…

深入理解Qt计算器应用的构建过程

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、数字按钮的信号与槽函数连接 二、运算符按钮的信号与槽函数连接 三、特殊按钮的信号与…

红外超声波雷达测距(water)

文章目录 一 RS-232二 RS485三 Modbus四 stm32多路超声波测距4.1 设计方案4.2 代码 参考资料总结 实验要求 一. 采用stm32F103和HC-SR04超声波模块&#xff0c; 使用标准库或HAL库 定时器中断&#xff0c;完成1或2路的超声波障碍物测距功能。 1&#xff09;测试数据包含噪声&am…

【Linux】线程ID

大致草稿—————————— 思维导图 学习目标 一、线程ID的理解 1.1 引出对tid的理解 我们先来创建一个线程复习一下线程的函数&#xff1a; pthread_t tid; // 创建一个线程 pthread_create(&tid, nullptr, threadrun, (void*)"thread-1"); // 打印出…

怎么花草识别?方法有三种!

怎么花草识别&#xff1f;在这个五彩斑斓的世界里&#xff0c;花草是我们生活中不可或缺的一部分。它们点缀着我们的环境&#xff0c;为我们带来无尽的美丽与惊喜。然而&#xff0c;面对众多的花草种类&#xff0c;你是否曾感到困惑和迷茫&#xff0c;不知道如何识别它们&#…

VIO System 丨适用于控制器开发前期的测试系统

VIO综述 嵌入式软件的HIL测试需要复杂的测试系统及完整的ECU硬件&#xff0c;这导致通常只能在开发流程的后期阶段进行测试。全新推出的低成本解决方案VIO System&#xff0c;使得在开发前期不仅可以进行总线通讯测试&#xff0c;也可以同时进行I/O信号测试。 该系统旨在通过…

LabVIEW版本控制

LabVIEW作为一种流行的图形化编程环境&#xff0c;在软件开发中广泛应用。有效地管理版本控制对于确保软件的可靠性和可维护性至关重要。LabVIEW提供了多种方式来管理VI和应用程序的修订历史&#xff0c;以满足不同规模和复杂度的项目需求。 LabVIEW中的VI修订历史 LabVIEW内置…

docker安装Mysql5.7版本

首先Linux系统已经安装好了docker应用。 1.搜索镜像 docker search mysql 2.拉取5.7的镜像 总之,选starts最多的那个就对了。 docker pull mysql:5.7 ~ docker pull mysql:5.7 5.7: Pulling from library/mysql fc7181108d40: Downloading [============> …

mysql创建数据表----centos7.9

mysql创建数据表 查看存在的表 show tables;我这里还未创建任何表所以是这样的 如有是这样 若没有表需要先创建一个表 CREATE DATABASE tb_your_name&#xff1b;创建字段及属性 CREATE TABLE tb_laws_regulations (id INT AUTO_INCREMENT PRIMARY KEY, -- 文件唯…

柯桥外贸俄语哪里可以学,零基础俄语培训

Де́лать 做 из му́хи 从苍蝇 слона́ 大象 我觉得汉语里有一个很合适的词来形容&#xff1a; Де́лать из му́хи слона́ 就是 小题大做&#xff0c;本来是一件很小的事&#xff0c;却把它形容成天大的事一样 Хвтит де́…

【UE5.1 角色练习】10-物体抬升、抛出技能 - part2

目录 前言 效果 步骤 一、让物体缓慢的飞向手掌 二、向着鼠标方向发射物体 前言 在上一篇&#xff08;【UE5.1 角色练习】08-物体抬升、抛出技能 - part1&#xff09;的基础上继续完成角色将物体吸向手掌&#xff0c;然后通过鼠标点击的方向来发射物体的功能。 效果 步骤…

代码随想录算法训练营第三十二 | ● 122.买卖股票的最佳时机II ● 55. 跳跃游戏 ● 45.跳跃游戏II

122.买卖股票的最佳时机II 讲解链接&#xff1a;https://programmercarl.com/1005.K%E6%AC%A1%E5%8F%96%E5%8F%8D%E5%90%8E%E6%9C%80%E5%A4%A7%E5%8C%96%E7%9A%84%E6%95%B0%E7%BB%84%E5%92%8C.html 简单思路&#xff1a;逐个计算连续两天的股票差值&#xff0c;sum初始为零&…

【并查集】专题练习

题目列表 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 模板 836. 合并集合 - AcWing题库 #include<bits/stdc.h> using lllong long; //#define int ll const int N1e510,mod1e97; int n,m; int p[N],sz[N]; int find(int a) {if(p[a]!a) p[a]find(p[a]);return p[a…