使用簡單方法在圖像中檢測血細胞
對象檢測問題的基礎是數(shù)據(jù)的外觀,F(xiàn)在,本文將介紹可用于解決對象檢測問題的不同深度學習架構。讓我們首先討論我們將要處理的問題陳述。
目錄
1. 了解問題陳述:血細胞檢測
2. 數(shù)據(jù)集鏈接
3. 解決對象檢測問題的簡單方法
4. 實施簡單方法的步驟
· 加載數(shù)據(jù)集
· 數(shù)據(jù)探索
· 為簡單方法準備數(shù)據(jù)集
· 創(chuàng)建訓練和驗證集
· 定義分類模型架構
· 訓練模型
· 作出預測
5. 結(jié)論
了解問題陳述血細胞檢測
問題陳述
對于一組給定的血細胞圖像,我們必須檢測圖像中的白細胞。現(xiàn)在,這是來自數(shù)據(jù)集的示例圖像。如你所見,你可以看到有一些紅色陰影區(qū)域和藍色或紫色區(qū)域。
在上圖中,紅色陰影區(qū)域是紅細胞(RBC),紫色陰影區(qū)域是白細胞(WBC),還有一些小的黑色突出部分是血小板。
正如你在此圖像中看到的那樣,我們有多個對象和多個類。
為簡單起見,我們將其轉(zhuǎn)換為單類單對象問題。這意味著我們將只考慮白細胞。
因此,只有一個類,即白細胞,而忽略其余的類。此外,我們將只保留具有單個白細胞的圖像。
因此,具有多個白細胞的圖像將從該數(shù)據(jù)集中刪除。
以下是我們將從該數(shù)據(jù)集中選擇圖像的方法。
因此,我們刪除了圖像 2 和圖像 5,因為圖像 5 沒有白細胞,而圖像 2 有 2 個白細胞,其他圖像保留在數(shù)據(jù)集中。同樣,測試集也將只有一個白細胞。
現(xiàn)在,對于每個圖像,我們在白細胞周圍都有一個邊界框。正如你在這張圖片中看到的,我們的文件名為 1.jpg,這些是白細胞周圍邊界框的邊界框坐標。
在下一節(jié)中,我們將介紹解決此對象檢測問題的簡單方法。
解決對象檢測問題的簡單方法
在本節(jié)中,我們將討論一種解決對象檢測問題的簡單方法。所以讓我們首先了解任務,我們必須在血細胞圖像中檢測白細胞,可以看到下圖。
現(xiàn)在,最簡單的方法是將圖像劃分為多個塊,因此對于此圖像,將圖像劃分為四個塊。
我們對這些塊中的每一個進行分類,因此第一個塊沒有白細胞,第二個塊有一個白細胞,同樣第三個和第四個沒有任何白細胞。
我們已經(jīng)熟悉分類過程以及如何構建分類算法。因此,我們可以輕松地將這些單獨的塊中的每一個分類為 yes 和 no,以表示白細胞。
現(xiàn)在,在下圖中,具有白細胞的塊(綠色框)可以表示為邊界框,因此在這種情況下,我們將取這個塊的坐標值,并將其返回為白細胞的邊界框。
現(xiàn)在為了實施這種方法,我們首先需要準備我們的訓練數(shù)據(jù)。
現(xiàn)在可能有一個問題,為什么我們需要準備訓練數(shù)據(jù)?我們已經(jīng)有了這些圖像和邊界框。
我們的訓練數(shù)據(jù)采用以下格式,其中我們有白細胞邊界框和邊界框坐標。
現(xiàn)在,請注意我們有完整圖像的這些邊界框坐標,但我們將把這個圖像分成四個塊。我們需要所有這四個塊的邊界框坐標。下一個問題是我們?nèi)绾巫龅竭@一點?
我們必須定義一個新的訓練數(shù)據(jù),我們有文件名,如下圖所示。
我們有不同的塊,對于每個塊,我們有 Xmin、Xmax、Ymin 和 Ymax 值,它們表示這些塊的坐標,最后,我們的目標變量是白細胞。圖像中是否存在白細胞?
現(xiàn)在在這種情況下,它將成為一個簡單的分類問題。因此,對于每個圖像,我們將其劃分為四個不同的塊,并為每個塊創(chuàng)建邊界框坐標。
現(xiàn)在下一個問題是我們?nèi)绾蝿?chuàng)建這些邊界框坐標?這真的很簡單。
考慮到我們有一個大小為 (640*480) 的圖像。所以原點是(0,0)。上圖有 x 軸和 y 軸,這里我們的坐標值為 (640, 480)。
現(xiàn)在,我們找出中點,它是 (320,240)。一旦我們有了這些值,我們就可以很容易地找出每個塊的坐標。所以對于第一個塊,我們的 Xmin 和 Ymin 將是 (0,0) ,而 Xmax, Ymax 將是 (320,240)。
同樣,我們可以在第二個、第三個和第四個塊中找到它。一旦我們有了這些塊中的每一個的坐標值或邊界框值。下一個任務是確定此塊中是否存在白細胞。
在這里我們可以清楚地看到塊 2 有白細胞,而其他塊沒有,但是我們不能在數(shù)據(jù)集中的每個塊上對每個圖像都手動標注白細胞。
現(xiàn)在在下一節(jié)中,我們將實現(xiàn)簡單的方法。
實施簡單方法的步驟
在上一節(jié)中,我們討論了用于對象檢測的簡單方法,F(xiàn)在讓我們定義在血細胞檢測問題上實施這種方法的步驟。
這些是將要遵循的步驟:
1. 加載數(shù)據(jù)集
2. 數(shù)據(jù)探索
3. 為簡單方法準備數(shù)據(jù)集
4. 創(chuàng)建訓練和驗證集
5. 定義分類模型架構
6. 訓練模型
7. 作出預測
讓我們進入下一節(jié),實現(xiàn)上述步驟。
1.加載所需的庫和數(shù)據(jù)集
因此,讓我們首先從加載所需的庫開始。numpy和pandas,matplotlib用來可視化數(shù)據(jù),我們已經(jīng)加載了一些庫來處理圖像并調(diào)整圖像大小,最后是torch庫。
# Importing Required Libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import os
from PIL import Image
from skimage.transform import resize
import torch
from torch import nn
現(xiàn)在我們將修復一個隨機種子值。
# Fixing a random seed values to stop potential randomness
seed = 42
rng = np.random.RandomState(seed)
在這里,我們將安裝驅(qū)動器,因為數(shù)據(jù)集存儲在驅(qū)動器上。
# mount the drive
from google.colab import drive
drive.mount('/content/drive')
現(xiàn)在因為驅(qū)動器上的數(shù)據(jù)以 zip 格式提供。我們必須解壓縮這些數(shù)據(jù),在這里我們將解壓縮數(shù)據(jù)。
所以我們可以看到所有的圖像都被加載并存儲在一個名為 images 的文件夾中。在這個文件夾的末尾,我們有一個 CSV 文件,它是trained.csv。
# unzip the dataset from drive
!unzip /content/drive/My Drive/train_zedkk38.zip
2.數(shù)據(jù)探索
閱讀 CSV 文件并找出存儲在這個“train.csv”文件中的信息是什么。
## Reading target file
data = pd.read_csv('train.csv')
data.shape
打印 CSV 文件的前幾行,我們可以看到該文件具有 image_names 以及 cell_type,它將表示紅細胞或白細胞等等。最后是此特定圖像中此特定對象的邊界框坐標。data.head()
因此,如果我們檢查紅細胞、白細胞和血小板的計數(shù)值。我們將看到紅細胞具有最大計數(shù)值,其次是白細胞和血小板。
data.cell_type.value_counts()
現(xiàn)在為簡單起見,我們將只考慮白細胞。因此,我們選擇了只有白細胞的數(shù)據(jù)。
現(xiàn)在我們針對這些圖像有 image_names和 cell_type WBC。還有邊界框坐標。
(data.loc[data['cell_type'] =='WBC']).head()
讓我們看看原始數(shù)據(jù)集中的幾張圖像以及這些圖像的形狀。
我們可以看到這些圖像的形狀是(480,640,3)。這是一個具有三個通道的 RGB 圖像,這是數(shù)據(jù)集中的第一張圖像。
image = plt.imread('images/' + '1.jpg')
print(image.shape)
plt.imshow(image)
下一步是用這個圖像創(chuàng)建塊。我們要學習如何把這張圖片分成四個塊,F(xiàn)在我們知道圖像的形狀是 (640, 480)。因此這張圖片的中間點是 (320,240),中心是 (0, 0)。
因此,我們有圖像中所有這些塊的坐標,在這里我們將利用這些坐標并創(chuàng)建塊。
這些坐標的格式將是 Ymin、Ymax、Xmin 和 Xmax。這里我們的 (Ymin, Ymax) 是 (0, 240) 并且 (Xmin, Xmax) 是 (0,320)。這基本上表示第一個塊。
同樣,對于隨后的第二個第三個和第四個塊,我們有 image_2、image_3、image_4。這是一個我們可以從圖像創(chuàng)建塊的過程。
# creating 4 patches from the image
# format ymin, ymax, xmin, xmax
image_1 = image[0:240, 0:320, :]
image_2 = image[0:240, 320:640, :]
image_3 = image[240:480, 0:320, :]
image_4 = image[240:480, 320:640, :]
現(xiàn)在我們需要為這些塊分配一個目標值。為了做到這一點,我們計算并集的交集,我們必須找出交集區(qū)域和并集區(qū)域。
所以交集區(qū)域就是這個特定的矩形,要找出面積,我們需要找出這個矩形的 Xmin、Xmax 和 Ymin、Ymax 坐標。
def iou(box1, box2):
Irect_xmin, Irect_ymin = max(box1[0],box2[0]), max(box1[2],box2[2])
Irect_xmax, Irect_ymax = min(box1[1],box2[1]), min(box1[3],box2[3])
if Irect_xmax < Irect_xmin or Irect_ymax < Irect_ymin:
target = inter_area = 0
else:
inter_area = np.a(chǎn)bs((Irect_xmax - Irect_xmin) * (Irect_ymax - Irect_ymin))
box1_area = (box1[1]-box1[0])*(box1[3]-box1[2])
box2_area = (box2[1]-box2[0])*(box2[3]-box2[2])
union_area = box1_area+box2_area-inter_area
iou = inter_area/union_area
target = int(iou > 0.1)
return target
我們有來自訓練 CSV 文件的原始邊界框坐標。當我將這兩個值用作我們定義的“ iou”函數(shù)的輸入時,目標為 1。
你也可以嘗試使用不同的塊,也可以基于你將得到的目標值。
box1= [320, 640, 0, 240]
box2= [93, 296, 1, 173]
iou(box1, box2)
輸出為 0,F(xiàn)在下一步是準備數(shù)據(jù)集。
3.為簡單方法準備數(shù)據(jù)集
我們只考慮并探索了數(shù)據(jù)集中的單個圖像。因此,讓我們對數(shù)據(jù)集中的所有圖像執(zhí)行這些步驟。這里是我們擁有的完整數(shù)據(jù)。
data.head()
現(xiàn)在,我們正在轉(zhuǎn)換這些細胞類型,紅細胞為0,白細胞為 1,血小板為 2。
data['cell_type'] = data['cell_type'].replace({'RBC': 0, 'WBC': 1, 'Platelets': 2})
現(xiàn)在我們必須選擇只有一個白細胞的圖像。
因此,首先我們創(chuàng)建數(shù)據(jù)集的副本,然后僅保留白細胞并刪除任何具有多個白細胞的圖像。
## keep only Single WBCs
data_wbc = data.loc[data.cell_type == 1].copy()
data_wbc = data_wbc.drop_duplicates(subset=['image_names', 'cell_type'], keep=False)
現(xiàn)在我們已經(jīng)選擇了圖像。我們將根據(jù)輸入圖像大小設置塊坐標。
我們正在逐一讀取圖像并存儲該特定圖像的白細胞邊界框坐標,使用我們在此處定義的塊坐標從該圖像中提取塊。
然后我們使用自定義的 IoU 函數(shù)找出每個塊的目標值。最后,在這里我們將塊大小調(diào)整為標準大小 (224, 224, 3)。在這里,我們正在為每個塊創(chuàng)建最終輸入數(shù)據(jù)和目標數(shù)據(jù)。
# create empty lists
X = []
Y = []
# set patch co-ordinates
patch_1_coordinates = [0, 320, 0, 240]
patch_2_coordinates = [320, 640, 0, 240]
patch_3_coordinates = [0, 320, 240, 480]
patch_4_coordinates = [320, 640, 240, 480]
for idx, row in data_wbc.iterrows():
# read image
image = plt.imread('images/' + row.image_names)
bb_coordinates = [row.xmin, row.xmax, row.ymin, row.ymax]
# extract patches
patch_1 = image[patch_1_coordinates[2]:patch_1_coordinates[3],
patch_1_coordinates[0]:patch_1_coordinates[1], :]
patch_2 = image[patch_2_coordinates[2]:patch_2_coordinates[3],
patch_2_coordinates[0]:patch_2_coordinates[1], :]
patch_3 = image[patch_3_coordinates[2]:patch_3_coordinates[3],
patch_3_coordinates[0]:patch_3_coordinates[1], :]
patch_4 = image[patch_4_coordinates[2]:patch_4_coordinates[3],
patch_4_coordinates[0]:patch_4_coordinates[1], :]
# set default values
target_1 = target_2 = target_3 = target_4 = inter_area = 0
# figure out if the patch contains the object
## for patch_1
target_1 = iou(patch_1_coordinates, bb_coordinates )
## for patch_2
target_2 = iou(patch_2_coordinates, bb_coordinates)
## for patch_3
target_3 = iou(patch_3_coordinates, bb_coordinates)
## for patch_4
target_4 = iou(patch_4_coordinates, bb_coordinates)
# resize the patches
patch_1 = resize(patch_1, (224, 224, 3), preserve_range=True)
patch_2 = resize(patch_2, (224, 224, 3), preserve_range=True)
patch_3 = resize(patch_3, (224, 224, 3), preserve_range=True)
patch_4 = resize(patch_4, (224, 224, 3), preserve_range=True)
# create final input data
X.extend([patch_1, patch_2, patch_3, patch_4])
# create target data
Y.extend([target_1, target_2, target_3, target_4])
# convert these lists to single numpy array
X = np.a(chǎn)rray(X)
Y = np.a(chǎn)rray(Y)
現(xiàn)在,讓我們打印原始數(shù)據(jù)和剛剛創(chuàng)建的新數(shù)據(jù)的形狀。我們可以看到我們最初有 240 張圖像。
現(xiàn)在我們將這些圖像分成四部分, 即(960,224,224,3)。這是圖像的形狀。
# 4 patches for every image
data_wbc.shape, X.shape, Y.shape
讓我們快速看一下我們剛剛創(chuàng)建的這些圖像之一。這是我們的原始圖像,這是原始圖像的最后一個塊或第四個塊。我們可以看到分配的目標是1。
image = plt.imread('images/' + '1.jpg')
】
plt.imshow(image)
如果我們檢查任何其他塊,假設我要檢查此圖像的第一個塊,這里會將目標設為0。你將獲得第一個塊。
同樣,你可以確保將所有圖像轉(zhuǎn)換為塊并相應地分配目標。
plt.imshow(X[0].a(chǎn)stype('uint8')), Y[0]
4.準備訓練和驗證集
現(xiàn)在我們有了數(shù)據(jù)集。我們將準備我們的訓練和驗證集。現(xiàn)在請注意,這里我們的圖像形狀為 (224,224,3)。
# 4 patches for every image
data_wbc.shape, X.shape, Y.shape
輸出是:
((240, 6), (960, 224, 224, 3), (960,))
在 PyTorch 中,我們首先需要擁有通道。因此,我們將移動具有形狀 (3,224,224) 的軸。
X = np.moveaxis(X, -1, 1)
X.shape
輸出是:
(960, 3, 224, 224)
現(xiàn)在,我們對圖像像素值進行歸一化。
X = X / X.max()
使用訓練測試拆分功能,我們將創(chuàng)建一個訓練集和驗證集。
from sklearn.model_selection import train_test_split
X_train, X_valid, Y_train, Y_valid=train_test_split(X, Y, test_size=0.1,
random_state=seed)
X_train.shape, X_valid.shape, Y_train.shape, Y_valid.shape
上述代碼的輸出是:
((864, 3, 224, 224), (96, 3, 224, 224), (864,), (96,))
現(xiàn)在,我們要將訓練集和驗證集都轉(zhuǎn)換為張量,因為它們是“ numpy”數(shù)組。
X_train = torch.FloatTensor(X_train)
Y_train = torch.FloatTensor(Y_train)
X_valid = torch.FloatTensor(X_valid)
Y_valid = torch.FloatTensor(Y_valid)
5.模型構建
現(xiàn)在,我們要構建我們的模型,在這里我們安裝了一個庫,它是 PyTorch 模型摘要。
!pip install pytorch-model-summary
這僅用于在 PyTorch 中打印模型摘要。現(xiàn)在我們從這里導入?yún)R總函數(shù)。
from pytorch_model_summary import summary
這是我們?yōu)榉椒ǘx的架構。
我們定義了一個順序模型,其中有Conv2d 層,輸入通道數(shù)為 3,過濾器數(shù)量為 64,過濾器的大小為 5,步幅設置為 2。對于這個 Conv2d 層有 ReLU 激活函數(shù)。一個池化層,窗口大小為 4,步幅為 2,然后是卷積層。
現(xiàn)在展平 Conv2d 層的輸出,最后是全連接層和 sigmoid 激活函數(shù)。
## model architecture
model = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=64, kernel_size=5, stride=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=4,stride=2),
nn.Conv2d(in_channels=64, out_channels=64, kernel_size=5, stride=2),
nn.Flatten(),
nn.Linear(40000, 1),
nn.Sigmoid()
)
在這里打印模型,將是我們定義的模型架構。
print(model)
使用summary函數(shù),我們可以查看模型摘要。因此,這將為我們返回每個層的輸出形狀,每個層的可訓練參數(shù)的數(shù)量,F(xiàn)在我們的模型已經(jīng)準備好了。
print(summary(model, X_train[:1]))
現(xiàn)在模型已經(jīng)準備好訓練了。
6.訓練模型
讓我們訓練這個模型。所以我們要定義我們的損失函數(shù)和優(yōu)化函數(shù)。我們將二元交叉熵定義為損失和Adam優(yōu)化器。然后我們將模型傳輸?shù)?GPU。
在這里,我們從輸入圖像中提取批次來訓練這個模型。
## loss and optimizer
criterion = torch.nn.BCELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
## GPU device
if torch.cuda.is_available():
model = model.cuda()
criterion = criterion.cuda()
因此,我們從 x_train 中提取了批次并使用了這些批次。我們將對該模型進行總共 15 個 epoch 的訓練。我們還設置了一個 optimizer.Zero_grad() 并將輸出存儲在這里。
現(xiàn)在我們正在計算損失并存儲所有損失并執(zhí)行反向傳播和更新參數(shù)。此外,我們在每個 epoch 之后打印損失。
在輸出中,我們可以看到每個時期的損失都在減少。所以這個模型的訓練就完成了。
# batch size of the model
batch_size = 32
# defining the training phase
model.train()
for epoch in range(15):
# setting initial loss as 0
train_loss = 0.0
# to randomly pick the images without replacement in batches
permutation = torch.randperm(X_train.size()[0])
# to keep track of training loss
training_loss = []
# for loop for training on batches
for i in range(0,X_train.size()[0], batch_size):
# taking the indices from randomly generated values
indices = permutation[i:i+batch_size]
# getting the images and labels for a batch
batch_x, batch_y = X_train[indices], Y_train[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda().float(), batch_y.cuda().float()
# clearing all the accumulated gradients
optimizer.zero_grad()
# mini batch computation
outputs = model(batch_x)
# calculating the loss for a mini batch
loss = criterion(outputs.squeeze(),batch_y)
# storing the loss for every mini batch
training_loss.a(chǎn)ppend(loss.item())
# calculating the gradients
loss.backward()
# updating the parameters
optimizer.step()
training_loss = np.a(chǎn)verage(training_loss)
print('epoch: t', epoch, 't training loss: t', training_loss)
7.做出預測
現(xiàn)在讓我們使用這個模型來進行預測。所以在這里我只從驗證集中獲取前五個輸入并將它們傳輸?shù)?Cuda。
output = model(X_valid[:5].to('cuda')).cpu().detach().numpy()
這是我們拍攝的前五張圖像的輸出,F(xiàn)在我們可以看到前兩個的輸出是沒有白細胞或有白細胞。
output
這是輸出:
array([[0.00641595],
[0.01172841],
[0.99919134],
[0.01065345],
[0.00520921]], dtype=float32)
繪制圖像。我們可以看到這是第三張圖片,這里的模型說有一個白細胞,我們可以看到這張圖片中有一個白細胞。
plt.imshow(np.transpose(X_valid[2]))
同樣,我們可以檢查另一張圖像,因此將獲取第一張圖像。
你可以看到輸出圖像,這個圖像是我們的輸入塊,這個塊中沒有白細胞。
plt.imshow(np.transpose(X_valid[1]))
這是一種非常簡單的方法,可以進行預測或識別具有白細胞的圖像的塊或部分。
結(jié)論
使用簡單方法了解使用圖像數(shù)據(jù)集進行血細胞檢測的實際實現(xiàn)。這是解決業(yè)務問題和開發(fā)模型的真正挑戰(zhàn)。
在處理圖像數(shù)據(jù)時,你必須分析一些任務,例如邊界框、計算 IoU 值、評估指標。本文的下一個級別(未來任務)是一個圖像可以有多個對象。任務是檢測每個圖像中的對象。希望這些文章能幫助你了解如何使用圖像數(shù)據(jù)檢測血細胞,如何建立檢測模型,我們將使用這種技術,并將其應用于醫(yī)學分析領域。
原文標題 : 使用簡單方法在圖像中檢測血細胞
請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
-
即日-11.13立即報名>>> 【在線會議】多物理場仿真助跑新能源汽車
-
11月28日立即報名>>> 2024工程師系列—工業(yè)電子技術在線會議
-
12月19日立即報名>> 【線下會議】OFweek 2024(第九屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會
-
即日-12.26火熱報名中>> OFweek2024中國智造CIO在線峰會
-
即日-2025.8.1立即下載>> 《2024智能制造產(chǎn)業(yè)高端化、智能化、綠色化發(fā)展藍皮書》
-
精彩回顧立即查看>> 【限時免費下載】TE暖通空調(diào)系統(tǒng)高效可靠的組件解決方案
推薦專題
-
5 夾縫中的文遠知行
- 高級軟件工程師 廣東省/深圳市
- 自動化高級工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級銷售經(jīng)理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術專家 廣東省/江門市
- 封裝工程師 北京市/海淀區(qū)
- 結(jié)構工程師 廣東省/深圳市