Working with Aperio SVS files in Matlab – Loading Sub-Sections

In the previous tutorial we discussed how to load different levels of the image pyramid for Aperio SVS images in Matlab and how they corresponded.

In this tutorial we will extend upon that in 2 critical ways. First, we’d like to be able to load only small sub-sections from images (easy) and then extend upon that so we can identify regions at a low-magnification that we’d like to load the corresponding high-magnification version (harder).

Loading sub-images

Loading sub-images in Matlab is very straight forward:

  1. io_roi=imread(filename,'Index',index,'PixelRegion',{Rows,Cols});

From the Matlab documentation for imread:

Cell array, {Rows, Cols}, specifying the boundaries of the region. Rows and Cols must be either two- or three-element vectors. If you specify two elements, the values denote the 1-based indices [start stop]. If you specify three elements, the values denote the 1-based indices [start increment stop], to allow image downsampling.

Using this definition, we define Rows and Cols as such:

  1. Rows=[start_row start_row+height];
  2. Cols=[start_col start_col+width];

This is useful because if we would like to load only a 1,000 x 1,000 sub image from a 100k x 100k image, we can do so without having to load the entire image (which may or may not fit into memory)!

Identifying Specific Sub-Images

The normal produce to identify ROIs is:

  1. Identify ROI using a lower magnification
  2. Load that location at higher magnification

So is there a way that we can do this, inside of Matlab, in an easy way.

Of course 🙂 I’ve written a script which I’ll run through piece by piece.

First we’ll have the user select an image via a UI:

  1. [filename, pathname] = uigetfile( ...
  2.     {'*.tif*;*.png;*.jpg;*.svs;*.scn', 'All Image Files (*.tif*, *.png, *.jpg, *.svs, *.scn)';
  3.     '*.tif*','TIFF images (*.tif, *.tiff)'; ...
  4.     '*.png','PNG images (*.png)'; ...
  5.     '*.jpg','JPG images (*.jpg)'; ...
  6.     '*.svs','SVS images (*.svs)'; ...
  7.     '*.scn','SCN images (*.scn)'; ...
  8.     '*.*',  'All Files (*.*)'}, ...
  9.     'Pick Image');

Afterwards, we’ll load and display some of the pyramid information, allowing the user to select which layer they would like to use for their ROI discovery:

  1. I1info=imfinfo([pathname filename]);
  2. for i=1:numel(I1info),pageinfo1{i}=['Page ' num2str(i) ': ' num2str(I1info(i).Height) ' x ' num2str(I1info(i).Width)]; end
  3. fprintf('done.\n');
  4. fname=[pathname filename];
  5. if numel(I1info)>1,
  6.     [s,v]=listdlg('Name','Choose Level','PromptString','Select a page for Roi Discovery:','SelectionMode','single','ListSize',[170 120],'ListString',pageinfo1); drawnow;
  7.     if ~v, guidata(hObject, handles); return; end
  8.     fprintf('Reading page %g of image 1... ',s);
  9.     io=imread(fname,s);
  10.     fprintf('done.\n');
  11. else
  12.     fprintf('Image doesnt have any pages!\n');
  13. end


select_level_for_roi
 

We can see that every layer is available as an option, although we discussed in the previous post they all may not be useful for the ROI discovery purpose (such as the image label). For this example, we have selected layer 4 and loaded the associated 5k x 5k image.

Afterwards, the script displays the image and awaits the user to select a ROI using the imrect command as shown here:

  1. figure,imshow(io)
  2. h=imrect;
  3. roi = wait(h);

 

selected_roi
We can see that the user’s selected region appears in Blue. If we look at the roi varaiable, we can see the necessary coordinates:


roi_points
Its important to note that they are of the form [xmin ymin width height].

From there we have the user select which level they would like to load the sub-image from:

select_level_for_extract
In this case, we’ll select the highest level, Page 1.

Now comes the “tricky” part. We compute the ratio between the low magnification and the high magnification:

  1. hratio=I1info(s2).Height/I1info(s).Height;
  2. wratio=I1info(s2).Width/I1info(s).Width;

With that information, we can scale the ROI up so that the points are now relative to the higher-magnification:

  1. roi(2:2:4)=roi(2:2:4)*hratio;
  2. roi(1:2:3)=roi(1:2:3)*wratio;

And lately we create the Rows and Cols variable:

  1. Rows=[roi(2) roi(2)+roi(4)];
  2. Cols=[roi(1) roi(1)+roi(3)];

Which get fed into the ROI loading command, using imread:

  1. io_roi=imread(fname,'Index',s2,'PixelRegion',{Rows,Cols});

From there we can view the sub-image which was loaded io_roi, and see that it does indeed correspond with the highlighted region in the lower-magnification image:

sub_image
 

This is of course an example and some additional concerns need to be taken into account. For example, if a “very large” (as defined by computer memory) region is selected on the low magnification image, when it is scaled to the high magnification and the loading takes place, it is possible that the image may exceed available memory. This is to say, one needs to pick small enough regions so that the high-magnification versions are tractable.

Full source available here.

In the next tutorial, we’ll discuss how to make binary masks from the xml annotation file created by ImageScope.

9 thoughts on “Working with Aperio SVS files in Matlab – Loading Sub-Sections”

  1. Andrew,
    this is a great way to tackle the problem of big SVS files. The issue I’m having though is that when I run your code, the zoomed image (the subsection I’ve picked out from the first image) comes up black in a SVS from my lab. I’m going to do more testing, but I think it might be because of a file format issue. Specifically, I think that the larger sizes of images might have JPEG2000 compression, but Matlab thinks it is a TIFF – and therefore I get a black image. I’m not sure what else could be the issue. Your SVS works great, but it looks like your files are JPEG not JPEG2000

    Note with my SVS that uses JPEG2000 compression, that the script works if I choose the Page 2 image in both listboxes (this Page seems to be a different format than the others). I’m using a scaled down SVS file, so even if I choose the Page 3 image off the bat, ,it is only 1955 x 3134 so should fit in memory, but it shows up black. Making me think it is a file format/compression issue.

    Thoughts?

    1. Hi James,

      You’ve hit it right on the head. Older svs files are compressed using jpeg2000, and matlab can’t currently read them through the imread function : ( The newer ones don’t seem to be an issue. Anyway, I opened a support case with mathworks: “Technical Support Case #01141579 regarding ‘Error when loading SVS files using IMread’”. Their answer was to use lower level functions, which is a waste of time. In the end, for those types of svs files, I use openslide with matlab wrappers. The concept is exactly the same, though the implementation is a bit different as openslide looks at the image pyramid in a different order and some of the parameters are different, but I can report that it works successfully. Next time I’m using it I’ll be sure to document and make a blog post, but if you have any issues in the meantime, feel free to drop me a line.

      Cheers,
      Andrew

      1. Hi,

        I am new to working with digital histology slides. One option appears to be to ‘extract region’ in imagescope. Save the extracted region .SVS as output JPEG rather than JPEG2000. The extracted region then works with the above tutorial.

        This website is a very good introduction. Cheers!

        Nick

        1. i would be very careful taking that approach. i do not know if “extract region” performs any processing on the images before they are saved. many image programs automatically “correct” images for lighting/contrast/color profile when loading. if you use “corrected” images in downstream applications, especially to train classifiers for use with non-correct images, your results may appear erratic. i’d double to check to make sure what you think you’re getting is actually what you’re getting

  2. This is wonderful code – I process large quantities of scanned .SVS and .SCN images using vendor applications, and had never found a way to read those images directly into MatLab. Leica should offer you a ridiculous amount of money to keep this code private.

  3. please i have a big problem in reading svs files. i donot know why the first page in SVS is read by black image where the second page may be read normal.

    1. See the comment above from james. If matlab is loading a black image, you’re only option is to use openslide unfortunately :-\

Leave a Reply

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