基于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
英文地址,請注明出處:http://en.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/…