knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.path = "man/figures/README-",
  out.width = "100%"
)

clasifierrr

Motivation

The goal of clasifierrr is to ... classify image regions using R.

In my field of study, there are many cases where one has a lot of images that require classification. Whether it is counting cells, quantifying areas in IHC, counting dots in cells, measuring spheroid sizes ... And it would be nice to automate those tasks.

Nonetheless, many of those classification parameters are experiment-specific, making a generalized classifier inpractical. In addition, the number of images is usually enough to be extremely tedious to work out by a human but not enough to train a neural network.

clasifierrr takes care of those cases, where small datasets are used to build a clasification algorithm and allow the user to deploy it on many images.

Installation

remotes::install_github("jspaezp/clasifierrr")

Workflow

  1. Externally create the masking files for the classification
  2. Internally create a parameters data frame
  3. use build_train_multi to create the training dataset
  4. use ranger to train the classifier
  5. use classify_img to classify as many images as you want
  6. (optional) use filter_masks to remove objects that are too small or too big

Example

library(clasifierrr)
library(EBImage)
library(ranger)
## basic example code
## 
## 
params_df <- tibble::tibble(
    file = c(
        system.file(
            "extdata", "4T1-shNT-1_layer1.png",
            package = "clasifierrr"),
        system.file(
            "extdata", "4T1-shNT-1_layer2.png",
            package = "clasifierrr")),
    classif = c("spheroid", "bg"),
    related_file = system.file(
        "extdata", "4T1-shNT-1.png",
        package = "clasifierrr")
)

params_df

Form of the classifier files

It has to be a file of the same size of the related image, where it is all black except for the desired classifier section.

Several classifications can be used.

I personally use gimp to generate those, just open the image you want to classify, draw on a new layer, disable the main layer and export to a png.

base_image <- readImageBw(params_df[[3]][[1]])
display(
  EBImage::combine(
    base_image,
    readImageBw(params_df[[1]][[1]]),
    readImageBw(params_df[[1]][[2]])),
  method = "raster", all = TRUE)

Calculating Features

The classifier is based on the concept of features, which is applying several filters to the image to detect edges and calculate the consistency with the neighborhood.

you can use as many filters as you want but THE FILTER WIDTHS HAVE TO BE ODD NUMBERS, also consider that the more filters, the more memmory you will need.

features <- calc_features(
  base_image, filter_widths = c(3,5),
  shape_sizes = c(201, 501))
head(features, 2)

Each of the columns can be made to an image

display_filters(features, dims = dim(base_image), scale = TRUE)

Building a training dataset from the files

The program goes in to the files, generates the features form the base image and assigns a classification to the pixles that overlap with the region you defined in the "classifier files" (the ones that look like squigly lines)

trainset <- build_train_multi(
  params_df, 
  filter_widths = c(3,5),
  shape_sizes = c(201, 501))
head(trainset)

Train a classifier

Here we use any "machine learning" algorithm as our classifier. I really like ranger, so that is what I will recommend.

classifier <- ranger(
    pixel_class ~ .,
    data = trainset, 
    num.trees = 100, 
    importance = "impurity", 
    min.node.size = 5, 
    max.depth = 200)
classifier

If the classifier was trained using importance = "impurity", you can ask it to give you the relative importance of the variables used.

sort(ranger::importance(classifier), decreasing = TRUE)

Using the classifier on an image

The classify_img has an interface for many kinds of inputs depending on what you have planned.

It Can be used directly on calculated features ...

# This just reads the image to classify
test_img <- readImageBw(system.file(
        "extdata", "4T1-shNT-1.png",
        package = "clasifierrr"))

test_feat <- calc_features(
  test_img, filter_widths = c(3,5),
  shape_sizes = c(201, 501))

class_img <- classify_img(
    classifier, 
    feature_frame = test_feat, 
    dims = dim(test_img), 
    filter_widths = c(3,5),
    shape_sizes = c(201, 501),
    class_highlight = "spheroid")
display(class_img, method = "raster")

It can also be used on a raw image ...

class_img <- classify_img(
  classifier, 
  img = test_img, 
  filter_widths = c(3,5), 
  shape_sizes = c(201, 501))
# display(colorLabels(class_img), method = "raster")

And as well in a system file

class_img <- classify_img(
  classifier,
  path = system.file(
    "extdata", "4T1-shNT-1.png",
    package = "clasifierrr"),
  filter_widths = c(3,5), 
  shape_sizes = c(201, 501),
  class_highlight = "spheroid")

# display(class_img, method = "raster")

Cleaning the final image

The final image can be cleaned manually or using filter_masks, which can remove stuff either too big or small.

As a reminder, white regions are considered objects, so if your object is black, try running something like img <- 1- img

filt_class_img <- filter_masks(min_radius = 10, max_radius = Inf, mask = class_img)

display(filt_class_img, method = "raster")
table(filt_class_img)
filt_class_img


jspaezp/clasifierrr documentation built on March 2, 2020, 11:20 a.m.