用到一个数据集stanford40,共有40类图像,每类约200个,数量不定。在确定数据集后,将数据集分为测试集和训练集两部分。
第一步,提取图像特征。用caffe的模型进行提取。最开始考虑提取特征的时候,搜索了很多网上的方法,各种让你建立文件名文件以及train_caffenet等等,我试了很久,各种各样的报错,于是开始用caffe中的model提取特征就好。代码如下:
import os,sys,cv2,skimage
import numpy as np
import scipy.io as sio
import cv2
#import matplotlib.pyplot as plt
prototxt_path = '/media/meddisk/model/deploy.prototxt'
caffe_model_path = '/media/meddisk/model/bvlc_alexnet.caffemodel'
dataset_dir = '/media/new_disk]/caffe/data/train'
feature_dir = '/media/new_disk]/alexnet_feature'
caffe_root = '/home/library/caffe-master/'
sys.path.append(caffe_root + 'python/')
import caffe
caffe.set_mode_gpu()
net = caffe.Net(prototxt_path,caffe_model_path,caffe.TEST)
# input preprocessing: 'data' is the name of the input blob == net.inputs[0]
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))
transformer.set_mean('data', np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy').mean(1).mean(1)) # mean pixel
transformer.set_raw_scale('data', 255) # the reference model operates on images in [0,255] range instead of [0,1]
transformer.set_channel_swap('data', (2,1,0)) # the reference model has channels in BGR order instead of RGB
net.blobs['data'].reshape(1,3,227,227)
def get_feature(pth):
net.blobs['data'].data[...] = transformer.preprocess('data', caffe.io.load_image(pth))
out = net.forward()
feature = net.blobs['fc7'].data[0]
feature = feature.reshape(1,-1).tolist()
return feature
if __name__ == '__main__':
for root, dirs, files in os.walk(dataset_dir):
# i = 0;
real_output_dir = root.replace(dataset_dir, feature_dir)
# real_output_dir_20 = real_output_dir.replace('feature','feature(20)')
if not os.path.exists(real_output_dir):
os.mkdir(real_output_dir)
# if not os.path.exists(real_output_dir_20):
# os.mkdir(real_output_dir_20)
for file in files:
feat_vec = get_feature(root + os.sep + file)
#print feat_vec.shape
np.save(real_output_dir + os.sep + file.split('.')[0] + '.npy',feat_vec)
# if i < 20:
# np.save(real_output_dir_20 + os.sep + file.split('.')[0] + '.npy',feat_vec)
# i = i + 1
使用的时候更改路径就好了。这样得到的结果是npy的,如果想用python继续下面的步骤,就用这个方法。
还有一种提取到txt的方法:
1.py
import os,sys,cv2,skimage
import numpy as np
import scipy.io as sio
import cv2
#import matplotlib.pyplot as plt
caffe_root = '/home/library/caffe-master/'
model_root = '/media/new_disk/caffe/'
sys.path.append(caffe_root + 'python/')
import caffe
caffe.set_mode_gpu()
net = caffe.Net(model_root + 'models/ResNet-50/ResNet-50-deploy.prototxt',
model_root + 'models/ResNet-50/ResNet-50-model.caffemodel',
caffe.TEST)
# input preprocessing: 'data' is the name of the input blob == net.inputs[0]
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))
transformer.set_mean('data', np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy').mean(1).mean(1)) # mean pixel
transformer.set_raw_scale('data', 255) # the reference model operates on images in [0,255] range instead of [0,1]
transformer.set_channel_swap('data', (2,1,0)) # the reference model has channels in BGR order instead of RGB
net.blobs['data'].reshape(1,3,224,224)
def get_feature(pth):
net.blobs['data'].data[...] = transformer.preprocess('data', caffe.io.load_image(pth))
out = net.forward()
feature = net.blobs['pool5'].data[0].tolist()
return feature
if __name__ == '__main__':
print get_feature(sys.argv[1])
2.py
import os, sys
import cv2
import numpy as np
import get_feature
if __name__ == '__main__':
if len(sys.argv) != 3:
print 'Usage : python
exit()
input_dir = sys.argv[1]
output_dir = sys.argv[2]
for root, dirs, files in os.walk(input_dir):
real_output_dir = root.replace(input_dir, output_dir)
if not os.path.exists(real_output_dir):
os.mkdir(real_output_dir)
for file in files:
feat_vec = get_feature.get_feature(root + os.sep + file)
feat_str_vec = ['%f' % x[0][0] for x in feat_vec]
open(real_output_dir + os.sep + file.split('.')[0] + '.txt', 'w').write(' '.join(feat_str_vec))
两个py文件实现。。得到txt文件
我想用matlab来实现libsvm的分类,在得到txt特征后,将之转化为mat文件:
clear all;clc
MatPath = '/media/new_disk/test_feature_mat';
txtPath = '/media/new_disk/test_feature';
fid = fopen('/media/new_disk/feature_temp/TxtToMat_error.txt','a+');
txtContent = dir([txtPath '/*.txt']);
length(txtContent)
for t_i = 1:length(txtContent)
txt_feat = txtContent(t_i).name;
ind = strfind(txt_feat,'.');
txt_name = txt_feat(1:ind-1);
if exist([MatPath '/' txt_name '.mat'],'file')
delete([txtPath '/' txt_feat]);
continue;
end
idt_all = [];
feat=[];
try
idt_all = importdata([txtPath '/' txt_feat]);
feat = idt_all(:,41:end);
save([MatPath '/' txt_name '.mat'],'feat','-v7.3');
disp (['have finish ' num2str(t_i) ' th image'])
delete([txtPath '/' txt_feat]);
catch
fprintf(fid,'%s\n',txt_name);
end
end
fclose(fid);
现在又遇到了另一个问题:如何对所有的训练数据进行处理呢。想到的方法:将所有的特征合为一个矩阵mat,就可以使用libsvm简单实现;循环读取特征。那么我决定采用第一种。
由于自己对matlab不太熟悉,就很麻烦,代码如下:
length=[207,239,180,192,275,266,183,169,236,267,253,208,231,179,272,275,171,183,239,269,240,180,215,225,273,276,165,231,194,221,177,173,182,210,273,162,203,190,163,226];
l=[0,10,15,14,18,8,7,13,18,8,15,7,13,12,9,19,7,28,27,7,14,14,14,14,7,13,14,13,7,17,7,13,15,15,16,15,14,11,12,18,17];
method_pre=['applaudingblowing_bubblesbrushing_teethcleaning_the_floorclimbingcookingcutting_treescutting_vegetablesdrinkingfeeding_a_horsefishingfixing_a_bikefixing_a_cargardeningholding_an_umbrellajumpinglooking_through_a_microscopelooking_through_a_telescopephoningplaying_guitarplaying_violinpouring_liquidpushing_a_cartreadingriding_a_bikeriding_a_horserowing_a_boatrunningshooting_an_arrowsmokingtaking_photostexting_messagethrowing_frisbyusing_a_computerwalking_the_dogwashing_disheswatching_TVwaving_handswriting_on_a_boardwriting_on_a_book'];
a=[];
b=[];
x=0;
for k=1:40
a=[];
b=[];
x=x+l(k);
clear a;clear b;
for i=1:9
b=cell2mat(struct2cell(load(['/media/new_disk/resnet_feature_mat/' method_pre([x+1:x+l(k+1)]) '/' method_pre([x+1:x+l(k+1)]) '_00' num2str(i) '.mat'])));
if i==1
a=b;
else
a=[a;b];
end
end
for i=10:99
b=cell2mat(struct2cell(load(['/media/mcislab/new_disk/chenjialu/resnet_feature_mat/' method_pre([x+1:x+l(k+1)]) '/' method_pre([x+1:x+l(k+1)]) '_0' num2str(i) '.mat'])));
a=[a;b];
end
for i=100:length(k)
%fprintf('%d',length(k))
b=cell2mat(struct2cell(load(['/medianew_disk/resnet_feature_mat/' method_pre([x+1:x+l(k+1)]) '/' method_pre([x+1:x+l(k+1)]) '_' num2str(i) '.mat'])));
a=[a;b];
end
save(['/media/mcislab/new_disk/feature_temp/',num2str(k),'.mat'],'a');
end
得到每类特征矩阵,然后要生成label。
l=[207,239,180,192,275,266,183,169,236,267,253,208,231,179,272,275,171,183,239,269,240,180,215,225,273,276,165,231,194,221,177,173,182,210,273,162,203,190,163,226];
x=1;
clear b;
for k=1:40
for j=x:x+l(k)-1
b(j,1)=k;
end
x=x+l(k);
end
save('/media/new_disk/feature_temp/label.mat','b');
好了,现在数据和标签都准备好了,用libsvm进行训练吧,
T_label=[];
T_data=[];
test_data=[];
T_data=cell2mat(struct2cell(load('/media/new_disk/feature_temp/resnet_feature.mat')));
T_label=cell2mat(struct2cell(load('/medianew_disk/feature_temp/label.mat')));
test_data=cell2mat(struct2cell(load('/media/new_disk/test_feature_mat/applauding_265.mat')));
addpath('/media/new_disk/libsvm-3.18/matlab')
%model = svmtrain(T_label, T_data, '-c 1 -g 2');
[predict_label,accuracy,decision_values]= svmpredict(1,test_data,model);
那么最后就可以得到结果了。
值得一提的是,我遇到一个最大的问题就是,在合并特征为矩阵的时候,load得到的矩阵总是struct形式,自己很郁闷也很不解,那么用·cell2mat和struct2cell函数就能解决问题了。