基于OpenCV、随机森林算法实现的图像分类识别系统

一、数据准备

二、划分训练集-测试集

三、特征表示

对图片数值化
常用特征:
    颜色直方图(Color Histograms)
    方向梯度直方图(Histograms of Oriented Gredient,HOG)
    局部二值模式(Local Binary Pattern,LBP)

四、分类算法

逻辑回归
支持向量机(SVM)
随机森林

五、模型评估

对测试集的图片进行预测,并与正确类别进行比较
分类器性能指标:
    精确度(Precision)
    召回率(Recall)
    F1值(F1 score)

六、OpenCV是一个基于BSD许可发行的跨平台计算机视觉库

安装:
conda install -c menpo opencv
opencv的导入:import cv2
              cv2.__version__

OpenCV的使用
    在线文档:http://docs.opencv.org/2.4.11/

七、颜色空间(颜色模型)

常见颜色空间有:
    RGB :模型容易理解,连续变换颜色时不直观
        (红red    绿green    蓝blue)三原色:
        RGB取值范围[[0,255][0,255][0,255]]

HSV 是为了数字化图像提出来了,不能很好的表示人眼解释图像过程
    H (Hue)色相:[0,360]
    S (Saturation)饱和度,即色彩纯净度,0饱和度为白色
    V (Value/Brightness):明度 0明度为纯黑色

    在OpenCV中
        H = [0,179]
        S = [0,255]
        V = [0,255]
Lab:颜色之间的欧式距离有具体含义--距离越大,人眼感官两种颜色差距越远
    L 通道:像素亮度,上白下黑 中间灰
    a 通道:左绿 右红
    b 通道:一端纯蓝,一端纯黄

灰度图:每个像素[0,255]
    根据人眼敏感度,把RGB图片转换为灰度图,不是简单把RGB每个通道取平均值
    而是:
        Y = 0.299*R + 0.587*G + 0.114*B
代码:

import cv2                      #导入 Opencv
cv2.__version__
import os 
output_dir = 'output2'          #设置输出文件夹,若不存在则创建
if not os.path.exists(output_dir):
    os.mkdir(output_dir)    

img_file = './../image.png'     #读取图片
img = cv2.imread(img_file)

type(img)                       #读入图片后得到ndarray 对象
img.shape                       #ndarray的三个维度分别是图片的:高,宽,通道

#使用 matplotlib 显示图片
import matplotlib.pyplot as plt
import numpy as np

# pyplot.imgshow 在显示图片时是按照RGB通道顺序显示,cv2则相反
# 需要通过 np.flip(img,axis = 2) 调整3个通道的顺序
plt.imshow(np.flip(img,axis = 2))
plt.axis('off')
plt.show()

#输出并保存图片
output_image = os.path.join(output_dir,'image.png')
cv2.imwrite(output_image,img)

 #----------图像特征:颜色直方图-------------
import numpy as np
import cv2
from matplotlib import pyplot as plt
%matplotlib inline
 #RGB颜色空间
img_b = img_bgr[...,0]
img_g = img_bgr[...,1]
img_r = img_bgr[...,2]
fig = plt.gcf()
 #分通道显示图片:略

 #HSV颜色空间
img_hsv = cv2.cvtColor(img_bgr,cv2.COLOR_BGR2HSV)
img_h = img_bgr[...,0]
img_s = img_bgr[...,1]
img_v = img_bgr[...,2]
 #分通道显示图片:略

 #L*a*b颜色空间
img_lab = cv2.cvtColor(img_bgr,cv2.COLOR_BGR2LAB)
img_ls = img_bgr[...,0]
img_as = img_bgr[...,1]
img_bs = img_bgr[...,2]
 #分通道显示图片:略

 #灰度图
img_gray = cv2.cvtColor(img_bgr,cv2.COLOR_BGR2GRAY)

 #----------图像分类-------------
import numpy as np
import cv2
import os
from sklearn.model_selection import train_test_split
from sklearn.preprocession import LabelEncoder
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import comfusion_matrix,precision_recall_fscore_support
import pandas as pd
import pickle

output_dir = 'output'
if not os.path.exist(output_dir):
    os.mkdir(output_dir)

 #1 数据准备
image_dir = '../data/images'
images = []
labels = []
for fname in os.listdir(image_dir)
    #跳过不是目标图片的文件
    if not fname.stratswith('image'):   continue
    fpath = os.path.join(image_dir,fname)
    #根据文件名,提取图片分类
    lab = fpath.split('_')[1]
    #RGB模式读取图片
    img = cv2.imread(fpath,cv2.IMREAD_COLOR)
    images.append(img)
    labels.append(lab)

 #将图片标签ID化
label_encoder = LabelEncoder()
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):
    # 每个通道等分为8组后 计算直方图
    hist = cv2.calcHist([img],[0,1,2],None,[s]*3,[0,256]*3)
    # 将多维数组 8*8*8 的多维数组拉平
    return hist.ravel()

 #提取每个图像的直方图
x = np.row_stack([transform(img) for img in image])

train_x = x[train_idx,:]
test_x = x[train_idx,:]

 #2.2 使用随机森林--训练分类器
model = RandomForestClassifier(n_estimators = 15,max_depth = 3,random_state = 1234)#n_estimastors 子模型个数(10-200)-默认10,太小容易欠拟合,反之过拟合
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_cf1.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)
    #计算总体的平均 Precision, Recall, f1, support
    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 = '12',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                           #各项评价指标


 #4使用分类器对新图像分类
 #定义一个用于分类的 Predictor 类
class Predictor(object):

    def __init__(self,model_file):
        with open(model_file,'rb') as infile:
            self.loaded = pickle.load(infile)
        self.model = self.loaded['model']
        self.label_encoder = self.loaded['label_encoder']

    #实现分类逻辑
    def predict(self,img_file):
        img = cv2.imread(img_file,cv2.IMREAD_COLOR)          #读取图像文件
        img = cv2.cvtColor(img,cv2.COLOR_BGR2LAB)            #颜色空间-->Lab
        #计算颜色直方图
        x = cv2.calcHist([img],[0,1,2],None,[8]*3,[0,256]*3) #返回(8,8,8)的 ndarray

        x = x.reshape((1,-1))             #变形为(1,512)的 ndarray
        y = self.model.predict(x)         #预测分类

        #转化为原始标签
        label = self.label_encoder.inverse_transform(y)
        return

predictor = Predictor(os.path.join(output_dir,'model_rf2.pkl'))
 #对新图片进行分类
predictor.predict('./../data/images/image_crous_001.png')   

猜你喜欢

转载自blog.csdn.net/wsp_1138886114/article/details/80660014
今日推荐