用分割點座標將影象二值化
阿新 • • 發佈:2019-01-22
最近在做影象分割,找了一些醫學影象資料集,但GroundTruth不是二值圖,而是由座標表示。
如圖:
圖1 座標:以(X, Y)成對存放於txt檔案中
圖2 原始圖
圖3 將座標標註在圖上
由於訓練過程需要將影象分為二值圖,也就是說要將左心室和非左心室分割開來。
opencv有個很好用的函式,可以直接將影象用輪廓座標分割成二值圖。那就是cv2.fillPoly
首先是得到一個掩模(mask),毫無疑問這個mask需要跟原圖一樣的大小。
import numpy as np
import pydicom
import cv2
import matplotlib.pyplot as plt
from PIL import Image
raw_dicom = pydicom.dcmread(dicom_dir) #影象為dicom格式,所以用pydicom讀取
dicom_picture = raw_dicom.pixel_array.astype(int) #用pixel_array提取影象資訊。相當於一個畫素值組成的陣列
mask = np.zeros_like(dicom_picture) #將mask定義為一個跟影象一樣大小的零矩陣
coords = np.loadtxt(counter_dir, delimiter=' ').astype('int' ) #將座標以list的形式提取出來
cv2.fillPoly(mask, [coords], 255) #關鍵的一步,用這個函式就可以將輪廓內的部分標記出來。
結果:
圖4 原圖
圖5 二值圖
還有一個坑的地方,為什麼用255而不是1,我看很多人都用的1,這是方便後續的儲存。解釋一下:
如果用1填充,那麼用plt.imshow(mask, cmap =’gray’)可以將影象顯示出來,但是儲存的時候就是全黑的。我猜測是因為儲存畫素範圍預設為0-255,所以0和1就沒有太大的差別。所以我選用了255來填充。
這樣就可以得到圖中的效果了,但是為了得到二值圖,還需要再轉換一下。我用了PIL中的Image
mask = Image.fromarray(mask) #mask是一個數組,所以先轉為影象
mask = mask.convert("1") #convert("1")表示轉為2值圖
scipy.misc.imsave("counter.png", mask) #最後就是儲存了