1、安装libsvm
在虚拟环境中pip install -U libsvm-official
测试代码:
from libsvm.svmutil import *
from libsvm.svm import *
y, x = [1, -1], [{1: 1, 2: 2}, {1: 1, 2: 0}]
prob = svm_problem(y, x)
param = svm_parameter('-t 0 -c 4 -b 1')
model = svm_train(prob, param)
yt = [1]
xt = [{1: 2, 2: 3}]
p_label, p_acc, p_val = svm_predict(yt, xt, model)
print(p_label)
结果图:
2、代码
参考:python使用libsvm
python 使用 libsvm
from libsvm.svmutil import *
import joblib
from skimage.feature import local_binary_pattern
import cv2
from skimage.feature import hog
import numpy as np
def get_image_list(dirname,size): #加载图片
img_list = []
for i in range(size):
path = dirname+ str(i) +'.png' #图片存放路径
img = cv2.imread(path) #调用opencv的imread函数读取图片,得到一个通道为三的数组
img_list.append(img)
path = dirname
return img_list
def write(label,save_path,feature): #保存特征 ###大概是这样的。自己摸索的,不知道对不对,反正能训练
###例:标签(1)+空格(‘ ’)+ 序号(从1开始str(j + 1))+冒号(‘:’)+特征值+空格(‘ ’)换行('\n')
###例如1 1:31.077399380804952 2:71.24458204334366 3:214.22600619195046 4:5.040721180244506 5:9.946245307810633 6:27.205359467206083 7:5.467070774735018 8:11.444525326546477 9:29.464294388212977
### 1 1:0.04953560371517028 2:0.05263157894736842 3:0.02476780185758514 4:0.018575851393188854 5:0.0 6:0.030959752321981424 7:0.021671826625386997 8:0.03715170278637771 9:0.058823529411764705 10:0.05263157894736842 11:0.09907120743034056 12:0.0804953560371517 13:0.06191950464396285 14:0.04953560371517028 15:0.018575851393188854 16:0.021671826625386997 17:0.009287925696594427 18:0.01238390092879257 19:0.009287925696594427 20:0.0030959752321981426 21:0.0 22:0.01238390092879257 23:0.0030959752321981426 24:0.006191950464396285 25:0.01238390092879257 26:0.25386996904024767
###一张图片的标签在最前方。之后是特征值,每张图片的特征值在一行,下一张图片需要换行。例如纹理特征,有9个值,序号就从1-9。hog有12480个值,序号就从1-12480.
with open(save_path, 'a', encoding='utf-8') as f:
text = str(label) + ' '
f.write(text)
length = len(feature)
for j in range(0, length):
with open(save_path, 'a', encoding='utf-8') as f:
text = str(j + 1) + ':' + str(feature[j]) + ' '
f.write(text)
with open(save_path, 'a', encoding='utf-8') as f:
text = '\n'
f.write(text)
#灰度值
def rgb2gray(im):
gray = im[:, :, 0] * 0.2989 + im[:, :, 1] * 0.5870 + im[:, :, 2] * 0.1140
return gray
def lbp(image): #纹理特征,代码copy的
radius = 3
n_points = 8 * radius
# 转换为灰度图显示
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 处理
lbp = local_binary_pattern(image, n_points, radius, method='uniform')
#'default':原始的局部二值模式,它是灰度但不是旋转不变的。
#'ror':扩展灰度和旋转不变的默认实现。
#'uniform':改进的旋转不变性和均匀的模式以及角度空间的更精细的量化,灰度和旋转不变。
#'nri_uniform':非旋转不变的均匀图案变体,它只是灰度不变的R199。
#'VAR':局部对比度的旋转不变方差度量,图像纹理是旋转但不是灰度不变的。
n_bins = int(lbp.max() + 1)
lbp_hist, _ = np.histogram(lbp, density=True, bins=n_bins, range=(0, n_bins)) # 绘制直方图,百分比normed=True,像素个数normed=flase
# lbp_hist, _ = cv2.calcHist([lbp],[0],None,[256],[0,255])#像素个数
return lbp_hist
def color_moments(img): #颜色矩特征 代码copy的
# Convert BGR to HSV colorspace
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# Split the channels - h,s,v
h, s, v = cv2.split(hsv)
# Initialize the color feature
color_feature = []
# N = h.shape[0] * h.shape[1]
# The first central moment - average
h_mean = np.mean(h) # np.sum(h)/float(N)
s_mean = np.mean(s) # np.sum(s)/float(N)
v_mean = np.mean(v) # np.sum(v)/float(N)
color_feature.extend([h_mean, s_mean, v_mean])
# The second central moment - standard deviation
h_std = np.std(h) # np.sqrt(np.mean(abs(h - h.mean())**2))
s_std = np.std(s) # np.sqrt(np.mean(abs(s - s.mean())**2))
v_std = np.std(v) # np.sqrt(np.mean(abs(v - v.mean())**2))
color_feature.extend([h_std, s_std, v_std])
# The third central moment - the third root of the skewness
h_skewness = np.mean(abs(h - h.mean())**3)
s_skewness = np.mean(abs(s - s.mean())**3)
v_skewness = np.mean(abs(v - v.mean())**3)
h_thirdMoment = h_skewness**(1./3)
s_thirdMoment = s_skewness**(1./3)
v_thirdMoment = v_skewness**(1./3)
color_feature.extend([h_thirdMoment, s_thirdMoment, v_thirdMoment])
return color_feature
def clear(path): #清除txt中的内容
with open(path, 'a', encoding='utf-8') as f:
f.truncate(0)
def pos_feat():
img_list = get_image_list(pos_path,pos_size) #读取正样本图片
for image in img_list:
lbp=lbp(image) #提取lbp特征
write(1,lbp_save_txt,lbp) #保存
color = color_moments(image) #提取color特征
write(1, color_save_txt, color) #保存
image_height = 128 #hog特征,不知道为什么,一放到def中,就出错。就这样凑合用吧
image_width = 64
pred_img = cv2.resize(image, (64, 128), interpolation=cv2.INTER_AREA)
image = np.reshape(pred_img, (image_height, image_width, 3))
gray = rgb2gray(image) / 255.0
# 这句话根据你的尺寸改改
fd = hog(gray, orientations=12, block_norm='L1', pixels_per_cell=[8, 8], cells_per_block=[4, 4],
visualize=False,
transform_sqrt=True)
write(1, hog_save_txt, fd) #保存
def neg_feat():
img_list = get_image_list(neg_path,neg_size)
for image in img_list:
lab = lbp(image) #提取lbp特征
write(-1, lbp_save_txt, lab) #保存
color = color_moments(image) #提取lbp特征
write(-1, color_save_txt, color) #保存
image_height = 128
image_width = 64
pred_img = cv2.resize(image, (64, 128), interpolation=cv2.INTER_AREA)
image = np.reshape(pred_img, (image_height, image_width, 3))
gray = rgb2gray(image) / 255.0
# 这句话根据你的尺寸改改
fd = hog(gray, orientations=12, block_norm='L1', pixels_per_cell=[8, 8], cells_per_block=[4, 4],
visualize=False,
transform_sqrt=True)
write(-1, hog_save_txt, fd) #保存
#训练和测试
def train(path,save_path):
train_label, train_pixel = svm_read_problem(path) #读取训练图片的标签和特征
per_80 = int(np.floor(0.8 * len(train_label))) #copy别人的,不知道有什么用 https://blog.csdn.net/weixin_45226065/article/details/131561808
model = svm_train(train_label[:per_80], train_pixel[:per_80], '-c 4') #训练
svm_save_model(save_path, model) #保存训练后的模型
print("训练之后的模型存放在model文件夹中")
def test(test_image,test_feature_txt,model_path): #测试一张图片,若要改为测试文件夹的图片,也简单的
img = cv2.imread(test_image) #读取测试图片
feature = color_moments(img) #提取颜色特征
write(1, test_feature_txt, feature) #保存颜色特征。因为预测图片不清楚是否含有目标,我只需要预测的标签,所以标签随意赋值为1。若需要准确度,可将这个值改为待测图片的标签。
model = svm_load_model(model_path) #提取颜色特征训练的lisvm模型
test_label, test_pixel = svm_read_problem(test_feature_txt) #读取测试图片的标签和特征
p_label, p_acc, p_val = svm_predict(test_label, test_pixel, model) #预测
return p_label #我只需要预测的标签值
if __name__ == '__main__':
pos_path = "images\\pos\\" # 正样本图像地址
neg_path = "images\\neg\\" # 负样本图像地址
pos_size=472 #正样本图片数量
neg_size=456 #负样本图片数量
color_save_txt = 'feature\\color.txt' #color特征保存的txt libsvm数据格式
hog_save_txt = 'feature\\hog.txt' #hog特征保存的txt libsvm数据格式
lbp_save_txt = 'feature\\lbp.txt' #lbp特征保存的txt libsvm数据格式
color_model_path='model/libsvm_color.model' #训练之后模型保存的地址。
hog_model_path='model/libsvm_hog.model'
lbp_model_path='model/libsvm_lbp.model'
test_image='images/temp_pictures/27.png' #测试图片地址
test_feature_txt='text_feature.txt' #测试图片特征保存地址
need_extra_feat = input('是否需要重新训练模型?y/n\n')
if need_extra_feat == 'y':
clear(color_save_txt) #清除txt中的内容
clear(hog_save_txt)
clear(lbp_save_txt)
pos_feat() #提取正样本特征
neg_feat() #提取负样本特征
print("特征提取完成")
######我还不会特征融合,要是将3个特征融合的话,会更好一点#######
train(color_save_txt, color_model_path) #训练
train(hog_save_txt, hog_model_path)
train(lbp_save_txt, lbp_model_path)
result=test(test_image, test_feature_txt, color_model_path) #测试,仅颜色特征的预测标签
print(result) #预测的标签值