matlab2017a版本自带的trainingImageLabel app标记工具或者2017b及其以后版本的imageLabeler app(2017a的兼容升级版,还可以对像素进行标注),在工具标记完后“导出ROIs”输出是matlab内置的table类型或者struct类型数据(17b是table或者groundTruth类型),为统一起见,导出选择table格式!
一、图像标注--->VOC-XML标准格式
只需下面两小步即可!!!
1.下载这个通用的xml/matlab struct互转工具
下载链接http://cn.mathworks.com/matlabcentral/fileexchange/12907-xml-io-tools,解压并添加到你的工作路径下即可使用(或addpath)。目的是要用到这个工具里面的xml_write函数。
2.转换VOC-xml格式
matlab命令行敲入trainingImageLabeler进入APP(或者2017b及以后版本是imageLabeler)打开你自己的图像文件进行交互式标注。这里给出截图:
标注完成后,点击上图工具栏中靠右上角“Export ROIs”导出到工作空间中,类型选择table,变量名自己取,这里我取名mylabel,双击mylabel可以清楚直观查看标记内容,每四个数字组成一个ROI,即[x,y,width,heigth],没有标注的ROI就是空[],如下图所示:
接下来就是正式把mylabel转换为xml格式了,VOC-xml格式的文件是每个图像对应一个xml文件,我写了个转换函数如下,保存的批量xml文件自动保存到你选择的文件夹内!(比如我的保存在文件夹xmlSaveFolder内,最好跟图片文件在同一文件夹)。
- function matlab_to_VOCxml(mylabel)
- % 功能:把trainingImageLabel APP数据格式(table类型)转为VOC格式的xml
- % 输入: mylabel为导出到工作空间的标注文件
- % 输出: 自动生成xmlSaveFolder文件存储,每张图对应一个
- %
- % Example:
- % matlab_to_VOCxml(mylabel)
- %
- %%
- if nargin<1 || ~istable(mylabel)
- error('请导入trainingImageLabel APP文件的table数据!');
- end
- folder_name = uigetdir('','请选择保存VOC-xml的文件夹!');
- if ~folder_name
- warndlg('当前并没选择任何文件!','警告')
- return;
- end
- %%
- tableLabel = mylabel; %这里是自己的标注好的table类型数据
- variableNames = tableLabel.Properties.VariableNames; %cell类型
- numSamples = size(mylabel,1);
- numVariables = size(variableNames,2);
- h = waitbar(0,'Please wait...');
- steps = numSamples;
- %%
- for i = 1:numSamples
- rowTable = tableLabel(i,:);
- imageFullPathName = rowTable.(variableNames{1});%cell
- path = char(imageFullPathName);
- [pathstr,name,ext] = fileparts(path);
- index =strfind(pathstr,'\');
- annotation.folder = pathstr(index(end)+1:end);
- annotation.filename = [name,ext];
- annotation.path = path;
- annotation.source.database = 'Unknow';
- image = imread(annotation.path);
- annotation.size.width = size(image,2);
- annotation.size.height = size(image,1);
- annotation.size.depth = size(image,3);
- annotation.segmented = 0;
- objectnum = 0;
- for j = 2:numVariables %对于每个变量
- ROI_matrix = rowTable.(variableNames{j} );%cell
- if iscell(ROI_matrix)
- ROI_matrix = cell2mat(ROI_matrix);
- end
- numROIS = size(ROI_matrix,1);
- for ii = 1: numROIS % 对于每个ROI
- objectnum= objectnum+1;
- annotation.object(objectnum).name = variableNames{1,j};
- annotation.object(objectnum).pose = 'Unspecified';
- annotation.object(objectnum).truncated = 0;
- annotation.object(objectnum).difficult= 0;
- annotation.object(objectnum).bndbox.xmin = ROI_matrix(ii,1);
- annotation.object(objectnum).bndbox.ymin = ROI_matrix(ii,2);
- annotation.object(objectnum).bndbox.xmax = ROI_matrix(ii,1)+ROI_matrix(ii,3);
- annotation.object(objectnum).bndbox.ymax = ROI_matrix(ii,2)+ROI_matrix(ii,4);
- end
- end
- filename = fullfile(folder_name,[name,'_temp.xml']);
- xml_write(filename,annotation);
- %% 整理
- fid_r = fopen(filename,'r');
- fid_w = fopen(fullfile(folder_name,[name,'.xml']),'w');
- fgetl(fid_r);
- flagOffset = 0;flagObjects = 0;
- while(~feof(fid_r))
- tline = fgetl(fid_r);
- if contains(tline,'<object>')||contains(tline,'</object>')
- t_next_line = fgetl(fid_r);
- if contains(t_next_line,'<item>')
- flagOffset = mod(flagOffset+1,2);
- flagObjects = 1;
- newStr = strrep(t_next_line,'item','object');
- fprintf(fid_w,'%s\r\n',newStr(4:end));
- continue;
- end
- if ~flagObjects
- fprintf(fid_w,'%s\r\n',tline);
- fprintf(fid_w,'%s\r\n',t_next_line);
- else % 多个objects
- fprintf(fid_w,'%s\r\n',t_next_line);
- end
- elseif contains(tline,'<item>')||contains(tline,'</item>')
- newStr = strrep(tline,'item','object');
- fprintf(fid_w,'%s\r\n',newStr(4:end));
- elseif flagOffset
- fprintf(fid_w,'%s\r\n',tline(4:end));
- else
- fprintf(fid_w,'%s\r\n',tline);% 写objects前面若干行
- end
- end
- fclose(fid_r);
- fclose(fid_w);
- delete(filename);
- clear annotation;
- waitbar(i / steps);
- end
- close(h);