機器學習之基於水色圖像的水質評價
一、案例背景
- 水質等級最高爲10分,請爲以下水質打分:
- 水產養殖
水產養殖的關鍵因素之一是水質
養殖水體生態系統的平衡狀況可通過水質顏色體現
傳統水質監控的關鍵:行家
- 依賴人(專家)的侷限性
對個人經驗要求高
存在主觀性引起的觀察性偏差
觀察結果的可比性、可重複性不高,不易推廣應用
- 在線水質監測
1.計算機視覺
2.數字圖像處理技術
3.專家經驗(專家數據)
4.機器學習算法
- 原始數據
- 水質分類標準
二、挖掘目標
請根據水質圖片,利用圖像處理技術和相應模型,實現水質的自動評價。
三、分析方法與過程
- 採集水樣圖像
- 特徵提取
- 圖像特徵主要包括:顏色特徵、紋理特徵、形狀特徵、空間關係特徵等。
- 與幾何特徵相比,顏色特徵更爲穩健,對於物體的大小和方向均不敏感,表現出較強的魯棒性。
- 本案例中由於水色圖像是均勻的,故主要關注顏色特徵。
四、數據預處理
- 數據轉化(Python)
圖片轉像素值矩陣:PIL Image.open()
r,g,b = im.split() #分成3個顏色通道
r_d = np.asarray® #取出各通道像素值 - 圖像切割
- 顏色特徵
顏色直方圖:反映的是圖像中顏色的組成分佈,即出現了哪些顏色以及各種顏色出現的概率。其優點在於它能簡單描述一幅圖像中顏色的全局分佈,即不同色彩在整幅圖像中所佔的比例,特別適用於描述那些難以自動分割的圖像和不需要考慮物體空間位置的圖像。其缺點在於它無法描述圖像中顏色的局部分佈及每種色彩所處的空間位置,即無法描述圖像中的某一具體的對象或物體。
顏色矩:圖像中任何的顏色分佈均可以用它的矩來表示。根據概率論,隨機變量的概率分佈可以由其各階矩唯一的表示和描述。一副圖像的色彩分佈也可認爲是一種概率分佈,那麼圖像可以由其各階矩來描述。顏色矩包含各個顏色通道的一階距、二階矩和三階矩,對於一幅RGB顏色空間的圖像,具有R、G和B三個顏色通道,則有9個分量。
顏色直方圖產生特徵維數一般大於顏色矩的特徵維數,爲了避免過
多變量影響後續的分類效果,在本案例採用顏色矩來提取水樣圖像的特徵。
- 特徵提取:各階顏色矩
一階顏色矩:採用一階原點矩,反映了圖像的整體明暗程度。
二階顏色矩:採用二階中心矩的平方根,反映了圖像顏色的分佈範圍。
三階顏色矩:採用三階中心矩的立方根,反映了圖像顏色分佈的對稱性。
- 顏色矩特徵提取後的數據集
五、模型構建與評價 - 抽取80%作爲訓練樣本,剩下的20%作爲測試樣本。
- 用訓練集樣本對模型進行訓練。
- 用測試集樣本對模型性能進行評價。
相關代碼如下:(其中可以點擊此處獲取原始數據的照片樣本即water-images)
#data-procss文件
#進行數據處理
import os, re #調用os,re正則表達式
from PIL import Image #通過PIL庫導入照片類
import numpy as np
#自定義函數獲取指定路徑中的所有圖片名稱
path = 'water_images/'
def get_img_names(path=path):
file_names = os.listdir(path)
img_names = []
for i in file_names:
if re.findall('\d_\d+\.jpg$',i) !=[] : #\d表示數字,\d+表示至少一個數字,\.運用\表示轉意符號,$表示結尾
img_names.append(i) #append對元素i的追加
return img_names
def var(rd): #求顏色通道的三階顏色距
mid = np.mean((rd-rd.mean())**3)
return np.sign(mid)*abs(mid)**(1/3)
#獲取樣本數據:自變量data和標籤 labels
def get_img_data(path=path):
img_names = get_img_names(path=path) #獲取所有圖片的名稱
n = len(img_names)
data = np.zeros([n,9]) #data保存所有樣本自變量
labels = np.zeros([n]) #樣本標籤
for i in range(n):
img = Image.open(path+img_names[i]) #讀取圖片數據
M, N = img.size #像素矩陣的行列數
box = (M/2-50, N/2-50, M/2+50, N/2+50)
region = img.crop(box) #用crop方法截取圖像的中心區域
#region.show()
#img.show() #展示圖片
#數據預處理
r, g, b = region.split() #分割像素通道
rd = np.asarray(r) #把圖片數據轉換爲數組
gd = np.asarray(g)
bd = np.asarray(b)
data[i, 0] = rd.mean() #一階顏色距
data[i, 1] = gd.mean()
data[i, 2] = bd.mean()
data[i, 3] = rd.std() #二階顏色距
data[i, 4] = gd.std()
data[i, 5] = bd.std()
data[i, 6] = var(rd) #三階顏色距
data[i, 7] = var(gd)
data[i, 8] = var(bd)
labels[i] = img_names[i][0]
return data, labels
#main
#模型構建與性能評估
from data_process import get_img_data # 導入數據預處裏的函數
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, confusion_matrix
data, labels = get_img_data() # 數據預處理
data_tr, data_te, labels_tr, labels_te = train_test_split(data, labels, test_size=0.2) # 將專家樣本拆分爲訓練集和測試集
Dtc = DecisionTreeClassifier().fit(data_tr, labels_tr) # 模型訓練
pre = Dtc.predict(data_te) # 模型預測
sum(pre==labels_te)/len(pre) # 預測精度
confusion_matrix(labels_te, pre) # 混淆矩陣
classification_report(labels_te, pre) # 分類性能報告
運行結果: