Adapting Cellpose ROI import plugin for batch processing

Hi there,

I’m looking for advice/help with modifying the ‘imagej_roi_converter’ plugin provided by Cellpose to use it for batch processing. (I’ve scoured the forum for help but haven’t found anything similar``)
Right now when you open the plugin, it requires an open image and asks for input in the form of a .txt file containing coordinates to outlines of segmented features. These are then listen in ROI manager. My data requires me to measure area of the outlines and save the list as txt file. Because of multiple inputs that have to be done manually as well as saving the measurements it is not possible to run via the ‘batch’ command in processing menu.

This is the list of actions I have to take for each image before I can run the script again for another one.

open("C:/Users/annac/Desktop/Experiment 50.1_sub/WR_sub/WR1-substack-0009.tif");
selectWindow("WR1-substack-0009.tif");
run("imagej roi converter");
roiManager("Measure");
saveAs("Results", "C:/Users/annac/Desktop/Experiment 50.1_sub/WR_sub/WR1-substack-0009_cp_measurement.csv");
roiManager("Delete");
close();

I was wondering if there is a way to make this run automatically for each folder? The files have sequential names: for example the name of the image is WR1-substack-0001.tif and the name of the outline file would be WR1-substack-0001_cp_outlines.txt. And I would like the output file of measured area to be WR1-substack-0001_cp_measurement.csv.

I’d be grateful for any help with this!
(Also I’m a complete newbie so I apologise if this is a trivial issue).

Thanks

Sorry that this is slightly off topic, but in case it helps, I am able to batch import Cellpose results as detection objects into a QuPath project; those objects can then be used to make measurements, export measurements, generate summary measurements, visualizations based on measurements, etc.
I tried integrating things a bit more but for the moment I have to batch CellPose, and then batch import (the png file in my case, not the text).

And an example image of what it looks like, with cells color coded be circularity.

Thanks for this, I’m not familiar with QuPath but will see if this would work for me.

1 Like

I managed to make the QuPath script to work and I am now trying to export the measurements but here is where the issue lies.

Here is the script that I am using (adapted from QuPath website):

import qupath.lib.gui.tools.MeasurementExporter
import qupath.lib.objects.PathCellObject
import qupath.lib.objects.PathObjects

// Get the list of all images in the current project
def project = getProject()
def imagesToExport = project.getImageList()

// Separate each measurement value in the output file with a tab ("\t")
def separator = "\t"

// Choose the columns that will be included in the export
// Note: if 'columnsToInclude' is empty, all columns will be included
def columnsToInclude = new String[]{}    

// Choose the type of objects that the export will process
// Other possibilities include:
//    1. PathAnnotationObject
//    2. PathDetectionObject
//    3. PathRootObject
// Note: import statements should then be modified accordingly
def exportType = PathObject

// Choose your *full* output path
def outputPath = "C:/Users/annac/Desktop/WR/WR_T1/WR_T1.tsv"
def outputFile = new File(outputPath)

// Create the measurementExporter and start the export
def exporter  = new MeasurementExporter()
                  .imageList(imagesToExport)            // Images from which measurements will be exported
                  .separator(separator)                 // Character that separates values
                  .includeOnlyColumns(columnsToInclude) // Columns are case-sensitive
                  .exportType(exportType)               // Type of objects to export
                  .exportMeasurements(outputFile)        // Start the export process

print "Done!"

When I leave this line clear, I get some parameters (name, image, parent, centroid etc) but never Area of the shapes imported from CellPose.

// Choose the columns that will be included in the export
// Note: if 'columnsToInclude' is empty, all columns will be included
def columnsToInclude = new String[]{}

I can do it by hand by selecting Area through Shape Features but only when I have all Geometry features selected in the Hierarchy tab. This doesn’t work for all images in project and it doesn’t work through script which hinders the batch processing.

Which arguments do I add so the resulting tab contains name, number of detections and area of each?
I imagine it would look like this:

def columnsToInclude = new String[]{"Name", "Num Detections", _____ }

Thanks!

1 Like

I would recommend starting with the Measure->Export Measurements function in the GUI (described here), as it runs across any number of images. Once you are familiar with that and get the data you want, then dig into the scripting if you need to.
In order to get the areas (or other measurements based on shape), use Analyze->Calculate Features->Add Shape Features as you already mentioned.
A script to add those to all detections in the project (when Run for Project) would look like this

selectDetections()
addShapeMeasurements("AREA", "LENGTH", "CIRCULARITY", "SOLIDITY", "MAX_DIAMETER", "MIN_DIAMETER")

Oops, running around and trying to do things quickly, missed that. If you want many measurements, I would not bother with that line at all, and only use the .excludeColumns(“Name”) if you want to eliminate a few.

def columnsToExclude = new String[]{"Name", "Class","Parent", "ROI" }
def exporter  = new MeasurementExporter()
                  .imageList(imagesToExport)            // Images from which measurements will be exported
                  .separator(separator)                 // Character that separates values
                  //.includeOnlyColumns(columnsToInclude) // Columns are case-sensitive
                   .excludeColumns(columnsToExclude) 
                  .exportType(exportType)               // Type of objects to export
                  .exportMeasurements(outputFile)        // Start the export process

print "Done!"

There is an example of this in use here:

1 Like

I played around with the libraries for different object types and managed to get this working too!
I added this:

import qupath.lib.objects.PathDetectionObject

and I was then able to select parameters I wanted:

def columnsToInclude = new String[]{"Image", "Area µm^2", "Num Detections"}

Thanks for all your help and directing me to QuPath! This solution is actually better then the ImageJ I had in mind :clap:

4 Likes