# How LabCanvas Image Analysis is validated

> How LabCanvas Image Analysis is checked: 5,144 automated checks against scikit-image, SciPy, scikit-learn and tifffile and images with known answers, the…

URL: https://www.labcanvas.com/image-analysis-validation

Every measurement is checked number by number against established open-source image analysis software and images with known answers before each release: 5,144 automated checks across 26 test suites, all passing on 8 November 2026.

## What is checked, and against what

For each area, reference values are produced by an independent implementation and stored with the code. The checks run the same functions the app uses and compare the results to the stated tolerance.

| Area | What is checked | Reference | Checks |
| --- | --- | --- | --- |
| Image files and projects | TIFF and BigTIFF reading (8-, 16-, 32-bit, stacks, LZW and Deflate, both byte orders, ImageJ and OME-TIFF metadata, pixel size and units), ImageJ TIFFs written back unchanged, and projects that save and reopen every image, ROI and table | tifffile 2026.10.15, NumPy 2.5.3 | 123 |
| Measurements | Area, mean, SD, min/max, median, mode, integrated density, centroid and centre of mass, perimeter, Feret diameters, fitted ellipse, shape descriptors, skewness and kurtosis, line profiles, for every ROI shape and calibration | NumPy 2.5.3, SciPy 1.18.1, scikit-image 0.26.0; ImageJ definitions by hand | 1,293 |
| ROI tools | Combining, intersecting and subtracting ROIs, enlarging, shrinking and rings by exact distances, convex hull, fitted ellipses and circles, rotation and scaling, masks to ROIs | NumPy 2.5.3, SciPy 1.18.1, scikit-image 0.26.0 | 347 |
| ImageJ ROI files | RoiSet.zip and.roi files written and read for every ROI type, with names, colours, line widths and positions, in both directions | roifile 2026.9.22 | 351 |
| Spot detection | Find Maxima with ImageJ’s prominence rule: plateaus, edges, ties and saddles, against h-maxima | scikit-image 0.26.0 h_maxima; ImageJ MaximumFinder rules by hand | 98 |
| Cell counter and spots | Counts per category and per ROI, marker tables, and spots found against images with known spots | synthetic ground truth; ImageJ's Cell Counter and Find Maxima rules by hand | 54 |
| Threshold and particles | The 16 automatic threshold methods, connected objects, outlines and traced perimeters, holes, watershed splitting of touching objects, particle measurements and summaries | scikit-image 0.26.0, scipy 1.18.1, NumPy 2.5.3; hand-computed traced perimeters; constructed touching disks | 509 |
| Trainable pixel classifier | Pixel features at several scales (smoothing, gradients, Laplacian, Hessian and structure-tensor eigenvalues), the random forest’s accuracy against scikit-learn’s, and nuclei found after a few brush strokes | scipy 1.18.1 ndimage, scikit-image 0.26.0, scikit-learn 1.9.1 RandomForestClassifier; the Nuclei sample's ground truth | 170 |
| Western blots and gels | Lane profiles, background baselines, band areas, normalisation to a loading control or total protein, molecular-weight ladder fits and lane alignment, on blots with known amounts and sizes | NumPy 2.5.3 (polyfit, correlate, median), SciPy 1.18.1; known amounts, sizes and shifts of the sample and synthetic blots | 183 |
| Background, filters and colocalisation | Rolling-ball and sliding-paraboloid background, Gaussian, median, mean, minimum and maximum filters, unsharp mask, image maths, bit-depth conversion, Pearson and Manders coefficients with Costes thresholds | numpy 2.5.3, scipy 1.18.1, scikit-image 0.26.0; ImageJ definitions by hand | 178 |
| Contrast and noise | Local contrast (CLAHE), non-local-means denoising, outlier removal, despeckle and FFT bandpass filtering | scikit-image 0.26.0, scipy 1.18.1, numpy 2.5.3; ImageJ definitions by hand | 50 |
| Binary images | Erode, dilate, open, close (ImageJ’s count rule and exact distances), fill holes, outlines, distance maps with non-square pixels, ultimate points | scipy 1.18.1 ndimage, numpy 2.5.3; ImageJ's count rule by hand; synthetic discs | 82 |
| Image calculator | Arithmetic and logic between images and channels, ratio images with background and threshold, and maths on one image, in 32-bit or with ImageJ’s integer rules | numpy 2.5.3 float32 and int64; ImageJ's integer rules by hand | 58 |
| Drift correction | Sub-pixel registration by phase correlation, shifting stacks and channels, and drift recovered from images with known drift | scikit-image 0.26.0 phase_cross_correlation, scipy 1.18.1 ndimage.shift; synthetic drift | 55 |
| Stacks | Reslicing, orthogonal views and substacks | numpy 2.5.3, scipy 1.18.1 map_coordinates | 18 |
| Image check | Clipped pixels, signs of processed or lossy data, uneven illumination and focus, against images with known faults | NumPy 2.5.3, SciPy 1.18.1; known truth of synthetic images and the samples | 66 |
| Colour | Colour deconvolution of stains (H-DAB, H&E) and the colour spaces used for colour thresholds | scikit-image 0.26.0 separate_stains and rgb2lab, Python colorsys; known stain amounts of the synthetic IHC section | 46 |
| Cell assays | Nuclear vs cytoplasmic ratio, spots per cell, colony counting, wound closure, FRAP recovery fits, calcium ΔF/F₀ and peaks, against reference pipelines and samples with known answers | scikit-image 0.26.0 expand_labels, h_maxima, Hough circles and watershed; SciPy 1.18.1 distance_transform_edt, curve_fit, find_peaks, correlate; NumPy 2.5.3; the samples' ground truth | 131 |
| Structures and motion | Skeletons, branches and junctions, Sholl analysis, tube networks, kymographs, particle tracking and mean squared displacement | scikit-image 0.26 skeletonize, skan 0.13, scipy ndimage/map_coordinates/linear_sum_assignment, trackpy 0.7, numpy; samples against their ground truth | 189 |
| Deconv |  | scikit-image 0.26.0 richardson_lucy, microscPSF slowGL, psfmodels 0.3.3, SciPy 1.18.1 quad; synthetic ground truth | 31 |
| Deepseg |  | stardist 0.9.2 and cellpose 3.1.1.3; StarDist 2D_versatile_fluo, ONNX checked against the BioImage Model Zoo TensorFlow output | 45 |
| Formats |  | pydicom, readlif, czifile, nd2, oiffile and tifffile; 42 fixture cases | 557 |
| Large |  | tifffile, zarr, numcodecs and libjpeg-turbo; region extracts against NumPy slices | 156 |
| Objects3d |  | scikit-image 0.26 label, regionprops, marching_cubes and watershed; SciPy 1.18 ndimage; synthetic shapes with known volume and surface; cells3d | 237 |
| Recipes |  | the same steps run by hand on the samples; ImageJ macro export and import round trips | 95 |
| Stitch |  | scikit-image 0.26.0 phase_cross_correlation; synthetic tiles with known positions | 22 |
| Total |  |  | 5,144 |

## Raw values, ImageJ’s definitions

- **Raw data:** 16-bit and 32-bit images are measured as they are; nothing is converted to 8-bit for analysis.
- **Calibration:** pixel sizes and units are read from ImageJ and OME-TIFF metadata, and every table says its units.
- **Definitions:** measurements, thresholds and particle analysis follow ImageJ’s documented definitions, so results agree with published ImageJ analyses.
- **Methods text:** every results table says how its numbers were made, with the settings, ready for a methods section.

## Tolerances

- **Counts and pixel areas:** exact, against the reference and against images with a known answer.
- **Measurements** (means, standard deviations, calibrated areas and lengths, shape descriptors, ratios and coefficients): within 10⁻⁹ of the reference, relative; most agree to 10⁻¹².
- **Processed images** (backgrounds, filters, profiles), computed in single precision as ImageJ does: within a thousandth of a grey level of double-precision references, and within a hundredth for rolling-ball backgrounds of large radius.
- **Iterative fits** (recovery curves, ladder fits, registration): within 10⁻⁶, relative, unless a check states a looser bound and why.
- **Known answers:** sizes, rates and amounts recovered from synthetic images within the error stated in each check (for example molecular weights within 2%, wound areas within 1.1%).

## How to cite

Images were analysed in LabCanvas Image Analysis (www.labcanvas.com, accessed *month year*). Then paste the methods sentence of each results table, which names the methods and settings used.

## Frequently asked questions

**How do I cite LabCanvas Image Analysis in a paper?**

Name the software, its web address and when you used it, then the method: “Images were analysed in LabCanvas Image Analysis (www.labcanvas.com, accessed November 2026).” Every results table carries a methods sentence with the settings filled in (threshold method, sizes, background, normalisation) to paste after it.

**Will I get the same numbers as ImageJ or Fiji?**

For the standard measurements, yes: they follow ImageJ’s definitions (a pixel belongs to a region when its centre is inside it, ImageJ’s perimeter of traced outlines, integrated density, Feret diameters, the same automatic threshold methods). Where ImageJ’s definition differs from scikit-image’s, the ImageJ definition is tested on hand-computed cases. Methods that ImageJ leaves to plugins, such as the assays, are checked against scikit-image and SciPy pipelines and against images with known answers.

**Are measurements taken from the picture on screen?**

No. Measurements always read the raw values of the file (8-, 16- or 32-bit), never the displayed picture, so changing brightness, contrast or colours never changes a number. The image check warns when the data are clipped or lossy (for example a JPEG or a picture copied from a figure).

**How close do the numbers have to be?**

Counts and areas in pixels must match exactly. Measurements such as means, standard deviations, ratios and distances must match the reference to within one part in a billion (10⁻⁹, relative). Processed images, which are computed in single precision as in ImageJ, must agree with double-precision references to within a thousandth of a grey level (a hundredth for large rolling-ball backgrounds), and iterative fits to within one part in a million.

**What is not covered yet?**

Deep-learning segmentation models (such as StarDist or Cellpose) are not included: segmentation uses thresholds, watershed and a trainable classifier that learns from your brush strokes. Analysis is of 2D planes (stacks are handled slice by slice and as projections, without 3D objects), and microscope vendor files (.czi,.nd2,.lif) need to be saved as TIFF or OME-TIFF first.

**Where do the reference values come from?**

From independent, widely used open-source software (scikit-image, SciPy, NumPy, scikit-learn, tifffile, roifile, trackpy and skan, as named in the table), run on the same images, and from synthetic images whose content is known exactly, such as a field with a known number of cells or a blot with known band amounts. The reference values are stored with the code and the checks run before every release.

Questions or a result that looks wrong? Email [labcanvasapp@gmail.com](mailto:labcanvasapp@gmail.com) with the image; we check every report. See also the [Image Analysis guide](https://www.labcanvas.com/blog/image-analysis-microscopy-western-blot), how the [statistics are validated](https://www.labcanvas.com/statistics-validation), and our [editorial guidelines](https://www.labcanvas.com/editorial-guidelines).
