http://www.2cto.com/kf/201702/602665.html
(1)先把视频保存成图片
(2)再获取每张中人脸的坐标信息,保存到output.txt中
(3)利用output.txt生成XML文件
第一步:从视频中获得包括人脸的图像
/*
获取视频的每一帧,
如果检测到人脸,就把这一帧图像保存到本地
如果没检测到人脸,就不保存
*/
#include
#include
#include
#include
using namespace cv;//必须加入,否则无法检找到OPENCV的各个函数
using namespace std;
int img_num = 1;
char img_name[60] = { 0 };
string face_cascade_name = "haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;
string window_name = "人脸识别";
void detectAndDisplay(Mat frame){
std::vector faces;
//Mat frame_gray;
//cvtColor(frame, frame_gray, CV_BGR2GRAY);
//equalizeHist(frame_gray, frame_gray);
face_cascade.detectMultiScale(frame, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
//如果检测到人脸,就保存起来图片
sprintf(img_name, "%d.jpg", img_num);
img_num++;
if (faces.size() >= 0)
{
imwrite(img_name, frame);
}
for (int i = 0; i < faces.size(); i++)
{
rectangle(frame, faces[i], Scalar(255, 0, 0), 2, 8, 0);
}
imshow(window_name, frame);
}
int main(int argc, int* argv[])
{
VideoCapture cap("1.avi"); // open the default camera
if (!cap.isOpened()) // check if we succeeded
return -1;
if (!face_cascade.load(face_cascade_name)){
printf("[error] 无法加载级联分类器文件!\n");
return -1;
}
int nTick = 0;
for (;;)
{
if (!cap.isOpened())
{//等等摄像头打开
continue;
}
Mat frame;
nTick = getTickCount();
cap >> frame; // get a new frame from camera
if (frame.data == NULL)
{//等到捕获到数据
continue;
}
detectAndDisplay(frame);
if (waitKey(24) >= 0) break;
}
return 0;
}
第二步:获得output.txt文件
/*
依次读取本地中的图片,进行检测:
如果检测到人脸,就保存到output.txt文件中
如果检测不到人脸,就保存到no_face.txt文件中
*/
#include
#include
#include
#include
using namespace std;
using namespace cv;
void detectAndDisplay(Mat frame);
String face_cascade_name = "haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade; //定义人脸分类器
ofstream file_write("output.txt", ios::app); //output.txt文件
ofstream file_no_face("no_face.txt", ios::app); //output.txt文件
char buf[60] = { 0 }; //buf图片名称
char buf_path[60] = { 0 };
int i_img = 1; //遍历第i_img张图片
int main(void)
{
int count_img = 100000; //输入图片的总数量
//
for (; i_img <= count_img; i_img++)
{
sprintf(buf, "%d.jpg", i_img);//格式化输出sprintf函数
//sprintf(buf_path, "绝对路径\\%d.jpg", i_img);
sprintf(buf_path, "G:\\img\\%d.jpg", i_img);
Mat frame = imread(buf_path);
if (frame.data == NULL)
{
printf("处理完成 | 第%d张图片加载失败\n", i_img);
break;
}
if (!face_cascade.load(face_cascade_name))
{
printf("加载XML文件失败\n");
return -1;
};
detectAndDisplay(frame);
}
waitKey(0);
return 0;
}
void detectAndDisplay(Mat frame)
{
std::vector faces;
//检测人脸
face_cascade.detectMultiScale(frame, faces, 1.1, 3, CV_HAAR_DO_ROUGH_SEARCH, Size(70, 70), Size(100, 100));
char no_face_buf[60] = { 0 };
sprintf(no_face_buf, "%d.jpg\n", i_img);//格式化输出sprintf函数
if (faces.size() <= 0)
{
file_no_face << no_face_buf;
}
for (size_t j = 0; j < faces.size(); j++)
{
rectangle(frame, faces[j], Scalar(255, 0, 0), 2, 8, 0);
Mat faceROI = frame(faces[j]);
//写入本地
char name[60] = { 0 };
sprintf(name, "img%d_face_%d.jpg", i_img, j);
//imwrite(name, faceROI);
char output[100] = { 0 };
sprintf(output, "%s person %d %d %d %d\n", buf, faces[j].tl().x, faces[j].tl().y, faces[j].br().x, faces[j].br().y);
// 图片名字 类别 矩形的两个顶点坐标
printf("%s", output);
file_write << output;
}
imshow("正在处理", frame);
waitKey(300);
}
第三步:产生XML文件
将第2步得到的txt转成xml。格式如下:(注意folder字段)
<annotation>
<folder>logosfolder>
<filename>000001.jpgfilename>
<source>
<database>The logs Databasedatabase>
<annotation>The logs Databaseannotation>
<image>flickrimage>
<flickrid>0flickrid>
source>
<owner>
<flickrid>I do not knowflickrid>
<name>I do not knowname>
owner>
<size>
<width>293width>
<height>220height>
<depth>3depth>
size>
<segmented>0segmented>
<object>
<name>光头name>
<pose>Unspecifiedpose>
<truncated>0truncated>
<difficult>0difficult>
<bndbox>
<xmin>157xmin>
<ymin>24ymin>
<xmax>241xmax>
<ymax>99ymax>
bndbox>
object>
annotation>
【matlab代码】
下载工具链接:http://pan.baidu.com/s/1nuRMOsD 密码:2z4g
%%
%该代码可以做voc2007数据集中的xml文件,
%txt文件每行格式为:000002.jpg dog 44 28 132 121
%即每行由图片名、目标类型、包围框坐标组成,空格隔开
%如果一张图片有多个目标,则格式如下:(比如两个目标)
%000002.jpg dog 44 28 132 121
%000002.jpg car 50 27 140 110
%包围框坐标为左上角和右下角
%作者:小咸鱼_
%CSDN:http://blog.csdn.net/sinat_30071459
%%
clc;
clear;
%注意修改下面四个变量
imgpath='F:\face\';%图像存放文件夹
txtpath='F:\face\output.txt';%txt文件
xmlpath_new='F:\Annotations\';%修改后的xml保存文件夹
foldername='VOC2007';%xml的folder字段名
fidin=fopen(txtpath,'r');
lastname='begin';
while ~feof(fidin)
tline=fgetl(fidin);
str = regexp(tline, ' ','split');
filepath=[imgpath,str{1}];
img=imread(filepath);
[h,w,d]=size(img);
imshow(img);
rectangle('Position',[str2double(str{3}),str2double(str{4}),str2double(str{5})-str2double(str{3}),str2double(str{6})-str2double(str{4})],'LineWidth',4,'EdgeColor','r');
pause(0.1);
if strcmp(str{1},lastname)%如果文件名相等,只需增加object
object_node=Createnode.createElement('object');
Root.appendChild(object_node);
node=Createnode.createElement('name');
node.appendChild(Createnode.createTextNode(sprintf('%s',str{2})));
object_node.appendChild(node);
node=Createnode.createElement('pose');
node.appendChild(Createnode.createTextNode(sprintf('%s','Unspecified')));
object_node.appendChild(node);
node=Createnode.createElement('truncated');
node.appendChild(Createnode.createTextNode(sprintf('%s','0')));
object_node.appendChild(node);
node=Createnode.createElement('difficult');
node.appendChild(Createnode.createTextNode(sprintf('%s','0')));
object_node.appendChild(node);
bndbox_node=Createnode.createElement('bndbox');
object_node.appendChild(bndbox_node);
node=Createnode.createElement('xmin');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{3}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('ymin');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{4}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('xmax');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{5}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('ymax');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{6}))));
bndbox_node.appendChild(node);
else %如果文件名不等,则需要新建xml
copyfile(filepath, 'JPEGImages');
%先保存上一次的xml
if exist('Createnode','var')
tempname=lastname;
tempname=strrep(tempname,'.jpg','.xml');
xmlwrite(tempname,Createnode);
end
Createnode=com.mathworks.xml.XMLUtils.createDocument('annotation');
Root=Createnode.getDocumentElement;%根节点
node=Createnode.createElement('folder');
node.appendChild(Createnode.createTextNode(sprintf('%s',foldername)));
Root.appendChild(node);
node=Createnode.createElement('filename');
node.appendChild(Createnode.createTextNode(sprintf('%s',str{1})));
Root.appendChild(node);
source_node=Createnode.createElement('source');
Root.appendChild(source_node);
node=Createnode.createElement('database');
node.appendChild(Createnode.createTextNode(sprintf('My Database')));
source_node.appendChild(node);
node=Createnode.createElement('annotation');
node.appendChild(Createnode.createTextNode(sprintf('VOC2007')));
source_node.appendChild(node);
node=Createnode.createElement('image');
node.appendChild(Createnode.createTextNode(sprintf('flickr')));
source_node.appendChild(node);
node=Createnode.createElement('flickrid');
node.appendChild(Createnode.createTextNode(sprintf('NULL')));
source_node.appendChild(node);
owner_node=Createnode.createElement('owner');
Root.appendChild(owner_node);
node=Createnode.createElement('flickrid');
node.appendChild(Createnode.createTextNode(sprintf('NULL')));
owner_node.appendChild(node);
node=Createnode.createElement('name');
node.appendChild(Createnode.createTextNode(sprintf('xiaoxianyu')));
owner_node.appendChild(node);
size_node=Createnode.createElement('size');
Root.appendChild(size_node);
node=Createnode.createElement('width');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(w))));
size_node.appendChild(node);
node=Createnode.createElement('height');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(h))));
size_node.appendChild(node);
node=Createnode.createElement('depth');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(d))));
size_node.appendChild(node);
node=Createnode.createElement('segmented');
node.appendChild(Createnode.createTextNode(sprintf('%s','0')));
Root.appendChild(node);
object_node=Createnode.createElement('object');
Root.appendChild(object_node);
node=Createnode.createElement('name');
node.appendChild(Createnode.createTextNode(sprintf('%s',str{2})));
object_node.appendChild(node);
node=Createnode.createElement('pose');
node.appendChild(Createnode.createTextNode(sprintf('%s','Unspecified')));
object_node.appendChild(node);
node=Createnode.createElement('truncated');
node.appendChild(Createnode.createTextNode(sprintf('%s','0')));
object_node.appendChild(node);
node=Createnode.createElement('difficult');
node.appendChild(Createnode.createTextNode(sprintf('%s','0')));
object_node.appendChild(node);
bndbox_node=Createnode.createElement('bndbox');
object_node.appendChild(bndbox_node);
node=Createnode.createElement('xmin');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{3}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('ymin');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{4}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('xmax');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{5}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('ymax');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{6}))));
bndbox_node.appendChild(node);
lastname=str{1};
end
%处理最后一行
if feof(fidin)
tempname=lastname;
tempname=strrep(tempname,'.jpg','.xml');
xmlwrite(tempname,Createnode);
end
end
fclose(fidin);
file=dir(pwd);
for i=1:length(file)
if length(file(i).name)>=4 && strcmp(file(i).name(end-3:end),'.xml')
fold=fopen(file(i).name,'r');
fnew=fopen([xmlpath_new file(i).name],'w');
line=1;
while ~feof(fold)
tline=fgetl(fold);
if line==1
line=2;
continue;
end
expression = ' ';
replace=char(9);
newStr=regexprep(tline,expression,replace);
fprintf(fnew,'%s\n',newStr);
end
fprintf('已处理%s\n',file(i).name);
fclose(fold);
fclose(fnew);
delete(file(i).name);
end
end
【python代码】
/*
把上一步得到的txt文档转换为XML文件,python代码如下,我的需要训练识别的物体只有一个,如果要识别多个目标,那需要略微修改一下如下代码。
*/
#encoding=utf-8
import sys
import os
import codecs
import cv2
root = r'F:\dataset\xml'
fp = open('F:\dataset\pos-all.txt')
fp2 = open('train.txt', 'w')
uavinfo = fp.readlines()
for i in range(len(uavinfo)):
line = uavinfo[i]
line = line.strip().split('\t')
img = cv2.imread(line[0])
sp = img.shape
height = sp[0]
width = sp[1]
depth = sp[2]
info1 = line[0].split('\\')[-1]
info2 = info1.split('.')[0]
l_pos1 = line[1]
l_pos2 = line[2]
r_pos1 = line[3]
r_pos2 = line[4]
fp2.writelines(info2 + '\n')
with codecs.open(root +r'\\'+ info2 + '.xml', 'w', 'utf-8') as xml:
xml.write('\n')
xml.write('\t' + 'UAV_data' + '\n')
xml.write('\t' + info1 + '\n')
xml.write('\t)
xml.write('\t\tThe UAV autolanding \n')
xml.write('\t\tUAV AutoLanding\n')
xml.write('\t\tflickr\n')
xml.write('\t\tNULL \n')
xml.write('\t\n')
xml.write('\t\n' )
xml.write('\t\tNULL \n')
xml.write('\t\tXuSenhai \n')
xml.write('\t\n')
xml.write('\t\n' )
xml.write('\t\t' + str(width) + '\n')
xml.write('\t\t' + str(height) + '\n')
xml.write('\t\t' + str(depth) + '\n')
xml.write('\t\n')
xml.write('\t\t0 \n')
xml.write('\t)
xml.write('\t\tuav \n')
xml.write('\t\tUnspecified \n')
xml.write('\t\t0 \n')
xml.write('\t\t0 \n')
xml.write('\t\t\n' )
xml.write('\t\t\t' + l_pos1 + '\n')
xml.write('\t\t\t' + l_pos2 + '\n')
xml.write('\t\t\t' + r_pos1 + '\n')
xml.write('\t\t\t' + r_pos2 + '\n')
xml.write('\t\t\n')
xml.write('\t\n')
xml.write('')
fp2.close()
第四步:数据集分割–matlab代码
/*
在实际训练过程中,需要四个文件,分别为test.txt是测试集,train.txt是训练集,val.txt是验证集,trainval.txt是训练和验证集。每个文件为对于图片的名字。在VOC2007中,trainval大概是整个数据集的50%,test也大概是整个数据集的50%;train大概是trainval的50%,val大概是trainval的50%。可参考以下代码:
*/
%%
%该代码根据已生成的xml,制作VOC2007数据集中的trainval.txt;train.txt;test.txt和val.txt
%trainval占总数据集的50%,test占总数据集的50%;train占trainval的50%,val占trainval的50%;
%上面所占百分比可根据自己的数据集修改,如果数据集比较少,test和val可少一些
%%
%注意修改下面四个值
xmlfilepath='E:\Annotations';
txtsavepath='E:\ImageSets\Main\';
trainval_percent=0.5;%trainval占整个数据集的百分比,剩下部分就是test所占百分比
train_percent=0.5;%train占trainval的百分比,剩下部分就是val所占百分比
%%
xmlfile=dir(xmlfilepath);
numOfxml=length(xmlfile)-2;%减去.和.. 总的数据集大小
trainval=sort(randperm(numOfxml,floor(numOfxml*trainval_percent)));
test=sort(setdiff(1:numOfxml,trainval));
trainvalsize=length(trainval);%trainval的大小
train=sort(trainval(randperm(trainvalsize,floor(trainvalsize*train_percent))));
val=sort(setdiff(trainval,train));
ftrainval=fopen([txtsavepath 'trainval.txt'],'w');
ftest=fopen([txtsavepath 'test.txt'],'w');
ftrain=fopen([txtsavepath 'train.txt'],'w');
fval=fopen([txtsavepath 'val.txt'],'w');
for i=1:numOfxml
if ismember(i,trainval)
fprintf(ftrainval,'%s\n',xmlfile(i+2).name(1:end-4));
if ismember(i,train)
fprintf(ftrain,'%s\n',xmlfile(i+2).name(1:end-4));
else
fprintf(fval,'%s\n',xmlfile(i+2).name(1:end-4));
end
else
fprintf(ftest,'%s\n',xmlfile(i+2).name(1:end-4));
end
end
fclose(ftrainval);
fclose(ftrain);
fclose(fval);
fclose(ftest);
第五步:将得到的文件放置正确路径
1. 将训练图片放置于
faster-rcnn/data/VOCdevkit2007/VOC2007/JPEGImages 中
2. 将得到的xml文件放置于
faster-rcnn/data/VOCdevkit2007/VOC2007/Annotations 中
3. 将得到的test.txt,train.txt,val.txt,trainval.txt 放置于
faster-rcnn/data/VOCdevkit2007/VOC2007/Annotations/ImageSets/Main