<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maria Blanco Gonzalez-Mohino</title>
    <description>The latest articles on DEV Community by Maria Blanco Gonzalez-Mohino (@mariablancogonzalez).</description>
    <link>https://dev.to/mariablancogonzalez</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3495368%2F58da3da2-daa2-4d85-85b6-09391ef81a8f.jpeg</url>
      <title>DEV Community: Maria Blanco Gonzalez-Mohino</title>
      <link>https://dev.to/mariablancogonzalez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mariablancogonzalez"/>
    <language>en</language>
    <item>
      <title>QuPath Patch Extractor Pipeline</title>
      <dc:creator>Maria Blanco Gonzalez-Mohino</dc:creator>
      <pubDate>Thu, 11 Sep 2025 15:08:07 +0000</pubDate>
      <link>https://dev.to/mariablancogonzalez/qupath-stain-extractor-pipeline-3h0h</link>
      <guid>https://dev.to/mariablancogonzalez/qupath-stain-extractor-pipeline-3h0h</guid>
      <description>&lt;p&gt;This repository serves as documentation for the steps to follow with QuPath to extract tiles from a &lt;code&gt;.svs&lt;/code&gt; image (or any other format), ignoring background or less relevant areas.&lt;/p&gt;

&lt;p&gt;This repository documents the steps for using QuPath to extract tiles from .svs images (or other formats) while ignoring background or less relevant regions.&lt;/p&gt;

&lt;p&gt;👉 All references, configuration files, and scripts mentioned here can be found in my GitHub repository: &lt;a href="https://github.com/MariaBlancoGonzalez" rel="noopener noreferrer"&gt;MariaBlancoGonzalez&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Detection 🔎
&lt;/h2&gt;

&lt;p&gt;The first step is to create a project in QuPath and add all the images from which you want to extract patches. Choose any one to begin with – which image you pick doesn’t matter.&lt;/p&gt;

&lt;p&gt;Once everything is ready, create a pixel-level classifier via:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classify&lt;/strong&gt; &amp;gt; &lt;strong&gt;Pixel classification&lt;/strong&gt; &amp;gt; &lt;strong&gt;Create thresholder&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;A configuration window will appear:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6dong1rffpxdbee4k2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6dong1rffpxdbee4k2p.png" alt=" " width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resolution&lt;/strong&gt;: Defines the resolution of the image that is thresholded – and thus how ‘blocky’ the output is. This will almost always be lower than the full resolution of the image. In general, choose the lowest resolution that you consider ‘accurate enough’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Channel&lt;/strong&gt;: Defines the image channel that will be thresholded. This can also include channels that have been generated computationally, e.g. by color deconvolution, or averaging other channels. Use the Brightness/Contrast pane to visualize how some of these channels look; you want one that gives good contrast for what you want to detect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prefilter &amp;amp; Smoothing sigma&lt;/strong&gt;: Defines how the image is smoothed before thresholding. You probably want to choose ‘Gaussian’ and explore a few sigma values (e.g. 0–5).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Threshold&lt;/strong&gt;: Defines the threshold; pixels with values above and below can be treated differently. To get an idea of a suitable threshold, move the cursor over the image and check the values shown in the bottom right of the viewer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Above threshold&lt;/strong&gt;: Defines the classification of the objects created from pixel values above the threshold. You can leave it blank, or choose ‘Unclassified’ if you don’t want to detect anything above the threshold.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Below threshold&lt;/strong&gt;: Defines the classification of the objects created from pixel values below the threshold. You can leave it blank, or choose ‘Unclassified’ if you don’t want to detect anything below the threshold.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Region&lt;/strong&gt;: This doesn’t impact the results; rather, it controls how much of the image QuPath thresholds when you are adjusting settings and previewing the results. Rather than thresholding the whole image (especially if your resolution is high), you can restrict QuPath to threshold only around objects or annotations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;[!NOTE]&lt;br&gt;&lt;br&gt;
Information sourced from the official &lt;a href="https://qupath.readthedocs.io/en/stable/docs/tutorials/thresholding.html" rel="noopener noreferrer"&gt;QuPath documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A configuration file is included in the &lt;strong&gt;classifiers&lt;/strong&gt; folder, which was used for H&amp;amp;E and Ki67 detection in &lt;code&gt;.svs&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;Once the classifier is ready (our detector), save it and use it to create an object from the &lt;strong&gt;full image&lt;/strong&gt;. On the next screen, check the &lt;strong&gt;Split objects&lt;/strong&gt; option to generate annotations, as shown in the video below.&lt;/p&gt;

&lt;p&gt;After saving the classifier, go to the &lt;strong&gt;Workflow&lt;/strong&gt; tab and select &lt;strong&gt;Create split&lt;/strong&gt;. This generates a script you can reuse across all project images using the selected hyperparameters.&lt;/p&gt;

&lt;p&gt;At this stage, all detections for the images are complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extraction 🍀
&lt;/h2&gt;

&lt;p&gt;For tile extraction, the script &lt;strong&gt;tiles.groovy&lt;/strong&gt; is available in the &lt;strong&gt;scripts&lt;/strong&gt; folder. It was assembled using code from various forums.&lt;/p&gt;

&lt;p&gt;To run the scripts at the project level in QuPath:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Automate &amp;gt; DEPENDS scripts... &amp;gt; Detector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In script tab press 3 dots and &lt;strong&gt;Run for project&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Automate &amp;gt; DEPENDS scripts... &amp;gt; Tiles
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let the program do their thing and check the tiles folder in the project folder.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[!TIP]&lt;br&gt;
Line 38 of tiles.groovy is used to extract annotations at the corners. If unnecessary, set this option to false. You may also need a script to filter out valid tiles afterward.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Bibliography
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@article{bankhead2017qupath,
  title={QuPath: Open source software for digital pathology image analysis},
  author={Bankhead, Peter and Loughrey, Maurice B and Fern{\'a}ndez, Jos{\'e} A and Dombrowski, Yvonne and McArt, Darragh G and Dunne, Philip D and McQuaid, Stephen and Gray, Ronan T and Murray, Liam J and Coleman, Helen G and others},
  journal={Scientific reports},
  volume={7},
  number={1},
  pages={1--7},
  year={2017},
  publisher={Nature Publishing Group}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Acknowledgments
&lt;/h2&gt;

&lt;p&gt;Special thanks to &lt;a href="https://www.youtube.com/@LauraNicolasSaenz" rel="noopener noreferrer"&gt;@LauraNicolasSaenz&lt;/a&gt; for her amazing YouTube tutorial, which served as a key reference for the detection process:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=9TmEb3SxS1k" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F668aam3oho792k2wncpj.jpg" alt="Alt text" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>qupath</category>
      <category>programming</category>
      <category>groovy</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
