Matlab: VOC中的XML标注文件制作及其交互使用

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)打开你自己的图像文件进行交互式标注。这里给出截图:

Matlab: VOC中的XML标注文件制作及其交互使用

标注完成后,点击上图工具栏中靠右上角“Export ROIs”导出到工作空间中,类型选择table,变量名自己取,这里我取名mylabel,双击mylabel可以清楚直观查看标记内容,每四个数字组成一个ROI,即[x,y,width,heigth],没有标注的ROI就是空[],如下图所示:

Matlab: VOC中的XML标注文件制作及其交互使用

接下来就是正式把mylabel转换为xml格式了,VOC-xml格式的文件是每个图像对应一个xml文件,我写了个转换函数如下,保存的批量xml文件自动保存到你选择的文件夹内!(比如我的保存在文件夹xmlSaveFolder内,最好跟图片文件在同一文件夹)。

  1. function matlab_to_VOCxml(mylabel)  
  2. % 功能:把trainingImageLabel APP数据格式(table类型)转为VOC格式的xml  
  3. % 输入: mylabel为导出到工作空间的标注文件  
  4. % 输出: 自动生成xmlSaveFolder文件存储,每张图对应一个  
  5. %  
  6. % Example:  
  7. %          matlab_to_VOCxml(mylabel)  
  8. %  
  9. %%  
  10. if nargin<1 || ~istable(mylabel)  
  11.     error('请导入trainingImageLabel APP文件的table数据!');  
  12. end  
  13. folder_name = uigetdir('','请选择保存VOC-xml的文件夹!');  
  14. if ~folder_name  
  15.     warndlg('当前并没选择任何文件!','警告')  
  16.     return;  
  17. end  
  18.   
  19. %%  
  20. tableLabel = mylabel; %这里是自己的标注好的table类型数据  
  21. variableNames = tableLabel.Properties.VariableNames; %cell类型  
  22. numSamples = size(mylabel,1);  
  23. numVariables = size(variableNames,2);  
  24. h = waitbar(0,'Please wait...');  
  25. steps = numSamples;  
  26. %%  
  27. for i = 1:numSamples  
  28.     rowTable = tableLabel(i,:);  
  29.     imageFullPathName = rowTable.(variableNames{1});%cell  
  30.     path = char(imageFullPathName);  
  31.     [pathstr,name,ext] = fileparts(path);  
  32.     index =strfind(pathstr,'\');  
  33.       
  34.     annotation.folder = pathstr(index(end)+1:end);  
  35.     annotation.filename = [name,ext];  
  36.     annotation.path = path;  
  37.     annotation.source.database = 'Unknow';  
  38.     image = imread(annotation.path);  
  39.       
  40.     annotation.size.width = size(image,2);  
  41.     annotation.size.height = size(image,1);  
  42.     annotation.size.depth = size(image,3);  
  43.     annotation.segmented = 0;  
  44.       
  45.     objectnum = 0;  
  46.     for j = 2:numVariables %对于每个变量  
  47.         ROI_matrix = rowTable.(variableNames{j} );%cell  
  48.         if iscell(ROI_matrix)  
  49.              ROI_matrix = cell2mat(ROI_matrix);  
  50.         end  
  51.         numROIS = size(ROI_matrix,1);  
  52.         for ii = 1: numROIS % 对于每个ROI  
  53.             objectnum= objectnum+1;  
  54.             annotation.object(objectnum).name = variableNames{1,j};  
  55.             annotation.object(objectnum).pose = 'Unspecified';  
  56.             annotation.object(objectnum).truncated = 0;  
  57.             annotation.object(objectnum).difficult= 0;  
  58.             annotation.object(objectnum).bndbox.xmin = ROI_matrix(ii,1);  
  59.             annotation.object(objectnum).bndbox.ymin = ROI_matrix(ii,2);  
  60.             annotation.object(objectnum).bndbox.xmax = ROI_matrix(ii,1)+ROI_matrix(ii,3);  
  61.             annotation.object(objectnum).bndbox.ymax = ROI_matrix(ii,2)+ROI_matrix(ii,4);  
  62.         end  
  63.     end  
  64.       
  65.     filename = fullfile(folder_name,[name,'_temp.xml']);  
  66.     xml_write(filename,annotation);  
  67.         
  68.      %% 整理  
  69.      fid_r = fopen(filename,'r');  
  70.      fid_w = fopen(fullfile(folder_name,[name,'.xml']),'w');  
  71.      fgetl(fid_r);  
  72.      flagOffset = 0;flagObjects = 0;  
  73.      while(~feof(fid_r))  
  74.          tline = fgetl(fid_r);  
  75.          if contains(tline,'<object>')||contains(tline,'</object>')   
  76.              t_next_line = fgetl(fid_r);  
  77.              if contains(t_next_line,'<item>')  
  78.                  flagOffset = mod(flagOffset+1,2);  
  79.                  flagObjects = 1;  
  80.                  newStr = strrep(t_next_line,'item','object');  
  81.                  fprintf(fid_w,'%s\r\n',newStr(4:end));  
  82.                  continue;  
  83.              end  
  84.              if ~flagObjects   
  85.                  fprintf(fid_w,'%s\r\n',tline);  
  86.                  fprintf(fid_w,'%s\r\n',t_next_line);  
  87.              else % 多个objects  
  88.                  fprintf(fid_w,'%s\r\n',t_next_line);  
  89.              end  
  90.          elseif contains(tline,'<item>')||contains(tline,'</item>')  
  91.              newStr = strrep(tline,'item','object');  
  92.              fprintf(fid_w,'%s\r\n',newStr(4:end));  
  93.          elseif flagOffset  
  94.              fprintf(fid_w,'%s\r\n',tline(4:end));  
  95.          else  
  96.              fprintf(fid_w,'%s\r\n',tline);% 写objects前面若干行  
  97.          end  
  98.      end  
  99.      fclose(fid_r);  
  100.      fclose(fid_w);  
  101.      delete(filename);      
  102.      clear annotation;  
  103.      waitbar(i / steps);  
  104. end  
  105. close(h);