第95步 深度學習圖像目標檢測:Faster R-CNN建模

基于WIN10的64位系統演示

一、寫在前面

本期開始,我們學習深度學習圖像目標檢測系列。

深度學習圖像目標檢測是計算機視覺領域的一個重要子領域,它的核心目標是利用深度學習模型來識別并定位圖像中的特定目標。這些目標可以是物體、人、動物或其他可識別的實體。與傳統的圖像分類任務不同,目標檢測不僅要確定圖像中存在哪些類別的目標,還要確定它們的確切位置和尺寸。這通常是通過在圖像上繪制一個或多個邊界框來實現的,這些邊界框精確地標出了目標的位置和范圍。

二、Faster R-CNN簡介

Faster R-CNN 是一種流行的深度學習圖像目標檢測算法,由 Shaoqing Ren, Kaiming He, Ross Girshick 和 Jian Sun 在 2015 年提出。它是 R-CNN 系列模型中的一個重要里程碑,因為它提高了檢測速度,同時保持了高精度。以下是 Faster R-CNN 的主要特點和組件:

(1)區域提議網絡 (RPN):

Faster R-CNN 的核心創新是引入了一個叫做區域提議網絡 (RPN) 的組件。RPN 能夠在卷積特征圖上直接生成目標的邊界框提議,這大大減少了提議的計算時間。RPN 使用了一組固定大小和比例的錨框(anchors),對每一個錨框預測偏移量和目標存在的概率。

(2)共享卷積特征:

與其前任 Fast R-CNN 不同,Faster R-CNN 的 RPN 和最終的目標檢測都共享相同的卷積特征。這意味著圖像只需要進行一次前向傳播,從而大大提高了計算效率。

(3)ROI Pooling:

一旦得到了區域提議,Faster R-CNN 使用?ROI (Region of Interest) Pooling 技術來從每個提議中提取固定大小的特征。這確保無論提議的大小如何,都可以輸入到一個固定大小的全連接網絡中進行分類和邊界框回歸。

(4)雙任務損失:

RPN 被訓練為一個雙任務問題:分類(目標 vs. 非目標)和邊界框回歸。這種雙任務損失結構確保了 RPN 在生成提議時既考慮了準確性也考慮了定位。

總之,Faster R-CNN 通過引入區域提議網絡和共享卷積特征,大大提高了目標檢測的速度和精度,為后續的研究和應用打下了堅實的基礎。

三、數據源

來源于公共數據,文件設置如下:

大概的任務就是:用一個框框標記出MTB的位置。

四、Faster R-CNN實戰

直接上代碼:

import os
import random
import torch
import torchvision
from torchvision.models.detection import fasterrcnn_resnet50_fpn
from torchvision.transforms import functional as F
from PIL import Image
from torch.utils.data import DataLoader
import xml.etree.ElementTree as ET
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
import matplotlib.pyplot as plt
from torchvision import transforms
import albumentations as A
from albumentations.pytorch import ToTensorV2
import numpy as np# Function to parse XML annotations
def parse_xml(xml_path):tree = ET.parse(xml_path)root = tree.getroot()boxes = []for obj in root.findall("object"):bndbox = obj.find("bndbox")xmin = int(bndbox.find("xmin").text)ymin = int(bndbox.find("ymin").text)xmax = int(bndbox.find("xmax").text)ymax = int(bndbox.find("ymax").text)# Check if the bounding box is validif xmin < xmax and ymin < ymax:boxes.append((xmin, ymin, xmax, ymax))else:print(f"Warning: Ignored invalid box in {xml_path} - ({xmin}, {ymin}, {xmax}, {ymax})")return boxes# Function to split data into training and validation sets
def split_data(image_dir, split_ratio=0.8):all_images = [f for f in os.listdir(image_dir) if f.endswith(".jpg")]random.shuffle(all_images)split_idx = int(len(all_images) * split_ratio)train_images = all_images[:split_idx]val_images = all_images[split_idx:]return train_images, val_images# Dataset class for the Tuberculosis dataset
class TuberculosisDataset(torch.utils.data.Dataset):def __init__(self, image_dir, annotation_dir, image_list, transform=None):self.image_dir = image_dirself.annotation_dir = annotation_dirself.image_list = image_listself.transform = transformdef __len__(self):return len(self.image_list)def __getitem__(self, idx):image_path = os.path.join(self.image_dir, self.image_list[idx])image = Image.open(image_path).convert("RGB")xml_path = os.path.join(self.annotation_dir, self.image_list[idx].replace(".jpg", ".xml"))boxes = parse_xml(xml_path)# Check for empty bounding boxes and return Noneif len(boxes) == 0:return Noneboxes = torch.as_tensor(boxes, dtype=torch.float32)labels = torch.ones((len(boxes),), dtype=torch.int64)iscrowd = torch.zeros((len(boxes),), dtype=torch.int64)target = {}target["boxes"] = boxestarget["labels"] = labelstarget["image_id"] = torch.tensor([idx])target["iscrowd"] = iscrowd# Apply transformationsif self.transform:image = self.transform(image)return image, target# Define the transformations using torchvision
data_transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor(),  # Convert PIL image to tensortorchvision.transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # Normalize the images
])# Adjusting the DataLoader collate function to handle None values
def collate_fn(batch):batch = list(filter(lambda x: x is not None, batch))return tuple(zip(*batch))# Function to get the Mask R-CNN model
def get_model(num_classes):model = fasterrcnn_resnet50_fpn(pretrained=True)in_features = model.roi_heads.box_predictor.cls_score.in_featuresmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)return model# Function to save the model
def save_model(model, path="mmaskrcnn_mtb.pth", save_full_model=False):if save_full_model:torch.save(model, path)else:torch.save(model.state_dict(), path)print(f"Model saved to {path}")# Function to compute Intersection over Union
def compute_iou(boxA, boxB):xA = max(boxA[0], boxB[0])yA = max(boxA[1], boxB[1])xB = min(boxA[2], boxB[2])yB = min(boxA[3], boxB[3])interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)boxAArea = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1)boxBArea = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1)iou = interArea / float(boxAArea + boxBArea - interArea)return iou# Adjusting the DataLoader collate function to handle None values and entirely empty batches
def collate_fn(batch):batch = list(filter(lambda x: x is not None, batch))if len(batch) == 0:# Return placeholder batch if entirely emptyreturn [torch.zeros(1, 3, 224, 224)], [{}]return tuple(zip(*batch))#Training function with modifications for collecting IoU and loss
def train_model(model, train_loader, optimizer, device, num_epochs=10):model.train()model.to(device)loss_values = []iou_values = []for epoch in range(num_epochs):epoch_loss = 0.0total_ious = 0num_boxes = 0for images, targets in train_loader:# Skip batches with placeholder dataif len(targets) == 1 and not targets[0]:continue# Skip batches with empty targetsif any(len(target["boxes"]) == 0 for target in targets):continueimages = [image.to(device) for image in images]targets = [{k: v.to(device) for k, v in t.items()} for t in targets]loss_dict = model(images, targets)losses = sum(loss for loss in loss_dict.values())optimizer.zero_grad()losses.backward()optimizer.step()epoch_loss += losses.item()# Compute IoU for evaluationwith torch.no_grad():model.eval()predictions = model(images)for i, prediction in enumerate(predictions):pred_boxes = prediction["boxes"].cpu().numpy()true_boxes = targets[i]["boxes"].cpu().numpy()for pred_box in pred_boxes:for true_box in true_boxes:iou = compute_iou(pred_box, true_box)total_ious += iounum_boxes += 1model.train()avg_loss = epoch_loss / len(train_loader)avg_iou = total_ious / num_boxesloss_values.append(avg_loss)iou_values.append(avg_iou)print(f"Epoch {epoch+1}/{num_epochs} Loss: {avg_loss} Avg IoU: {avg_iou}")# Plotting loss and IoU valuesplt.figure(figsize=(12, 5))plt.subplot(1, 2, 1)plt.plot(loss_values, label="Training Loss")plt.title("Training Loss across Epochs")plt.xlabel("Epochs")plt.ylabel("Loss")plt.subplot(1, 2, 2)plt.plot(iou_values, label="IoU")plt.title("IoU across Epochs")plt.xlabel("Epochs")plt.ylabel("IoU")plt.show()# Save model after trainingsave_model(model)# Validation function
def validate_model(model, val_loader, device):model.eval()model.to(device)with torch.no_grad():for images, targets in val_loader:images = [image.to(device) for image in images]targets = [{k: v.to(device) for k, v in t.items()} for t in targets]model(images)# Paths to your data
image_dir = "tuberculosis-phonecamera"
annotation_dir = "tuberculosis-phonecamera"# Split data
train_images, val_images = split_data(image_dir)# Create datasets and dataloaders
train_dataset = TuberculosisDataset(image_dir, annotation_dir, train_images, transform=data_transform)
val_dataset = TuberculosisDataset(image_dir, annotation_dir, val_images, transform=data_transform)# Updated DataLoader with new collate function
train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True, collate_fn=collate_fn)
val_loader = DataLoader(val_dataset, batch_size=4, shuffle=False, collate_fn=collate_fn)# Model and optimizer
model = get_model(2)
optimizer = torch.optim.SGD(model.parameters(), lr=0.005, momentum=0.9, weight_decay=0.0005)# Train and validate
train_model(model, train_loader, optimizer, device="cuda", num_epochs=100)
validate_model(model, val_loader, device="cuda")#######################################Print Metrics######################################
def calculate_metrics(predictions, ground_truths, iou_threshold=0.5):TP = 0  # True PositivesFP = 0  # False PositivesFN = 0  # False Negativestotal_iou = 0  # to calculate mean IoUfor pred, gt in zip(predictions, ground_truths):pred_boxes = pred["boxes"].cpu().numpy()gt_boxes = gt["boxes"].cpu().numpy()# Match predicted boxes to ground truth boxesfor pred_box in pred_boxes:max_iou = 0matched = Falsefor gt_box in gt_boxes:iou = compute_iou(pred_box, gt_box)if iou > max_iou:max_iou = iouif iou > iou_threshold:matched = Truetotal_iou += max_iouif matched:TP += 1else:FP += 1FN += len(gt_boxes) - TPprecision = TP / (TP + FP) if (TP + FP) != 0 else 0recall = TP / (TP + FN) if (TP + FN) != 0 else 0f1_score = (2 * precision * recall) / (precision + recall) if (precision + recall) != 0 else 0mean_iou = total_iou / (TP + FP)return precision, recall, f1_score, mean_ioudef evaluate_model(model, dataloader, device):model.eval()model.to(device)all_predictions = []all_ground_truths = []with torch.no_grad():for images, targets in dataloader:images = [image.to(device) for image in images]predictions = model(images)all_predictions.extend(predictions)all_ground_truths.extend(targets)precision, recall, f1_score, mean_iou = calculate_metrics(all_predictions, all_ground_truths)return precision, recall, f1_score, mean_ioutrain_precision, train_recall, train_f1, train_iou = evaluate_model(model, train_loader, "cuda")
val_precision, val_recall, val_f1, val_iou = evaluate_model(model, val_loader, "cuda")print("Training Set Metrics:")
print(f"Precision: {train_precision:.4f}, Recall: {train_recall:.4f}, F1 Score: {train_f1:.4f}, Mean IoU: {train_iou:.4f}")print("\nValidation Set Metrics:")
print(f"Precision: {val_precision:.4f}, Recall: {val_recall:.4f}, F1 Score: {val_f1:.4f}, Mean IoU: {val_iou:.4f}")#sheet
header = "| Metric    | Training Set | Validation Set |"
divider = "+----------+--------------+----------------+"train_metrics = f"| Precision | {train_precision:.4f}      | {val_precision:.4f}          |"
recall_metrics = f"| Recall    | {train_recall:.4f}      | {val_recall:.4f}          |"
f1_metrics = f"| F1 Score  | {train_f1:.4f}      | {val_f1:.4f}          |"
iou_metrics = f"| Mean IoU  | {train_iou:.4f}      | {val_iou:.4f}          |"print(header)
print(divider)
print(train_metrics)
print(recall_metrics)
print(f1_metrics)
print(iou_metrics)
print(divider)#######################################Train Set######################################
import numpy as np
import matplotlib.pyplot as pltdef plot_predictions_on_image(model, dataset, device, title):# Select a random image from the datasetidx = np.random.randint(50, len(dataset))image, target = dataset[idx]img_tensor = image.clone().detach().to(device).unsqueeze(0)# Use the model to make predictionsmodel.eval()with torch.no_grad():prediction = model(img_tensor)# Inverse normalization for visualizationinv_normalize = transforms.Normalize(mean=[-0.485/0.229, -0.456/0.224, -0.406/0.225],std=[1/0.229, 1/0.224, 1/0.225])image = inv_normalize(image)image = torch.clamp(image, 0, 1)image = F.to_pil_image(image)# Plot the image with ground truth boxesplt.figure(figsize=(10, 6))plt.title(title + " with Ground Truth Boxes")plt.imshow(image)ax = plt.gca()# Draw the ground truth boxes in bluefor box in target["boxes"]:rect = plt.Rectangle((box[0], box[1]), box[2]-box[0], box[3]-box[1],fill=False, color='blue', linewidth=2)ax.add_patch(rect)plt.show()# Plot the image with predicted boxesplt.figure(figsize=(10, 6))plt.title(title + " with Predicted Boxes")plt.imshow(image)ax = plt.gca()# Draw the predicted boxes in redfor box in prediction[0]["boxes"].cpu():rect = plt.Rectangle((box[0], box[1]), box[2]-box[0], box[3]-box[1],fill=False, color='red', linewidth=2)ax.add_patch(rect)plt.show()# Call the function for a random image from the train dataset
plot_predictions_on_image(model, train_dataset, "cuda", "Selected from Training Set")#######################################Val Set####################################### Call the function for a random image from the validation dataset
plot_predictions_on_image(model, val_dataset, "cuda", "Selected from Validation Set")

不解讀了,給出GPT的咒語參考:

咒語:我有一批數據,存在“tuberculosis-phonecamera”文件夾中,包括兩部分:

一部分是MTB的痰涂片抗酸染色圖片,為jpg格式,命名為“tuberculosis-phone-0001.jpg”、“tuberculosis-phone-0002.jpg”等;

一部分是MTB的痰涂片抗酸染色圖片對應的注釋文件,主要內容是標注MTB的痰涂片抗酸染色圖片中MTB的具體位置,是若干個紅色框,為XML格式,命名為“tuberculosis-phone-0001.xml”、“tuberculosis-phone-0002.xml”等,我上傳一個xml文件給你做例子;

我需要基于上面的數據,使用pytorch建立一個Mask R-CNN目標識別模型,去識別MTB的痰涂片抗酸染色圖片中的MTB,并使用紅色框標注出來。數據需要隨機分為訓練集(80%)和驗證集(20%)。

看看結果:

(1)loss曲線圖:

(2)性能指標:

(3)訓練的圖片測試結果:

(4)驗證集的圖片測試結果:

五、寫在后面

直接使用預訓練模型,而且模型并沒有調參。但是訓練集的準確率還是挺高的,驗證集就差點意思了。需要更高的性能,還得認真研究如何調參。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/162229.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/162229.shtml
英文地址,請注明出處:http://en.pswp.cn/news/162229.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Docker Swarm總結(1/3)

目錄 1、swarm 理論基礎 1.1 簡介 1.2 節點架構 1.3 服務架構 1.4 服務部署模式 2、swarm 集群搭建 2.1 需求 ?2.2 克隆主機 2.3 啟動5個docker宿主機 2.4 查看 swarm 激活狀態 2.5 關閉防火墻 2.6 swarm 初始化 2.7 添加 worker 節點 2.8 添加 manager 節點 3、…

Mybatis-Plus3.0默認主鍵策略導致自動生成19位長度主鍵id的坑

碼字不易&#xff0c;如果對您有用&#xff0c;求各位看官點贊關注~ 原創/朱季謙 目前的Mybatis-Plus版本是3.0&#xff0c;至于最新版本是否已經沒有這個問題&#xff0c;后續再考慮研究。 某天檢查一位離職同事寫的代碼&#xff0c;發現其對應表雖然設置了AUTO_INCREMENT自…

7.1 Windows驅動開發:內核監控進程與線程回調

在前面的文章中LyShark一直在重復的實現對系統底層模塊的枚舉&#xff0c;今天我們將展開一個新的話題&#xff0c;內核監控&#xff0c;我們以監控進程線程創建為例&#xff0c;在Win10系統中監控進程與線程可以使用微軟提供給我們的兩個新函數來實現&#xff0c;此類函數的原…

H3C路由器基本配置命令

1、system-view 進入系統視圖 2、sysname R1 配置路由器名字為R1 3、display clock 查看當前系統時間 4、clock datetime 00:00:00 2/26/2023 用戶模式下修改系統時間 配置控制臺密碼 Console&#xff1a; 1、user-interface aux0 在系統模式下進入圖接口 2、authentication-mo…

2023亞太賽c題完整思路數據 數學建模亞太

Question 1: Analyze the main factors that affect the development of new energy electric vehicles in China, establish a mathematical model, and describe the impact of these factors on the development of new energy electric vehicles in China. 問題1:分析影響…

office 365企業版安裝教程

1.下載所需工具&#xff08;防火墻和防毒軟件記得關閉&#xff09; 下載鏈接&#xff1a;所需文件 2.安裝激活office 1.安裝 office tool plus 2.已安裝過office 先進行office的移除&#xff0c;再進行未安裝office的步驟進行 3.未安裝過office 1.設置部署 按照以下來進行安…

Linux命令(130)之hwclock

linux命令之hwclock 1.hwclock介紹 linux命令hwclock是用來顯示硬件時鐘 2.hwclock用法 hwclock [參數] hwclock參數 參數說明-s讓系統時間同步硬件時間-w讓硬件時間同步系統時間 3.實例 3.1.同步服務器時鐘時間 命令&#xff1a; ntpdate pool.ntp.org [rootrhel77 ~…

【vin 國標正則校驗】

規則一 var checkVINfunction(VIN){if(typeof(VIN)!string) return false;if(VIN.length!17) return false;VINVIN.toUpperCase();RE/^[A-HJ-NPR-Z\d]{8}[X\d][A-HJ-NPR-Z\d]{3}\d{5}$/if(!RE.test(VIN)) return false;let cOT{0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:1,B…

360:流氓or保家衛國的勇士?

你曾用過360嗎&#xff0c;這個在國內名聲不好的殺毒軟件&#xff0c;卻是令國外黑客聞風喪膽的存在。 首先&#xff0c;在電腦病毒剛興起的年代&#xff0c;殺毒軟件是要收費的&#xff0c;當時盛行的瑞星和金山就是采用的付費模式&#xff0c;而就在2006年&#xff0c;奇虎…

C/C++通過位操作實現2個uint32_t合并為uint64_t

#include <iostream> using namespace std;int main() {uint32_t a 10;uint32_t b 600;//先將uint32_t的a轉為uint64_t&#xff0c;此時a前面32位都是0&#xff0c;然后左移32位&#xff0c;此時右32位為0&#xff0c;最后加上uint32_t類型的b&#xff0c;填充右32位的…

解決Activiti5.22流程圖部署在Windows上正常,但在linux上部署后出現中文變方塊的問題

總結/朱季謙 樓主最近在做公司的工作流平臺&#xff0c;發現一個很無語的事情&#xff0c;Activiti5.22的流程圖在Windows環境上部署&#xff0c;是可以正常查看的&#xff0c;但發布到公司的Linux服務器上后&#xff0c;在上面進行流程圖在線部署時&#xff0c;發現中文都變成…

2023亞太杯數學建模C題思路代碼 - 我國新能源電動汽車的發展趨勢

1 賽題 問題C 我國新能源電動汽車的發展趨勢 新能源汽車是指以先進技術原理、新技術、新結構的非常規汽車燃料為動力來源( 非常規汽車燃料指汽油、柴油以外的燃料&#xff09;&#xff0c;將先進技術進行汽車動力控制和驅動相結 合的汽車。新能源汽車主要包括四種類型&#x…

一套開源、強大且美觀的WPF UI控件庫 - HandyControl

前言 今天給大家推薦一套開源、強大且美觀的WPF UI控件庫&#xff1a;HandyControl。 WPF介紹 WPF 是一個強大的桌面應用程序框架&#xff0c;用于構建具有豐富用戶界面的 Windows 應用。它提供了靈活的布局、數據綁定、樣式和模板、動畫效果等功能&#xff0c;讓開發者可以創…

關于Redis底層的兩個問題

1. 為什么Redis不共享包含字符串的對象&#xff1f; 當服務器考慮將一個共享對象設置為鍵的值對象時&#xff0c;程序首先需要檢查給定的共享對象和鍵想要創建的目標對象是否完全相同&#xff0c;只有在共享對象和目標對象完全相同的情況下&#xff0c;程序才會將共享對象用作…

SOEM主站開發篇(3):為APP程序添加命令

0 工具準備 1.SOEM-1.4.0源碼(官網:http://openethercatsociety.github.io/) 2.Linux開發板(本文為正點原子I.MX6U ALPHA開發板) 3.交叉編譯工具(arm-linux-gnueabihf-gcc) 4.cmake(版本不得低于3.9,本文為3.9.2) 5.Ubuntu 16.04(用于編譯生成Linux開發板的可執行文…

【追求卓越06】算法--遞歸

引導 遞歸算法算是我們比較常用的一種算法。但是想用好并不簡單。本章我不再介紹簡單的概念&#xff0c;主要講解遞歸算法的優缺點和如何用遞歸寫代碼。 個人愛好 其實相對于使用while循環&#xff0c;我更喜歡使用遞歸算法。為什么呢&#xff1f; 使用遞歸算法代碼往往會變…

Java語言中的控制流程

控制流程是編程中的重要概念之一&#xff0c;它允許程序根據條件執行不同的代碼塊或重復執行特定的代碼塊。在Java中&#xff0c;控制流程由條件語句和循環語句組成。本文將詳細介紹Java中的條件語句&#xff08;if語句和switch語句&#xff09;和循環語句&#xff08;for循環、…

MySQL用戶與權限管理

快捷查看指令 ctrlf 進行搜索會直接定位到需要的知識點和命令講解&#xff08;如有不正確的地方歡迎各位小伙伴在評論區提意見&#xff0c;博主會及時修改&#xff09; MySQL用戶與權限管理 登錄 #本地登錄 mysql -uroot -p123456#遠程登錄 #客戶端語法&#xff1a;mysql -…

聚觀早報 |快手Q3營收;拼多多殺入大模型;Redmi K70E開啟預約

【聚觀365】11月23日消息 快手Q3營收 拼多多殺入大模型 Redmi K70E開啟預約 華為nova 12系列或下周發布 亞馬遜啟動“AI就緒”新計劃 快手Q3營收 財報顯示&#xff0c;快手第三季度營收279億元&#xff0c;同比增長20.8%&#xff1b;期內盈利21.8億元&#xff0c;去年同期…

貓罐頭多久喂一次?好用的貓罐頭牌子推薦

貓愛吃貓罐頭&#xff0c;包含各種美味&#xff0c;提供營養和口感。但喂貓吃罐頭需技巧和耐心&#xff0c;以確保貓健康快樂成長。 作為一個從業寵物營養師7年的人&#xff0c;可以說對于貓咪的食物很有研究和貓罐頭品牌選購上&#xff0c;我有自己的見解。 一、貓罐頭多久喂…