IPSDK  4_1_0_2
IPSDK : Image Processing Software Development Kit

tutorial for basic 2d quantification process More...

tutorial for basic 2d quantification process

Overview

This script introduces basics for 2d quantification problems resolution using the IPSDK library. The following figure presents such problems :

Sample_Quantification2d.png

It presents some classical processing steps used during 2d quantification :

Usage

The application can be called through a command line as follows:

   <application_script_filename> [--inputImgFilePath <input_image_file_path>] [--outputReportPath <output_report_file_path>] [--inHalfKnlSize <half_kernel_size>] [--inSpaceSigma <space_sigma_value>] [--inDilateFactor <dilate_factor>]
     
   Arguments:
      --inputImgFilePath  optional; specifies the name of the TIFF file, from
                          which the input grey level image will be loaded; if not 
                          specified by the user, the input image is loaded from file 
                          <DEV_ROOT>/data/Sample/images/blobs_483x348_UInt8.tif
                          
      --outputReportPath  optional; specifies the name of the CSV file, in
                          which the output quantification will be saved; if not 
                          specified by the user, the output results file is saved to
                          file <TEMPORARY_IPSDK_DIR>/Sample/quantification2d.csv

      --inHalfKnlSize     optional; specifies the value of half kernel size along each axis,
                          used while applying the mean smoothing filter; if not
                          specified by the user, equals to 3 by default

      --inSpaceSigma      optional; specifies the value of the spatial Gaussian standard deviation,
                          used while applying the 2d separated bilateral filter; if not
                          specified by the user, equals to 8 by default

      --inDilateFactor    optional; specifies the value of the dilatation factor
                          used while applying the 2d watershed-based binary separation; if not
                          specified by the user, equals to 5 by default

Source code documentation

We start by importing all necessary libraries:

import os
import sys, getopt
import PyIPSDK
import PyIPSDK.IPSDKIPLFiltering as filter
import PyIPSDK.IPSDKIPLBinarization as bin
import PyIPSDK.IPSDKIPLAdvancedMorphology as advmorpho
import PyIPSDK.IPSDKIPLShapeSegmentation as shapesegmentation
import PyIPSDK.IPSDKIPLShapeAnalysis as shapeanalysis

Then we define the input parameters.

# retrieve program parameters
inputImgPath, outputReportPath, inHalfKnlSize, inSpaceSigma, inDilateFactor = readCmdArguments(argv)

We load the input image from the associated TIFF file, by calling the function ipsdk::image::file::loadTiffImageFile.

# opening of input image
greyImg = PyIPSDK.loadTiffImageFile(inputImgPath)
greyImg.png

The first step consists in input image filtering to remove noise. In this tutorial we use Separated bilateral smoothing 2d filter. The good choice of used filter is a quite difficult task since it is dependent on input image type and on searched shapes.

At this step, the user will have to make a choice which is generally the result of successive try. See Filtering image operations for a list of available filters. There is no universal solution for that step, the user could nevertheless be interested in following questions :

# filtering of input image to smooth defaults
greyFilteredImg = filter.separatedBilateral2dImg(greyImg, inHalfKnlSize, inSpaceSigma)
greyFilteredImg.png

Once the input image is filtered, we process to an automatic image binarization. In this tutorial we use Otsu Threshold binarization filter.

# auto threshold on filtered image
binImg, threshold = bin.otsuThresholdImg(greyFilteredImg)
PyIPSDK.saveTiffImageFile(os.path.join(tmpPath, "binImg.tif"), binImg)
binImg.png

Please note in the previous image the connected area enhanced by red circles. During the next step, we will automatically separate these areae using a binary separation technic based on watershed algorithm (Watershed Binary Separation 2d).

# automatic separation of binary shapes
binSepImg = advmorpho.watershedBinarySeparation2dImg(binImg, inDilateFactor, PyIPSDK.eWatershedSeparationMode.eWSM_Split)
PyIPSDK.saveTiffImageFile(os.path.join(tmpPath, "binSepImg.tif"), binSepImg)
binSepImg.png

Once all the shapes are separated, we can proceed to a connected components analysis (Connected Component 2d) :

# connected components analysis of separated binary image
labelImg = advmorpho.connectedComponent2dImg(binSepImg)
PyIPSDK.saveTiffImageFile(os.path.join(tmpPath, "labelImg.tif"), labelImg)
labelImg.png

And then to the extraction of associated shapes (Label shape extraction 2d) :

# extraction of contours from connected components image
shape2dColl = shapesegmentation.labelShapeExtraction2d(labelImg)
contours.png

We can now define :

# definition of a geometric calibration (if available)
geometricCalibration = PyIPSDK.createGeometricCalibration2d(0.01, 0.02, "mm");
# definition of measure set on shapes
measureInfoSet2d = PyIPSDK.createMeasureInfoSet2d(geometricCalibration);
PyIPSDK.createMeasureInfo(measureInfoSet2d, "Area2dMsr");
PyIPSDK.createMeasureInfo(measureInfoSet2d, "EquivalentRayMsr");
PyIPSDK.createMeasureInfo(measureInfoSet2d, "MaxFeretDiameterMsr", shapeanalysis.createMaxFeretDiameterMsrParams(180));
PyIPSDK.createMeasureInfo(measureInfoSet2d, "MeanMsr");

And finally compute these measures :

# shape analysis computation
measureSet = shapeanalysis.shapeAnalysis2d(greyImg, shape2dColl, measureInfoSet2d)

Lastly, we save the measurement report into a csv format.

# save report in csv format
print("Saving measure report in file " + outputReportPath)
PyIPSDK.saveCsvMeasureFile(outputReportPath, measureSet)
report.png

Data can also be directly accessed through python using the following syntax :

# retrieve area measure results
areaMsrResults = measureSet.getMeasure("Area2dMsr").getMeasureResult()
# extract associated results collection
areaValues = areaMsrResults.getColl(0)
print("First label area equals " + str(areaValues[1]))

Or plotted using histogram measure feature (requests matplotlib to be installed):

# retrieve histogram from measure results
areaHistogram = areaMsrResults.extractHistogram(15, 0)
# plot histogram results
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.bar(areaHistogram.getBinMidValues(), areaHistogram.getFrequencies(), areaHistogram.getBinWidth(), color='r')
plt.title("Area histogram")
plt.xlabel('Bin mean')
plt.ylabel('Frequencies')
plt.grid(True)
plt.show()
plot.png

See the full source listing