基于OpenCV图像分割与PyTorch的增强图像分类方案

在图像分类任务中,背景噪声和复杂场景常常会对分类准确率产生负面影响。为了应对这一挑战,本文介绍了一种结合OpenCV图像分割与PyTorch深度学习框架的增强图像分类方案。通过先对图像进行分割提取感兴趣区域(Region of Interest,ROI),再进行分类,可以有效减少背景干扰,突出关键特征,从而提高分类准确率。该方案在多种复杂场景下表现出色,尤其适用于图像背景复杂或包含多个对象的情况。

一、方案概述

本方案的核心在于将OpenCV的图像分割技术与PyTorch的深度学习模型相结合。具体来说,我们使用OpenCV提供的选择性搜索(Selective Search)和GrabCut两种分割算法来提取图像中的主要区域,然后将这些区域输入到基于PyTorch构建的ResNet50分类模型中进行训练和分类。为了实现这一流程,我们设计了一个完整的Python代码框架,涵盖了数据加载、分割、模型构建、训练、微调、评估和预测等各个环节。

二、代码实现

以下是该增强图像分类方案的完整代码实现,基于Python语言,使用了OpenCV、PyTorch、torchvision等常用库。在运行代码之前,请确保已安装这些库,并根据实际需求调整代码中的数据路径等参数。

1. 导入所需库

import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, confusion_matrix
import cv2
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from torchvision import models, transforms
from torchvision.models import resnet50, ResNet50_Weights

2. 定义带分割功能的自定义图像数据集类

class SegmentedImageDataset(Dataset):"""带分割功能的自定义图像数据集"""def __init__(self, image_paths, labels, img_size=(224, 224), transform=None, segmentation_method='selective_search', use_segmentation=True):self.image_paths = image_pathsself.labels = labelsself.img_size = img_sizeself.transform = transform or self._default_transform()self.segmentation_method = segmentation_methodself.use_segmentation = use_segmentation# 初始化分割器if self.use_segmentation:if self.segmentation_method == 'selective_search':self.ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()elif self.segmentation_method == 'grabcut':pass  # GrabCut不需要预初始化else:raise ValueError(f"不支持的分割方法: {segmentation_method}")def _default_transform(self):"""默认的图像转换"""return transforms.Compose([transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])def _segment_image(self, img):"""使用OpenCV分割图像,返回主要区域"""if not self.use_segmentation:return imgtry:if self.segmentation_method == 'selective_search':# 使用选择性搜索self.ss.setBaseImage(img)self.ss.switchToSelectiveSearchFast()rects = self.ss.process()# 选择最大的几个区域if len(rects) > 0:areas = [(x, y, w, h, w*h) for x, y, w, h in rects]areas.sort(key=lambda x: x[4], reverse=True)# 获取最大区域x, y, w, h, _ = areas[0]roi = img[y:y+h, x:x+w]# 如果ROI太小,返回原图if roi.size < img.size * 0.1:return imgelse:return roielse:return imgelif self.segmentation_method == 'grabcut':# 使用GrabCut分割mask = np.zeros(img.shape[:2], np.uint8)bgdModel = np.zeros((1, 65), np.float64)fgdModel = np.zeros((1, 65), np.float64)# 定义一个矩形,包含前景对象rect = (50, 50, img.shape[1]-100, img.shape[0]-100)# 应用GrabCutcv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)# 创建前景掩码mask2 = np.where((mask==2)|(mask==0), 0, 1).astype('uint8')img = img*mask2[:,:,np.newaxis]# 提取前景区域coords = cv2.findNonZero(mask2)if coords is not None:x, y, w, h = cv2.boundingRect(coords)roi = img[y:y+h, x:x+w]if roi.size > 0:return roireturn imgexcept Exception as e:print(f"分割图像时出错: {e}")return imgdef __len__(self):return len(self.image_paths)def __getitem__(self, idx):img_path = self.image_paths[idx]label = self.labels[idx]# 读取并处理图像img = cv2.imread(img_path)if img is None:# 如果图像读取失败,返回空白图像和标签img = np.zeros((self.img_size[0], self.img_size[1], 3), dtype=np.uint8)else:# 图像分割img = self._segment_image(img)# 调整图像大小img = cv2.resize(img, self.img_size)# 转换颜色空间(BGR到RGB)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 应用转换if self.transform:img = self.transform(img)return img, label, img_path

3. 定义图像分类器类

class ImageClassifier:def __init__(self, data_dir, img_size=(224, 224), batch_size=32, num_classes=None):"""初始化图像分类器"""self.data_dir = data_dirself.img_size = img_sizeself.batch_size = batch_sizeself.num_classes = num_classesself.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")self.model = Noneself.label_to_index = Noneself.index_to_label = Nonedef load_data(self, test_size=0.2, val_size=0.2, shuffle=True):"""加载图像数据并分割为训练集、验证集和测试集"""# 收集所有图像路径和标签image_paths = []labels = []for class_name in os.listdir(self.data_dir):class_dir = os.path.join(self.data_dir, class_name)if not os.path.isdir(class_dir):continuefor img_name in os.listdir(class_dir):img_path = os.path.join(class_dir, img_name)if img_path.lower().endswith(('.png', '.jpg', '.jpeg')):image_paths.append(img_path)labels.append(class_name)# 如果未指定类别数,自动计算if self.num_classes is None:self.num_classes = len(set(labels))# 创建标签映射unique_labels = sorted(list(set(labels)))self.label_to_index = {label: idx for idx, label in enumerate(unique_labels)}self.index_to_label = {idx: label for label, idx in self.label_to_index.items()}# 转换标签为数字y = np.array([self.label_to_index[label] for label in labels])# 分割数据集X_train_paths, X_test_paths, y_train, y_test = train_test_split(image_paths, y, test_size=test_size, random_state=42, shuffle=shuffle, stratify=y)X_train_paths, X_val_paths, y_train, y_val = train_test_split(X_train_paths, y_train, test_size=val_size/(1-test_size), random_state=42, shuffle=shuffle, stratify=y_train)print(f"训练集大小: {len(X_train_paths)}")print(f"验证集大小: {len(X_val_paths)}")print(f"测试集大小: {len(X_test_paths)}")return X_train_paths, X_val_paths, X_test_paths, y_train, y_val, y_testdef build_model(self, dropout_rate=0.5):"""构建基于ResNet50的分类模型"""# 加载预训练的ResNet50模型model = resnet50(weights=ResNet50_Weights.IMAGENET1K_V2)# 冻结预训练模型的所有层for param in model.parameters():param.requires_grad = False# 修改最后的全连接层以适应我们的分类任务num_ftrs = model.fc.in_featuresmodel.fc = nn.Sequential(nn.Dropout(dropout_rate),nn.Linear(num_ftrs, self.num_classes))self.model = model.to(self.device)print("模型结构:")print(self.model)return self.modeldef train_model(self, X_train_paths, X_val_paths, y_train, y_val, epochs=10, lr=0.001, patience=3, model_path='best_model.pth',segmentation_method='selective_search', use_segmentation=True):"""训练模型"""# 创建数据加载器train_dataset = SegmentedImageDataset(X_train_paths, y_train, self.img_size,segmentation_method=segmentation_method,use_segmentation=use_segmentation)val_dataset = SegmentedImageDataset(X_val_paths, y_val, self.img_size,segmentation_method=segmentation_method,use_segmentation=use_segmentation)train_loader = DataLoader(train_dataset, batch_size=self.batch_size, shuffle=True)val_loader = DataLoader(val_dataset, batch_size=self.batch_size, shuffle=False)# 定义损失函数和优化器criterion = nn.CrossEntropyLoss()optimizer = optim.Adam(self.model.fc.parameters(), lr=lr)# 学习率调度器scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=patience//2)best_val_acc = 0.0early_stop_counter = 0train_losses = []val_losses = []train_accs = []val_accs = []for epoch in range(epochs):# 训练阶段self.model.train()train_loss = 0.0train_correct = 0train_total = 0for inputs, labels, _ in train_loader:inputs, labels = inputs.to(self.device), labels.to(self.device)optimizer.zero_grad()outputs = self.model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()_, predicted = outputs.max(1)train_total += labels.size(0)train_correct += predicted.eq(labels).sum().item()train_loss /= len(train_loader)train_acc = 100.0 * train_correct / train_total# 验证阶段self.model.eval()val_loss = 0.0val_correct = 0val_total = 0with torch.no_grad():for inputs, labels, _ in val_loader:inputs, labels = inputs.to(self.device), labels.to(self.device)outputs = self.model(inputs)loss = criterion(outputs, labels)val_loss += loss.item()_, predicted = outputs.max(1)val_total += labels.size(0)val_correct += predicted.eq(labels).sum().item()val_loss /= len(val_loader)val_acc = 100.0 * val_correct / val_total# 记录历史train_losses.append(train_loss)val_losses.append(val_loss)train_accs.append(train_acc)val_accs.append(val_acc)# 打印进度print(f'Epoch {epoch+1}/{epochs} | 'f'Train Loss: {train_loss:.4f} | Train Acc: {train_acc:.2f}% | 'f'Val Loss: {val_loss:.4f} | Val Acc: {val_acc:.2f}%')# 保存最佳模型if val_acc > best_val_acc:print(f'验证集准确率提高 ({best_val_acc:.2f}% --> {val_acc:.2f}%),保存模型...')torch.save(self.model.state_dict(), model_path)best_val_acc = val_accearly_stop_counter = 0else:early_stop_counter += 1print(f'早停计数器: {early_stop_counter}/{patience}')if early_stop_counter >= patience:print(f'早停在第 {epoch+1} 轮')break# 调整学习率scheduler.step(val_loss)# 加载最佳模型self.model.load_state_dict(torch.load(model_path))history = {'train_loss': train_losses,'val_loss': val_losses,'train_acc': train_accs,'val_acc': val_accs}return historydef fine_tune_model(self, X_train_paths, X_val_paths, y_train, y_val, lr=1e-5, epochs=10, patience=3, model_path='finetuned_model.pth',segmentation_method='selective_search', use_segmentation=True):"""微调模型"""# 解冻部分层进行微调for param in self.model.parameters():param.requires_grad = True# 创建数据加载器train_dataset = SegmentedImageDataset(X_train_paths, y_train, self.img_size,segmentation_method=segmentation_method,use_segmentation=use_segmentation)val_dataset = SegmentedImageDataset(X_val_paths, y_val, self.img_size,segmentation_method=segmentation_method,use_segmentation=use_segmentation)train_loader = DataLoader(train_dataset, batch_size=self.batch_size, shuffle=True)val_loader = DataLoader(val_dataset, batch_size=self.batch_size, shuffle=False)# 定义损失函数和优化器criterion = nn.CrossEntropyLoss()optimizer = optim.Adam(self.model.parameters(), lr=lr)# 学习率调度器scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=patience//2)best_val_acc = 0.0early_stop_counter = 0train_losses = []val_losses = []train_accs = []val_accs = []print("开始微调模型...")for epoch in range(epochs):# 训练阶段self.model.train()train_loss = 0.0train_correct = 0train_total = 0for inputs, labels, _ in train_loader:inputs, labels = inputs.to(self.device), labels.to(self.device)optimizer.zero_grad()outputs = self.model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()_, predicted = outputs.max(1)train_total += labels.size(0)train_correct += predicted.eq(labels).sum().item()train_loss /= len(train_loader)train_acc = 100.0 * train_correct / train_total# 验证阶段self.model.eval()val_loss = 0.0val_correct = 0val_total = 0with torch.no_grad():for inputs, labels, _ in val_loader:inputs, labels = inputs.to(self.device), labels.to(self.device)outputs = self.model(inputs)loss = criterion(outputs, labels)val_loss += loss.item()_, predicted = outputs.max(1)val_total += labels.size(0)val_correct += predicted.eq(labels).sum().item()val_loss /= len(val_loader)val_acc = 100.0 * val_correct / val_total# 记录历史train_losses.append(train_loss)val_losses.append(val_loss)train_accs.append(train_acc)val_accs.append(val_acc)# 打印进度print(f'Epoch {epoch+1}/{epochs} | 'f'Train Loss: {train_loss:.4f} | Train Acc: {train_acc:.2f}% | 'f'Val Loss: {val_loss:.4f} | Val Acc: {val_acc:.2f}%')# 保存最佳模型if val_acc > best_val_acc:print(f'验证集准确率提高 ({best_val_acc:.2f}% --> {val_acc:.2f}%),保存模型...')torch.save(self.model.state_dict(), model_path)best_val_acc = val_accearly_stop_counter = 0else:early_stop_counter += 1print(f'早停计数器: {early_stop_counter}/{patience}')if early_stop_counter >= patience:print(f'早停在第 {epoch+1} 轮')break# 调整学习率scheduler.step(val_loss)# 加载最佳模型self.model.load_state_dict(torch.load(model_path))history = {'train_loss': train_losses,'val_loss': val_losses,'train_acc': train_accs,'val_acc': val_accs}return historydef evaluate_model(self, X_test_paths, y_test, segmentation_method='selective_search', use_segmentation=True):"""评估模型"""# 创建测试数据加载器test_dataset = SegmentedImageDataset(X_test_paths, y_test, self.img_size,segmentation_method=segmentation_method,use_segmentation=use_segmentation)test_loader = DataLoader(test_dataset, batch_size=self.batch_size, shuffle=False)self.model.eval()test_loss = 0.0test_correct = 0test_total = 0all_labels = []all_predictions = []with torch.no_grad():for inputs, labels, _ in test_loader:inputs, labels = inputs.to(self.device), labels.to(self.device)outputs = self.model(inputs)loss = nn.CrossEntropyLoss()(outputs, labels)test_loss += loss.item()_, predicted = outputs.max(1)test_total += labels.size(0)test_correct += predicted.eq(labels).sum().item()all_labels.extend(labels.cpu().numpy())all_predictions.extend(predicted.cpu().numpy())test_loss /= len(test_loader)test_acc = 100.0 * test_correct / test_totalprint(f"测试集损失: {test_loss:.4f}, 准确率: {test_acc:.2f}%")# 生成分类报告print("\n分类报告:")print(classification_report(all_labels, all_predictions,target_names=[self.index_to_label[i] for i in range(self.num_classes)]))# 计算混淆矩阵cm = confusion_matrix(all_labels, all_predictions)print("\n混淆矩阵:")print(cm)return test_loss, test_acc, cmdef predict_image(self, img_path, segmentation_method='selective_search', use_segmentation=True):"""预测单张图像"""# 创建一个只包含这张图像的数据集dataset = SegmentedImageDataset([img_path], [0], self.img_size,segmentation_method=segmentation_method,use_segmentation=use_segmentation)data_loader = DataLoader(dataset, batch_size=1, shuffle=False)self.model.eval()with torch.no_grad():for inputs, _, _ in data_loader:inputs = inputs.to(self.device)outputs = self.model(inputs)probabilities = torch.nn.functional.softmax(outputs, dim=1)confidence, predicted = torch.max(probabilities, 1)class_idx = predicted.item()confidence = confidence.item()return self.index_to_label[class_idx], confidencereturn None, 0.0def visualize_history(self, history):"""可视化训练历史"""plt.figure(figsize=(12, 4))# 绘制准确率曲线plt.subplot(1, 2, 1)plt.plot(history['train_acc'])plt.plot(history['val_acc'])plt.title('模型准确率')plt.ylabel('准确率 (%)')plt.xlabel('训练轮次')plt.legend(['训练', '验证'], loc='lower right')# 绘制损失曲线plt.subplot(1, 2, 2)plt.plot(history['train_loss'])plt.plot(history['val_loss'])plt.title('模型损失')plt.ylabel('损失')plt.xlabel('训练轮次')plt.legend(['训练', '验证'], loc='upper right')plt.tight_layout()plt.show()

4. 使用示例

if __name__ == "__main__":# 设置数据目录(应包含按类别分好的子文件夹)data_directory = "path/to/your/dataset"  # 请替换为实际数据目录# 初始化分类器classifier = ImageClassifier(data_dir=data_directory, img_size=(224, 224), batch_size=32)# 加载数据X_train, X_val, X_test, y_train, y_val, y_test = classifier.load_data()# 构建模型model = classifier.build_model()# 训练模型(使用分割)print("开始基础训练...")history = classifier.train_model(X_train, X_val, y_train, y_val, epochs=5,segmentation_method='selective_search',  # 可选: 'grabcut'use_segmentation=True)# 可视化训练历史classifier.visualize_history(history)# 微调模型print("开始微调...")fine_tune_history = classifier.fine_tune_model(X_train, X_val, y_train, y_val, epochs=5,segmentation_method='selective_search',use_segmentation=True)# 可视化微调历史classifier.visualize_history(fine_tune_history)# 评估模型classifier.evaluate_model(X_test, y_test,segmentation_method='selective_search',use_segmentation=True)# 预测示例example_img_path = "path/to/test/image.jpg"  # 请替换为实际图像路径if os.path.exists(example_img_path):class_name, confidence = classifier.predict_image(example_img_path,segmentation_method='selective_search',use_segmentation=True)print(f"\n预测结果: {class_name}, 置信度: {confidence:.2f}")

三、方案改进说明

本方案在以下几个方面进行了改进,以提升图像分类的准确率和鲁棒性:

1. 集成多种分割方法

  • 支持选择性搜索(Selective Search)和GrabCut两种分割算法:选择性搜索适合复杂场景,能够生成多个候选区域;GrabCut则在已知对象大致位置时,能提供更精确的前景分割。用户可以根据实际应用场景选择合适的分割方法。
  • 通过参数控制是否使用分割功能:在数据加载阶段,用户可以通过设置use_segmentation参数来决定是否对图像进行分割。这为对比实验提供了便利,可以直观地观察到分割对分类效果的影响。
  • 自动提取图像中的主要区域:分割算法会自动识别并提取图像中的感兴趣区域,减少背景噪声的干扰,使分类模型能够更专注于关键特征,从而提高分类准确率。

2. 优化的数据处理流程

  • 创建了专门的SegmentedImageDataset类处理分割逻辑:该类继承自PyTorch的Dataset类,将图像分割与数据加载紧密结合。在数据加载过程中,实时对图像进行分割处理,确保每个批次的数据都是经过分割优化的,无需预先对整个数据集进行分割,节省了存储空间和预处理时间。
  • 在数据加载过程中实时进行图像分割:这种实时处理的方式使得数据处理更加灵活高效,能够根据不同的分割方法和参数动态调整数据,适应不同的训练需求。
  • 保留了原始的无分割处理路径:即使在启用了分割功能的情况下,如果分割过程中出现异常或分割结果不理想,代码会自动回退到原始图像,保证数据的完整性,避免因分割错误导致训练中断或数据丢失。

3. 灵活的参数配置

  • 可选择不同的分割算法:在训练、微调、评估和预测等各个阶段,用户都可以通过segmentation_method参数指定使用选择性搜索还是GrabCut进行分割,方便针对不同类型的图像数据进行优化。
  • 可在不同阶段分别控制是否使用分割:例如,在训练阶段使用分割来提高模型对关键特征的学习能力,而在预测阶段根据实际情况决定是否使用分割,以达到最佳的分类效果和效率平衡。

四、分割方法选择建议

  • 选择性搜索(Selective Search):适用于图像中包含多个对象或场景较为复杂的场景。它能够生成多个候选区域,帮助模型更好地识别和定位关键对象,从而提高分类准确率。
  • GrabCut:当图像中对象的位置相对固定且已知时,GrabCut可以提供更精确的前景分割。通过用户提供的初始矩形框,GrabCut能够更准确地分离前景和背景,减少背景噪声对分类的干扰。

五、使用提示

  1. 选择合适的分割方法:对于大多数场景,推荐先尝试选择性搜索方法,因为它对复杂场景的适应性更强。如果你的图像中对象位置较固定,可以考虑使用GrabCut来获得更精确的分割结果。
  2. 对比实验:可以通过设置use_segmentation=False来对比使用分割与不使用分割的效果差异。这有助于评估分割对分类准确率的实际提升效果,从而为实际应用提供参考依据。
  3. 权衡效率与准确率:分割会增加一定的处理时间,尤其是选择性搜索算法。在实际应用中,需要根据具体需求和资源情况权衡效率与准确率。如果对实时性要求较高,可以适当降低分割的复杂度或选择更高效的分割方法。

六、总结

本文介绍的基于OpenCV图像分割与PyTorch深度学习框架的增强图像分类方案,在处理复杂场景图像分类任务时表现出色。通过集成多种分割方法、优化数据处理流程和灵活的参数配置,该方案能够有效减少背景噪声,突出关键特征,从而显著提高分类准确率。无论是学术研究还是实际应用,这一方案都具有较高的实用价值和参考意义。希望本文的介绍和代码实现能够为从事图像分类相关工作的读者提供一些帮助和启发。

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

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

相关文章

华为云对象存储OBS 支持安卓/iOS/鸿蒙UTS组件

华为云对象存储OBS 支持安卓/iOS/鸿蒙UTS组件 介绍使用前须知vue代码调用示例权限说明API调用说明初始化配置&#xff08;openClient&#xff09;创建桶&#xff08;createBucket&#xff09;列举桶&#xff08;listBuckets&#xff09;删除桶&#xff08;deleteBucket&#xf…

Buildroot 2025.05 中文手册【AI高质量翻译】

译文在 Github 仓库 和 Gitee 仓库 保持最新&#xff0c;其它平台发的文档可能不会与之同步。 希望能够共同维护这个 仓库的 Buildroot 手册 中文译文&#xff0c;帮助更多人真正深入学习理解&#xff0c;更好的工作、生活和创造。 关于 AI 提示词 以及 更多工具 的收集&#…

采用ArcGIS10.8.2 进行插值图绘制

一、最终成果图展示 二、软件下载 链接: 百度网盘 请输入提取码 密码:azay 三、软件安装 1、在安装之前需要关闭电脑的防火墙及杀毒软件 设置-隐私和安全性-Windows安全中心-防火墙和网络保护 2、软件解压 (1)【ArcGIS_Desktop_1082_180......】“以管理员身份运行”…

Python网安-zip文件暴力破解(仅供学习)

目录 源码在这里 需要的模块 准备一个密码本和需要破解的ZIP文件 一行一行地从密码文件中读取每个密码。 核心部分 注意&#xff0c;需要修改上段代码注释里的这段具有编码问题的代码&#xff1a; 源码在这里 https://github.com/Wist-fully/Attack/tree/cracker 需要的…

如何让ChatGPT模仿人类写作,降低AIGC率?

在AI技术日益普及的当下&#xff0c;ChatGPT 等大语言模型已成为许多学术与写作任务中的得力助手。然而&#xff0c;学境思源&#xff0c;随着各类“AI检测系统”的出现&#xff0c;一键生成论文初稿&#xff01;我们也遇到一个新的问题&#xff1a;如何让AI写作看起来不像AI写…

科大讯飞2025AI开发者大赛-用户新增赛道时间规则解析

根据训练集中的时间规则&#xff0c;对测试集中的数据推断用户标签&#xff08;新用户或老用户&#xff09;。 时间规则如下: 针对训练集和测试集中都存在的did&#xff1a; 找到在训练集中标记为新用户最晚的时间点&#xff0c;则测试集中对应did的数据在此时间点前全部为新用…

.NET C# async/定时任务的异步线程池调度方案最大线程数‌ = 处理器核心数 × 250

关于.NET中Threading.Timer的线程机制&#xff0c;结合线程池特性和异步协作原理分析如下&#xff1a; 一、线程复用机制 ‌共享进程级线程池‌ Threading.Timer的回调任务‌不会每次新建线程‌&#xff0c;而是提交到.NET进程全局线程池统一调度&#xff0c;该线程池与async/…

Redis 高可用分片集群:主从模式与哨兵机制详解

一、为何需要分片集群&#xff1f; 在讨论具体方案之前&#xff0c;我们先明确分片集群要解决的问题&#xff1a; 单节点瓶颈&#xff1a;无论是内存容量还是处理能力&#xff08;QPS&#xff09;&#xff0c;单个 Redis 实例都有物理上限。高可用性需求&#xff1a;单点故障…

Qt readyRead信号避坑:不产生readyRead信号的解决方法

Qt readyRead信号避坑&#xff1a;不产生readyRead信号的解决方法 引言一、QSerialport的readyRead1.1 版本问题1.2 缓存问题1.3 阻塞问题 二、Q(Tcp)Socket的readyRead2.1 阻塞问题2.2 运行一段时间&#xff0c;突然不发信号2.3 和具体数据有关&#xff1f; 引言 目前没遇到相…

大事件项目记录10-文章分类接口开发-更新文章分类

四、更新文章分类。 CategoryController.java&#xff1a; PutMappingpublic Result update(RequestBody Validated Category category){categoryService.update(category);return Result.success();} CategoryService&#xff1a; //更新分类void update(Category category); …

AI接口使用–阿里云百炼

原文地址&#xff1a;AI接口使用–阿里云百炼 – 无敌牛 欢迎参观我的个人博客&#xff1a;无敌牛 – 技术/著作/典籍/分享等 最近开发了一个抖音AI起名小程序&#xff0c;已经在抖音上线了&#xff0c;欢迎大家来使用。其中用到了 AI文本生成 功能&#xff0c;我用的是 阿里云…

大模型之提示词工程入门——解锁与AI高效沟通的“钥匙”

一、什么是提示词工程&#xff1f; 提示词工程&#xff08;Prompt Engineering&#xff09; 是一门通过设计、优化输入文本&#xff08;Prompt&#xff09;来引导大语言模型&#xff08;LLM&#xff09;生成高质量输出的技术。它不仅是AI应用的核心环节&#xff0c;也是连接人…

智慧城市云计算大数据中心项目设计方案

第1章 总体方案设计 1.1 概述 1.2 建设目标 1.3 建设内容 1.3.1 标准规范体系编制 1.3.2 基础设施平台建设 1.3.3 数据资源平台建设 1.3.4 应用支撑平台建设 1.3.5 云管平台运维建设 1.3.6 应用上云迁移实施 1.3.7 信息安全保障建设 1.3.8 容灾备份系统建设 1.4 设…

OpenMP并行加速学习笔记2025.6.27

在OpenMP并行加速中&#xff0c;线程数&#xff08;如32、16、8&#xff09;的选择需结合硬件核心数、任务类型&#xff08;计算密集型或I/O密集型&#xff09;、负载均衡策略及线程开销综合判断。以下为具体差异分析与性能提升对比&#xff1a; 一、核心影响因素分析 1. 硬件…

对象回调和函数回调

1.对象回调&#xff1a; 对象回调原始写法&#xff0c;A调B B又回头调A package com.ldj.demo.controller;/*** User: ldj* Date: 2025/6/28* Time: 12:22* Description: 回调函数的理解 对象回调*/ public class Tr {public static void main(String[] args) {A a new A();…

Python实例题:Web 爬虫与数据可视化

目录 Python实例题 题目 要求&#xff1a; 解题思路&#xff1a; 代码实现&#xff1a; Python实例题 题目 Web 爬虫与数据可视化 要求&#xff1a; 编写一个爬虫&#xff0c;从豆瓣电影 Top250 页面&#xff08;豆瓣电影 Top 250&#xff09;抓取电影名称、评分、导演…

关于ubuntu 20.04系统安装分区和重复登录无法加载桌面的问题解决

1. 想要安装Ubuntu 20.04版本&#xff0c;有两块硬盘&#xff0c;所以在分区列表设置的格式为如下&#xff1a; 其中各个/boot 、/home的格式为如下&#xff08;Ubuntu20.04分区方案_ubuntu20.04手动分区-CSDN博客&#xff09; 2.安装完死活输完密码进不去主界面 必须禁用Nou…

26考研|数学分析:隐函数定理及其应用

前言 本章主要围绕隐函数、隐含数组的计算展开&#xff0c;本章的核心还是在于计算的运用&#xff0c;在理论层面要掌握隐函数&#xff08;隐函数组&#xff09;存在性定理&#xff0c;在计算方面&#xff0c;要掌握隐函数、隐函数组的计算方法&#xff0c;此外&#xff0c;本…

PyQtNode Editor 第三篇创建节点(节点的定义)

在 PyQtNode Editor 的开发之旅中,经过前两篇博客对基础环境搭建和核心类结构的探索,我们已经迈出了坚实的步伐。今天,我们将聚焦于node_scene文件,深入解析其中的代码逻辑。这段代码构建了Scene类,它如同整个节点编辑器的 “管理中枢”,承担着组织和协调节点、边等关键元…

通过docker安装nginx服务

nginx配置文件 https://gitee.com/Cairo-SR8/nginx-configuration.git一、安装nginx 1.1 拉去ARM镜像 docker pull registry.cn-hangzhou.aliyuncs.com/qiluo-images/linux_arm64_nginx:latest1.2 拉去x86镜像 docker pull registry.cn-hangzhou.aliyuncs.com/qiluo-images/…