Created Bisque XML from Matlab Binary Masks

Once we have images uploaded to Bisque, we might want to be able to overlay annotations on top of them so that users can interact with them. This post quickly goes through the conversation of a binary mask, in matlab, into an XML which can later be imported into Bisque.

This post is rather short because it is very similar to the process of exporting binary masks to ventana/image viewer.

In this case, we’ve done some tubule segmentation using deep learning. The output filenames all contain “class” which is a binary mask such as this one:

First we get a list of all of the files that we’ll be uploading. We also create a file with the names of the original files for later usage. We can use that file as an input file to our uploading script, so that we only upload the files which are necessary to match the annotations (as opposed to a whole directory, for example)

  1. files=dir('*class*.png');
  2. fall_files=fopen('tif_files_needed.txt','w');

Next we iterate through the files, and create the original file name by replacing the latter part of the filename with the correct extension:

  1. for fi=1:length(files)
  2. fname=files(fi).name;
  3. original_file_name=strrep(fname,'_class.png','.tif');

By design, the binary mask is half the size of the original image, so we upscale it as both the binary mask and the original file need to be of the same size for the annotation coordinate systems to overlay correctly.

  1. iob=imresize(imread(fname),2)>0;

We initialize the xml which needs to be sent. The root tag is a <gobject> and inside we can fill it with many polygons, each of which contain an ordered list of verticies.

  1. xml_to_send='<gobject>';

We want to do each object of the binary individually, so we label it and iterate through all of the object numbers

  1. [iol,num]=bwlabel(iob);
  2. for zz=1:num

We’re only interested in the points on the perimeter, so we use bwperim to create a binary perimeter image

  1. p=bwperim(iol==zz);

Afterwards, we want to trace a path, in order, around the perimeter and get those x,y coordinates. Matlab also has inbuilt functions for this:

  1. [r,c]=find(p);
  2. C=bwtraceboundary(p,[r(1) c(1)],'N');

Now that we have the path, we create the polygon itself by starting the polygon tag, then iterating through each vertex adding the appropriate xml:

  1. xml_to_send=strcat(xml_to_send,'<polygon>');
  2. for yy=1:length(C)
  3.       xml_to_send=strcat(xml_to_send,sprintf('<vertex index="%d" t="0.0" x="%0.2f" y="%0.2f" z="0.0"/>\n',yy-1,C(yy,2),C(yy,1)));
  4. end
  5. xml_to_send=strcat(xml_to_send,'</polygon>');
  6. end

Once all of our objects are done, we close the gobject and write the xml to file

  1. xml_to_send=strcat(xml_to_send,'</gobject>');
  3. fid=fopen(strrep(original_file_name,'tif','xml'),'w');
  4. fwrite(fid,xml_to_send);
  5. fclose(fid);

Finally, we add the original filename to the list of files which are needed on the server:

  1. fprintf(fall_files,'%s\n',original_file_name);
  2. end
  4. fclose(fall_files);

Thats all there is to it!

Next we show how to import these xml files into bisque

Full source available here.

Leave a Reply

Your email address will not be published. Required fields are marked *