opencv舌頭監測模型+keras神經網絡(LeNet)

基於前面使用opencv實現舌頭模型檢測後,本次主要針對模型參數調優,提升圖片識別率。算法

以前的模型精準率很高,但召回率不必定爲1,有時候舌頭圖片並無被圈出。因此咱們須要調整參數讓模型吧舌頭都識別出來,再經過LeNet模型作後續識別,將不是舌頭的剔除掉。數組

首先修改opencv訓練後的模型參數,調低scaleFactor值,讓模型更敏感,圈出更多的圖片(舌頭+額外的其餘非舌頭圖片)網絡

在默認參數(scaleFactor=1.38, minNeighbors=4, minSize=(20,20),), app

Cascades模型的識別率偏低但精度高,ide

在該參數下,在數據規模爲500的測試集中,一共切割出446張小圖,覆蓋了500張圖片中的398張圖片,剩餘的48張小圖爲識別錯誤圖片,或冗餘圖片。函數

修改成:(scaleFactor=1.002,, minNeighbors=3, minSize=(3,3),),測試

在該參數下,在數據規模爲500的測試集中,一共切割出4823張小圖,覆蓋了500張圖片中的499張圖片,剩餘的4324張小圖爲識別錯誤圖片,或冗餘圖片。spa

對比發現,前者的精準率很高,但召回率低於後者。因此咱們在加上LeNet模型對後者進行再次過來篩選。3d

收集整理數據集

在上一個步驟中,咱們經過Cascades算法共得到4823切割後的小圖,首先咱們須要人工把這些圖片分爲正樣本(是舌頭)和圖樣本(非舌頭)。blog

考慮到後期神經網絡模型的計算量,在載入數據時,咱們會將圖片標化爲200 * 200的灰度圖片,分完後的效果以下:

正樣本:


負樣本:

構建卷積神經網絡並訓練

爲了提升模型的判別準確率,咱們構建了一個深度爲15層的卷積神經網絡,

卷積網絡的輸入是以200 * 200 的灰度圖片,輸出是一個0-1以前的值,該值是一個機率值,

import cv2
import os
import numpy as np
import tensorflow as tf

import keras.backend as K
from keras.datasets import mnist
from keras.layers import *
from keras.models import *
from keras.optimizers import *
from keras.initializers import *
from keras.callbacks import *
from keras.utils.vis_utils import plot_model#顯示層級圖
from tqdm import tqdm


def loadGrayImg(path, shape=(200, 200, 1)):
    """
    獲取灰度值圖片
    :param path:
    :return:
    """
    img = cv2.imread(path)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (shape[0], shape[1]))
    return np.reshape(img, shape)


def loadData(dir, shape=(200, 200, 1)):
    """
    加載數據集
    :param dir:
    :return:
    """
    imgs = []
    for fn in os.listdir(dir):
        if fn.endswith('jpg'):
            imgs.append(loadGrayImg(os.path.join(dir, fn), shape=(200, 200, 1)))
    return np.array(imgs)#轉換爲numpy矩陣


def net():
    """卷及網絡模型"""
    inputs = Input(shape=(200, 200, 1))
    model = Lambda(lambda x: (x - 127.5) / 127.5)(inputs)#將像素值變爲(-1,-1)----灰度值是從0-255
    #卷積層--16個特徵圖,關機過濾器(5*5),步長2*2,特徵圖大小:(200-5+2)/2=98
    model = Conv2D(16, 5, strides=(2, 2))(model)
    #激活層--高級激活層Advanced Activation-----LeakyReLU層,LeakyRelU是修正線性單元(Rectified Linear Unit,ReLU)的特殊版本,當不激活時,
    # LeakyReLU仍然會有非零輸出值,從而得到一個小梯度,避免ReLU可能出現的神經元「死亡」現象。即,f(x)=alpha * x for x < 0, f(x) = x for x>=0

    #  sigmoid和tanh在x趨於無窮的兩側,都出現導數爲0的現象,成爲軟飽和激活函數。也就是形成梯度消失的狀況,從而沒法更新網絡狀態。
  # relu的主要特色就是:單側抑制,相對寬闊的興奮邊界,稀疏激活性。稀疏激活性,是指使得部分神經元輸出爲0,形成網絡的稀疏性,
  #緩解過擬合現象。可是當稀疏過大的時候,出現大部分神經元死亡的狀態,所以後面還有出現改進版的prelu.就是改進左側的分佈
    model = LeakyReLU()(model)
    #池化層----輸出49*49*16
    model = MaxPooling2D(strides=2)(model)
    #卷積層---32個特徵圖,(49-5+2)/2=23-------輸出23*23*32
    model = Conv2D(32, 5, strides=(2, 2))(model)
    #激活層
    model = LeakyReLU()(model)
    #池化層--輸出11*11*32
    model = MaxPooling2D(strides=2)(model)
    #卷積層--64個特徵圖feature map,輸出(11-5+2)/2=4*4*64
    model = Conv2D(64, 5, strides=(2, 2))(model)
    #激活層
    model = LeakyReLU()(model)
    #池化層---輸出2*2*64
    model = MaxPooling2D(strides=2)(model)
    #展開層--輸出256
    model = Flatten()(model)
    #drop層,默認0.5最好
    model = Dropout(0.2)(model)
    #全鏈接層,壓縮爲須要的維度128,若是本層的輸入數據的維度大於2,則會先被壓爲與kernel相匹配的大小。
    model = Dense(128)(model)
    # 全鏈接層,壓縮爲須要的維度128
    model = Dense(units=1, activation='sigmoid')(model)#使用simgod輸出0-1之間的值 ,二分類
    #生成模型
    model = Model(inputs=inputs, outputs=model)
    #運行模型,開始訓練
    model.compile(optimizer='nadam', loss='binary_crossentropy', metrics=['accuracy'])
    return model


def train(echos=500, batch_size=128):
    """訓練模型"""
    model = net()
    model.summary()
    plot_model(model, show_shapes=True, show_layer_names=True)

    positive = loadData('train/positive')#加載正數據
    negtive = loadData('train/negtive')#加載負數據
    #合併兩個矩陣----至關於拼接到前面一個數組的後面
    x = np.concatenate([positive, negtive])
    y = np.zeros(len(x))
    #賦值標籤
    y[0:len(positive)] = 1.
    y[len(positive):] = 0.

#進度條
    for i in tqdm(range(int(echos))):
        model.fit(x, y, batch_size=batch_size)#訓練傳入數據和標籤
        model.save('model/tongue_%d.model' % i)


if __name__ == '__main__':
    train()

最後整合Cascades模型和卷積網絡模型,作圖像切割

在識別和切割舌頭頭圖片時,主要用到了Cascades模型和卷積網絡模型兩種算法模型。

其中Cascades模型主完成於舌頭的座標定位;隨後咱們會根據這個鞋座標切割出一組圖像,而卷積網絡模型則用於計算這一組圖像中每個圖片屬於舌頭的機率,最終選取機率最高的一張做爲輸出。

相關文章
相關標籤/搜索