基于水色图像的水质评价
基于水色图像的水质评价(完整代码)
实验介绍
水质的好坏跟水色有一定关系,有经验的从事渔业生产的从业者可通过观察水色变化调控水质。
本次实战的目标是通过水色图像实现水质的自动评价。
下面水色与水质的关系表:
数据探索分析
数据源
在‘data/images’目录下给出了某地区的多个罗非鱼池塘水样的数据,根据上节给出的水产专家按水色判断水质分类的数据表来对数据进行探索分析。每个水质图片的命名规则为“类别_编号.jpg”,如1_1.jpg说明当前图片属于第一类的样本。
问题抽象
根据概率论的理论,随机变量的概率分布可以由其各阶矩唯一表示和描述。一幅图像的色彩分布也可以认为是一种概率分布,那么图像可以由其各阶矩来描述。颜色矩包含各个颜色通道的一阶矩、二阶矩和三阶矩,对于一幅RGB颜色空间图像,具有R、G和B三个颜色通道,则有9个分量。
将采集到的水样图像进行分割,采用颜色矩来提取水样图像的特征。
(1)一阶颜色矩
一阶颜色矩采用一阶原点矩,反映图像的整体明暗程度。
其中,Ei是在第i个颜色通道的一阶颜色矩,对于RGB颜色空间的图像,i=1,2,3。其中pij是第j个像素的第i个颜色通道的颜色值。
(2)二阶颜色矩
二阶颜色矩采用的是二阶中心矩的平方根,反映图像颜色的分布范围。
其中σi是在第i个颜色通道的二阶颜色矩,Ei是在第i个颜色通道的一阶颜色矩。
(3)三阶颜色矩
三阶颜色矩采用的是三阶中心距的立方根,反映图像颜色分布的对称性。
其中,si是在第i个颜色通道的三阶颜色矩,Ei是在第i个颜色通道的一阶颜色矩。
我们将对所有的水样图像进行特征提取,得到水质类别和水样特征的数据。
数据特征提取
我们将图像中颜色矩特征进行提取,并对数据进行规范化,使其取值在[0,1]之间。对图像中心区域的抽取可以采用pillow库来完成。
此处对书中给出的原始图片数据进行特征提取,并对结果进行规范化,使用该值直接应用到向量机模型,并未使用书中所给数据,分类效果较好。
编写以下代码进行颜色矩的抽取。
import numpy as np
import pandas as pd
from sklearn import preprocessing
from PIL import Image
import os
def PicManage(path,i):
pic = Image.open(path)
pic.c_x, pic.c_y = (int(i/2) for i in pic.size)
box = (pic.c_x-50, pic.c_y-50, pic.c_x+50, pic.c_y+50)
#从图片中提取中心100*100的子矩形
region = pic.crop(box)
#切分RGB
r, g, b = np.split(np.array(region), 3, axis = 2)
#计算一阶矩
r_m1 = np.mean(r)
g_m1 = np.mean(g)
b_m1 = np.mean(b)
#二阶矩
r_m2 = np.std(r)
g_m2 = np.std(g)
b_m2 = np.std(b)
#三阶矩
r_m3 = np.mean(abs(r - r.mean())**3)**(1/3)
g_m3 = np.mean(abs(g - g.mean())**3)**(1/3)
b_m3 = np.mean(abs(b - b.mean())**3)**(1/3)
#将数据标准化,区间在[-1,1]
typ = np.array([i])
arr = np.array([r_m1,g_m1,b_m1,r_m2,g_m2,b_m2,r_m3,g_m3,b_m3])
#df = pd.DataFrame(preprocessing.minmax_scale(arr,feature_range=(-1,1))).T
df = pd.DataFrame(arr).T
dn = pd.DataFrame(typ).T
return df,dn
result = []
type_result = []
for i in os.listdir('./data/images'):
if i.endswith('.jpg'):
df,dn = PicManage('./data/images/'+i,int(i[0]))
result.append(df)
type_result.append(dn)
data = pd.concat(result)
typ = pd.concat(type_result)
data = pd.DataFrame(preprocessing.normalize(data,norm='l2'))
data['type'] = typ.values
data.to_excel('picData.xls',index = False)
运行代码后,在picData.xls文件中可以看到我们将图片数据中的特征提取为颜色矩的值。
支持向量机模型建立
对特征提取后的样本进行抽样,抽取80%作为训练样本,剩下的20%作为测试样本,用于水质评价检验。
本实验擦用支持向量机作为水质评价分类模型,模型的输入包括两部分,一部分为训练样本的输入,另一部分为建模参数的输入。
对处理后的数据观察发现,数据之间的区分度较小。我们考虑将所有特征统一乘以一个适当的常数k,从而提高区分度和准确度。k值过大容易导致训练样本的过拟合,过小导致区分度低,模型准确率差。本次建模中k的最优值为30。
新建文件,输入以下代码:
#-*- coding:utf-8 -*-
import pandas as pd
#datapath = './data/moment.csv'
#data = pd.read_csv(datapath,encoding = 'gbk')
data = data.values
#划分训练集和测试集
#cross_validation在sklearn0.20中改为model_selection
from sklearn.model_selection import train_test_split
train, test, train_target, test_target = train_test_split(data[:,0:],data[:,-1],test_size=0.2)
train_target = train_target.astype(int)
test_target = test_target.astype(int)
#构建SVM模型
from sklearn import svm
model = svm.SVC()
model.fit(train*30,train_target)
#save model
from sklearn.externals import joblib
joblib.dump(model,'svcmodel.pkl')
#read model
#model = joblib.load('svcmodel.pkl')
#混淆矩阵
from sklearn import metrics
cm_train = metrics.confusion_matrix(train_target, model.predict(train*30))
cm_test = metrics.confusion_matrix(test_target, model.predict(test*30))
train_accuracy = metrics.accuracy_score(train_target,model.predict(train*30))
test_accuracy = metrics.accuracy_score(test_target,model.predict(test*30))
print("train accuracy: %f"% train_accuracy) #1.000
print("test accuracy: %f"% test_accuracy) #0.9756
tr = pd.DataFrame(cm_train,index = range(1,6),columns = range(1,6)).to_excel('train.xls')
te = pd.DataFrame(cm_test,index = range(1,6),columns = range(1,6)).to_excel('test.xls')
建立模型后,利用训练样本进行回判,得到的混淆矩阵如下,分类准确率为100%,分类效果很好。可应用模型进行水质评价。
模型评价
在上节代码中,我们将所有的测试样本作为输入样本,代入已经构建好的支持向量机模型,得出输出结果,即预测的水质类型。水质评价的混淆矩阵如下表。分类准确率为97.56%,说明水质评价模型对于新增的水色图像的分类效果较好,实现水质评价。
参考:
https://blog.****.net/qq_26978413/article/details/78400290
http://www.dydpg.com/2018/09/06/基于水色图像的水质评价/