1. 程式人生 > >基於OpenCV、隨機森林演算法實現的影象分類識別系統

基於OpenCV、隨機森林演算法實現的影象分類識別系統

開發環境jupyter notebook
import cv2
import os
import pickle                               #持久化
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import
LogisticRegression from sklearn.metrics import confusion_matrix, precision_recall_fscore_support output_dir = 'output' #圖片儲存目錄 if not os.path.exists(output_dir): os.mkdir(output_dir)

1 資料準備

image_dir = '../data/images'                     #圖片路徑

images = []
labels = []
for
fname in os.listdir(image_dir): if not fname.startswith('image'): continue # 跳過不是目標圖片的檔案 fpath = os.path.join(image_dir, fname) lab = fpath.split('_')[1] # 根據檔名,提取圖片分類 img = cv2.imread(fpath, cv2.IMREAD_COLOR) # RGB模式讀取圖片 images.append(img) #獲取所有圖片
labels.append(lab) # label_encoder = LabelEncoder() # 將圖片標籤ID化 y = label_encoder.fit_transform(labels) # 訓練集,測試集劃分 train_idx, test_idx = train_test_split(range(len(y)), test_size=0.2, stratify=y, random_state=1234) train_y = y[train_idx] test_y = y[test_idx]

2 使用RGB顏色直方圖做特徵訓練分類器

2.1 計算RGB顏色直方圖
# 定義特徵轉化函式
def transform(img):
    hist = cv2.calcHist([img], [0,1,2], None, [8]*3, [0,256]*3) # 每個通道等分為8組後計算直方圖
    return hist.ravel()                                         # 將8x8x8的多維陣列展平


x = np.row_stack([transform(img) for img in images])            # 提取每個影象的直方圖特徵
train_x = x[train_idx, :]
test_x = x[test_idx, :]
2.2 隨機森林—訓練分類器
"""
    RandomForestClassifier 常用引數

    n_estimators: 整數,樹的個數,預設10,樹越多擬合效果越好,也越容易過擬合
    criterion: 衡量樹的某次分裂好壞的指標,可選值有{'gini', 'entropy'}
    max_features: 尋找最佳分裂時最多使用多少個特徵
         如果為int,表示每次分裂時的最大特徵數
         如果為float,則最大特徵數為int(max_features * n_features)
         如果為'auto',則max_features=sqrt(n_features)
         如果為'sqrt',則max_features=sqrt(n_features)
         如果為'log2',則max_features=log2(n_features)
         如果為None,則max_features=n_features
     max_depth: int或None,每個樹最大的深度。預設None,表示每個樹節點會一直分裂直到所有
         的葉子節點都是純的,或者包含min_samples_split個樣本。深度越深,越容易過擬合。
     min_samples_split: int或float,預設為2,對一個節點進行分裂時,至少需要這麼多樣本。
         int: 表示樣本數
         float: 表示比例,即最小樣本數為 ceil(min_samples_split * n_samples)
     min_samples_leaf: int或float,預設為1,葉子節點至少需要這麼多樣本
         int: 表示樣本數
         float: 表示比例,樣本數為 ceil(min_samples_leaf * n_samples)
"""
model = RandomForestClassifier(n_estimators=15, max_depth=3, random_state=1234)
model.fit(train_x, train_y)        #擬合訓練
# 儲存模型
def save_model(model, label_encoder, output_file):
    try:
        with open(output_file, 'wb') as outfile:
            pickle.dump({
                'model': model,
                'label_encoder': label_encoder
            }, outfile)
        return True
    except:
        return False

save_model(model, label_encoder, os.path.join(output_dir, 'model_rf1.pkl'))
2.3 評估隨機森林分類器
# 計算各項評價指標
def eval_model(y_true, y_pred, labels):
    # 計算每個分類的Precision, Recall, f1, support
    p, r, f1, s = precision_recall_fscore_support(y_true, y_pred)
    tot_p = np.average(p, weights=s)
    tot_r = np.average(r, weights=s)
    tot_f1 = np.average(f1, weights=s)
    tot_s = np.sum(s)
    res1 = pd.DataFrame({
        u'Label': labels,
        u'Precision': p,
        u'Recall': r,
        u'F1': f1,
        u'Support': s
    })
    res2 = pd.DataFrame({
        u'Label': [u'總體'],
        u'Precision': [tot_p],
        u'Recall': [tot_r],
        u'F1': [tot_f1],
        u'Support': [tot_s]
    })
    res2.index = [999]
    res = pd.concat([res1, res2]) 

# 計算混淆矩陣
conf_mat = pd.DataFrame(confusion_matrix(y_true, y_pred), columns=labels, index=labels)
return conf_mat, res[[u'Label', u'Precision', u'Recall', u'F1', u'Support']]

# 在測試集上計算每個圖片的預測分類
y_pred = model.predict(test_x)

# 評估模型
conf_mat, evalues = eval_model(test_y, y_pred, label_encoder.classes_)
conf_mat                         #檢視混淆矩陣
evalues                          # 各項評價指標

這裡寫圖片描述

2.4 邏輯迴歸—訓練分類器
model = LogisticRegression(penalty='l2', C=1, random_state=1234)
model.fit(train_x, train_y) 

save_model(model, label_encoder, os.path.join(output_dir, 'model_lr1.pkl'))
2.5 評估邏輯迴歸分類器
# 在測試集上計算每個圖片的預測分類
y_pred = model.predict(test_x)

# 評估模型
conf_mat, evalues = eval_model(test_y, y_pred, label_encoder.classes_) 
conf_mat              #混淆矩陣
evalues               #各項評價指標