Coder Social home page Coder Social logo

histolab / histolab Goto Github PK

View Code? Open in Web Editor NEW
340.0 340.0 53.0 373.51 MB

Library for Digital Pathology Image Processing

Home Page: http://histolab.readthedocs.io

License: Apache License 2.0

Python 99.78% Makefile 0.22%
bioinformatics biology data-science digital-pathology digital-pathology-data hacktoberfest pathology python research science-research wsi

histolab's Introduction

histolab

Open Source Love

Test Status
Code Quality
Version Info
License
Documentation

Compatibility Details

Operating System Python version
Linux
MacOs

Table of Contents

Motivation

The histo-pathological analysis of tissue sections is the gold standard to assess the presence of many complex diseases, such as tumors, and understand their nature. In daily practice, pathologists usually perform microscopy examination of tissue slides considering a limited number of regions and the clinical evaluation relies on several factors such as nuclei morphology, cell distribution, and color (staining): this process is time consuming, could lead to information loss, and suffers from inter-observer variability.

The advent of digital pathology is changing the way pathologists work and collaborate, and has opened the way to a new era in computational pathology. In particular, histopathology is expected to be at the center of the AI revolution in medicine [1], prevision supported by the increasing success of deep learning applications to digital pathology.

Whole Slide Images (WSIs), namely the translation of tissue slides from glass to digital format, are a great source of information from both a medical and a computational point of view. WSIs can be coloured with different staining techniques (e.g. H&E or IHC), and are usually very large in size (up to several GB per slide). Because of WSIs typical pyramidal structure, images can be retrieved at different magnification factors, providing a further layer of information beyond color.

However, processing WSIs is far from being trivial. First of all, WSIs can be stored in different proprietary formats, according to the scanner used to digitalize the slides, and a standard protocol is still missing. WSIs can also present artifacts, such as shadows, mold, or annotations (pen marks) that are not useful. Moreover, giving their dimensions, it is not possible to process a WSI all at once, or, for example, to feed a neural network: it is necessary to crop smaller regions of tissues (tiles), which in turns require a tissue detection step.

The aim of this project is to provide a tool for WSI processing in a reproducible environment to support clinical and scientific research. histolab is designed to handle WSIs, automatically detect the tissue, and retrieve informative tiles, and it can thus be integrated in a deep learning pipeline.

Getting Started

Prerequisites

Please see installation instructions.

Documentation

Read the full documentation here https://histolab.readthedocs.io/en/latest/.

Communication

Join our user group on Slack

5 minutes introduction

Quickstart

Here we present a step-by-step tutorial on the use of histolab to extract a tile dataset from example WSIs. The corresponding Jupyter Notebook is available at https://github.com/histolab/histolab-box: this repository contains a complete histolab environment that can be used through Docker on all platforms.

Thus, the user can decide either to use histolab through histolab-box or installing it in his/her python virtual environment (using conda, pipenv, pyenv, virtualenv, etc...). In the latter case, as the histolab package has been published on (PyPi), it can be easily installed via the command:

pip install histolab

alternatively, it can be installed via conda:

conda install -c conda-forge histolab

TCGA data

First things first, let’s import some data to work with, for example the prostate tissue slide and the ovarian tissue slide available in the data module:

from histolab.data import prostate_tissue, ovarian_tissue

Note: To use the data module, you need to install pooch, also available on PyPI (https://pypi.org/project/pooch/). This step is needless if we are using the Vagrant/Docker virtual environment.

The calling to a data function will automatically download the WSI from the corresponding repository and save the slide in a cached directory:

prostate_svs, prostate_path = prostate_tissue()
ovarian_svs, ovarian_path = ovarian_tissue()

Notice that each data function outputs the corresponding slide, as an OpenSlide object, and the path where the slide has been saved.

Slide initialization

histolab maps a WSI file into a Slide object. Each usage of a WSI requires a 1-o-1 association with a Slide object contained in the slide module:

from histolab.slide import Slide

To initialize a Slide it is necessary to specify the WSI path, and the processed_path where the tiles will be saved. In our example, we want the processed_path of each slide to be a subfolder of the current working directory:

import os

BASE_PATH = os.getcwd()

PROCESS_PATH_PROSTATE = os.path.join(BASE_PATH, 'prostate', 'processed')
PROCESS_PATH_OVARIAN = os.path.join(BASE_PATH, 'ovarian', 'processed')

prostate_slide = Slide(prostate_path, processed_path=PROCESS_PATH_PROSTATE)
ovarian_slide = Slide(ovarian_path, processed_path=PROCESS_PATH_OVARIAN)

Note: If the slides were stored in the same folder, this can be done directly on the whole dataset by using the SlideSet object of the slide module.

With a Slide object we can easily retrieve information about the slide, such as the slide name, the number of available levels, the dimensions at native magnification or at a specified level:

print(f"Slide name: {prostate_slide.name}")
print(f"Levels: {prostate_slide.levels}")
print(f"Dimensions at level 0: {prostate_slide.dimensions}")
print(f"Dimensions at level 1: {prostate_slide.level_dimensions(level=1)}")
print(f"Dimensions at level 2: {prostate_slide.level_dimensions(level=2)}")
Slide name: 6b725022-f1d5-4672-8c6c-de8140345210
Levels: [0, 1, 2]
Dimensions at level 0: (16000, 15316)
Dimensions at level 1: (4000, 3829)
Dimensions at level 2: (2000, 1914)
print(f"Slide name: {ovarian_slide.name}")
print(f"Levels: {ovarian_slide.levels}")
print(f"Dimensions at level 0: {ovarian_slide.dimensions}")
print(f"Dimensions at level 1: {ovarian_slide.level_dimensions(level=1)}")
print(f"Dimensions at level 2: {ovarian_slide.level_dimensions(level=2)}")
Slide name: b777ec99-2811-4aa4-9568-13f68e380c86
Levels: [0, 1, 2]
Dimensions at level 0: (30001, 33987)
Dimensions at level 1: (7500, 8496)
Dimensions at level 2: (1875, 2124)

Note: If the native magnification, i.e., the magnification factor used to scan the slide, is provided in the slide properties, it is also possible to convert the desired level to its corresponding magnification factor with the level_magnification_factor property.

   print(
        "Native magnification factor:",
        prostate_slide.level_magnification_factor()
    )

    print(
        "Magnification factor corresponding to level 1:",
        prostate_slide.level_magnification_factor(level=1),
    )
    Native magnification factor: 20X
    Magnification factor corresponding to level 1: 5.0X

Moreover, we can retrieve or show the slide thumbnail in a separate window:

prostate_slide.thumbnail
prostate_slide.show()

example-image

ovarian_slide.thumbnail
ovarian_slide.show()

example-image

Tile extraction

Once that the Slide objects are defined, we can proceed to extract the tiles. To speed up the extraction process, histolab automatically detects the tissue region with the largest connected area and crops the tiles within this field. The tiler module implements different strategies for the tiles extraction and provides an intuitive interface to easily retrieve a tile dataset suitable for our task. In particular, each extraction method is customizable with several common parameters:

  • tile_size: the tile size;
  • level: the extraction level (from 0 to the number of available levels);
  • check_tissue: if a minimum percentage of tissue is required to save the tiles;
  • tissue_percent: number between 0.0 and 100.0 representing the minimum required percentage of tissue over the total area of the image (default is 80.0);
  • prefix: a prefix to be added at the beginning of the tiles’ filename (default is the empty string);
  • suffix: a suffix to be added to the end of the tiles’ filename (default is .png).

Random Extraction

The simplest approach we may adopt is to randomly crop a fixed number of tiles from our slides; in this case, we need the RandomTiler extractor:

from histolab.tiler import RandomTiler

Let us suppose that we want to randomly extract 30 squared tiles at level 2 of size 128 from our prostate slide, and that we want to save them only if they have at least 80% of tissue inside. We then initialize our RandomTiler extractor as follows:

random_tiles_extractor = RandomTiler(
    tile_size=(128, 128),
    n_tiles=30,
    level=2,
    seed=42,
    check_tissue=True, # default
    tissue_percent=80.0, # default
    prefix="random/", # save tiles in the "random" subdirectory of slide's processed_path
    suffix=".png" # default
)

Notice that we also specify the random seed to ensure the reproducibility of the extraction process.

We may want to check which tiles have been selected by the tiler, before starting the extraction procedure and saving them; the locate_tiles method of RandomTiler returns a scaled version of the slide with the corresponding tiles outlined. It is also possible to specify the transparency of the background slide, and the color used for the border of each tile:

random_tiles_extractor.locate_tiles(
    slide=prostate_slide,
    scale_factor=24,  # default
    alpha=128,  # default
    outline="red",  # default
)

example-image

Starting the extraction is then as simple as calling the extract method on the extractor, passing the slide as parameter:

random_tiles_extractor.extract(prostate_slide)

example-image

Random tiles extracted from the prostate slide at level 2.

Grid Extraction

Instead of picking tiles at random, we may want to retrieve all the tiles available. The Grid Tiler extractor crops the tiles following a grid structure on the largest tissue region detected in the WSI:

from histolab.tiler import GridTiler

In our example, we want to extract squared tiles at level 0 of size 512 from our ovarian slide, independently of the amount of tissue detected. By default, tiles will not overlap, namely the parameter defining the number of overlapping pixels between two adjacent tiles, pixel_overlap, is set to zero:

grid_tiles_extractor = GridTiler(
   tile_size=(512, 512),
   level=0,
   check_tissue=False,
   pixel_overlap=0, # default
   prefix="grid/", # save tiles in the "grid" subdirectory of slide's processed_path
   suffix=".png" # default
)

Again, we can exploit the locate_tiles method to visualize the selected tiles on a scaled version of the slide:

grid_tiles_extractor.locate_tiles(
    slide=ovarian_slide,
    scale_factor=64,
    alpha=64,
    outline="#046C4C",
)

example-image

grid_tiles_extractor.extract(ovarian_slide)

and the extraction process starts when the extract method is called on our extractor:

example-image

Examples of non-overlapping grid tiles extracted from the ovarian slide at level 0.

Score-based extraction

Depending on the task we will use our tile dataset for, the extracted tiles may not be equally informative. The ScoreTiler allows us to save only the "best" tiles, among all the ones extracted with a grid structure, based on a specific scoring function. For example, let us suppose that our goal is the detection of mitotic activity on our ovarian slide. In this case, tiles with a higher presence of nuclei are preferable over tiles with few or no nuclei. We can leverage the NucleiScorer function of the scorer module to order the extracted tiles based on the proportion of the tissue and of the hematoxylin staining. In particular, the score is computed as formula where formula is the percentage of nuclei and formula the percentage of tissue in the tile t

First, we need the extractor and the scorer:

from histolab.tiler import ScoreTiler
from histolab.scorer import NucleiScorer

As the ScoreTiler extends the GridTiler extractor, we also set the pixel_overlap as additional parameter. Moreover, we can specify the number of the top tiles we want to save with the n_tile parameter:

scored_tiles_extractor = ScoreTiler(
    scorer = NucleiScorer(),
    tile_size=(512, 512),
    n_tiles=100,
    level=0,
    check_tissue=True,
    tissue_percent=80.0,
    pixel_overlap=0, # default
    prefix="scored/", # save tiles in the "scored" subdirectory of slide's processed_path
    suffix=".png" # default
)

Notice that also the ScoreTiler implements the locate_tiles method, which visualizes (on a scaled version of the slide) the first n_tiles with the highest scores:

grid_tiles_extractor.locate_tiles(slide=ovarian_slide)

example-image

Finally, when we extract our cropped images, we can also write a report of the saved tiles and their scores in a CSV file:

summary_filename = "summary_ovarian_tiles.csv"
SUMMARY_PATH = os.path.join(ovarian_slide.processed_path, summary_filename)

scored_tiles_extractor.extract(ovarian_slide, report_path=SUMMARY_PATH)

Representation of the score assigned to each extracted tile by the NucleiScorer, based on the amount of nuclei detected.

Versioning

We use PEP 440 for versioning.

Authors

License

This project is licensed under Apache License Version 2.0 - see the LICENSE.txt file for details

Roadmap

Open issues

Acknowledgements

References

[1] Colling, Richard, et al. "Artificial intelligence in digital pathology: A roadmap to routine use in clinical practice." The Journal of pathology 249.2 (2019)

Contribution guidelines

If you want to contribute to histolab, be sure to review the contribution guidelines

histolab's People

Contributors

alessiamarcolini avatar bguetarni avatar buurro avatar christopher22 avatar dependabot-preview[bot] avatar dependabot[bot] avatar ernestoarbitrio avatar estyxx avatar kheffah avatar leriomaggio avatar nicolebussola avatar nipeone avatar patrick91 avatar pre-commit-ci[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

histolab's Issues

RandomTiler raise ValueError with check_tissue=False

Describe the bug
RandomTiler raise ValueError with check_tissue=False when extracting tiles

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-4b609d378638> in <module>
      9 random_tiles_extractor = RandomTiler(tile_size=(512,512), n_tiles=6, level=0, seed=42, check_tissue=False, prefix='processed/breast/')
     10 
---> 11 random_tiles_extractor.extract(breast_slide)

~/anaconda3/envs/histolab_env/lib/python3.7/site-packages/histolab/tiler.py in extract(self, slide)
    161 
    162         tiles_counter = 0
--> 163         for tiles_counter, (tile, tile_wsi_coords) in enumerate(random_tiles):
    164             tile_filename = self._tile_filename(tile_wsi_coords, tiles_counter)
    165             tile.save(tile_filename)

~/anaconda3/envs/histolab_env/lib/python3.7/site-packages/histolab/tiler.py in _random_tiles_generator(self, slide)
    226             iteration += 1
    227 
--> 228             tile_wsi_coords = self._random_tile_coordinates(slide)
    229             try:
    230                 tile = slide.extract_tile(tile_wsi_coords, self.level)

~/anaconda3/envs/histolab_env/lib/python3.7/site-packages/histolab/tiler.py in _random_tile_coordinates(self, slide)
    183         tile_w_lvl, tile_h_lvl = self.tile_size
    184 
--> 185         x_ul_lvl = np.random.choice(sparse.where(box_mask_lvl)[1])
    186         y_ul_lvl = np.random.choice(sparse.where(box_mask_lvl)[0])
    187 

mtrand.pyx in numpy.random.mtrand.RandomState.choice()

ValueError: 'a' cannot be empty unless no samples are taken

To Reproduce
Steps to reproduce the behavior:

from histolab.data import breast_tissue
from histolab.slide import Slide
from histolab.tiler import RandomTiler

breast_svs, breast_path = breast_tissue()

breast_slide = Slide(breast_path, "processed/")

random_tiles_extractor = RandomTiler(tile_size=(512,512), n_tiles=6, level=0, seed=42, check_tissue=False, prefix='processed/breast/')

random_tiles_extractor.extract(breast_slide)

Tilers should control tissue_percent parameter of has_enough_tissue

At the moment, the user can only decide whether to apply the tissue check during tile extraction or not, and not decide the percentage of tissue required.

We should add another parameter tissue_percent to the tilers' constructor to be used during the has_enough_tissue check

Tests fail when scikit-image colorconv.py module is involved

Description
Some assertion errors on test_image_filters happen using scikit-image==0.17.2 (current version 0.16.2

To Reproduce
Steps to reproduce the behavior:

  1. pip install scikit-image==0.17.2
  2. run tests
  3. See errors

Expected behavior
No failures at all

Screenshots
image

Software

  • OS: MacOSX
  • Python Version: 3.7

IMHO: histolab can't depend on a specific version of a 3rd party app because if that version will be deprecated or no longer updated/supported we will be in troubles. We have to avoid pinning a specific version as dependency (unless it's strictly necessary), in this specific case we need to investigate here https://scikit-image.org/docs/stable/release_notes_and_installation.html and refactor the tests expectations (if needed) according to the changes in this scikit-image version.

Grooming fixtures and expectations

Try to reduce image size of fixtures and expectations used in the test suite.
Some of our fixtures are ±640k, try use minimum reproducible examples for the whole test suite

Add Grid Tiler

We need a Tiler to extract the tiles from a "grid". Tiles may be overlapping or not, depending on user choice.

Extract tiles from the last level - or enable negative level indices

I'd like to be able to specify the level of extraction in a Tiler using a negative index, and so count backwards, instead of just from 0 to the number of available levels.

At the moment if we try to use a negative level histolab throws a LevelError(f"Level cannot be negative ({level_})"), but I think we could relax this constraint.

Inspiration from: ysbecca/py-wsi#38

TCGA custom connector

Main idea
Allow users to retrieve wsi file directly from tcga repo through easy and intuitive API

Solution
Connector module within data package

Remove ⚠️ VisibleDeprecationWarning ⚠️ from tiler.py module

This line, produces a VisibleDeprecationWarning with python 3.6 (here the travis job reference)

scores_ = np.array(scores)[:, 0]

Traceback:

VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
    scores_ = np.array(scores)[:, 0]

Task: Remove this warning and check that each job in CI don't have this warning message anymore

Absolute number as parameter of morphological filters

To use RemoveSmallObjects and RemoveSmallHoles morphological filters we need to specify the parameters min_size and area_threshold, respectively. Those parameters require absolute numbers to be specified taking into consideration the dimensions of the input image.
Therefore, the default value we specify (3000, found experimenting with thumbnails with scale factor 32) could be totally wrong, depending on the dimensions of the image the user could use.

I propose to use a relative number instead of an absolute one, so internally we can compute the real value needed depending on the real dimensions while having a default value which is generally correct.

Remove pandas dependency

We could remove the pandas dependency since it's used only once in the entire codebase. We could save the csv in another way :)

Scikit-image future warning 1

Describe the bug
Scikit-image shows FutureWarnings:

FutureWarning: skimage.measure.label's indexing starts from 0. In future version it will start from 1. To disable this warning, explicitely set the start_labelparameter to 1.

To Reproduce
Steps to reproduce the behavior:

from PIL import Image

from histolab.filters.image_filters_functional import kmeans_segmentation

img = Image.open('image.png')
kmeans_segmentation(img)

Software (please complete the following information):

  • OS: Linux 18.04 LTS
  • Python Version 3.7.7

Initial Update

The bot created this issue to inform you that pyup.io has been set up on this repo.
Once you have closed it, the bot will open pull requests for updates as soon as they are available.

Implement Filters Protocol

It could be nice to implement two Protocols for our Filter classes in the filters subpackage, namely ImageFilter and MorphologicalFilter.

This would be very similar to the implementation of a Scorer protocol (see https://github.com/histolab/histolab/blob/master/src/histolab/scorer.py#L36-L44)

The idea would be to have an abstract and not implemented __call__ method and a concrete __repr__ method, since every filter share the same __repr__ implementation:

def __repr__(self) -> str:
    return self.__class__.__name__ + "()"

Careful attention must be paid in the type annotations for the __call__ method for the two protocols:

  • image filters take a PIL.Image.Image and output Union[PIL.Image.Image, np.ndarray]
  • morphological filters take a np.ndarray and output a np.ndarray

Once we have the protocols, all the classes must subclass the respective protocol to get the implementation of __repr__, and we can use the protocols to improve the type annotations of apply_filters method of Tile (see https://github.com/histolab/histolab/blob/master/src/histolab/tile.py#L50)

Remove Pen mark filter?

The generic pen marks filter is not valid for red pen... We should discuss what to do with it?

tissue_percent in filters.util

https://github.com/MPBA/histolab/blob/master/src/histolab/filters/util.py

Function tissue_percent in filters.util accepts a PIL Image (img) as a parameter for checking the tissue percentage, and it calls mask_percent(img):

def tissue_percent(img: Image.Image) -> float:
    """Compute percentage of tissue in an image.

    Parameters
    ----------
    img : Image.Image
        Input image

    Returns
    -------
    float
        Percentage of image that is not masked
    """
    return 100 - mask_percent(img)

mask_percent in turn takes a numpy array as parameter and it checks for the number of pixels of the array which are not equal to zero:

def mask_percent(mask: np.ndarray) -> float:
    """Compute mask percentage of pixels different from zero.

    Parameters
    ----------
    mask : np.ndarray
        Input mask as Numpy array

    Returns
    -------
    float
        Percentage of image masked
    """

    mask_percentage = 100 - np.count_nonzero(mask) / mask.size * 100
    return mask_percentage

First of all, this call chain is not correct since the parameter types are different.

Secondly, it's not super clear that the image which tissue_percent takes must be ALREADY masked, i.e. not-tissue pixels must be equal to zero.

But if this is the case, I will already have the mask and I could simply use 100 - mask_percent to get the tissue percentage and I would have one obvious way to do it.
To me, having both functions suggests that tissue_percent can accept an original image and it will calculate the filters to get the tissue mask and then get the percentage of tissue.

Please let's discuss to clarify this point!

Color space "fake" conversion

Describe the bug
rgb_to_hed and rgb_to_hsv convert the color in an RGB image correctly, however the color space (mode) is not converted but remains RGB because it is the default mode of np_to_pil.
To Reproduce
Steps to reproduce the behavior:

  1. from histolab.filters.image_filters import RgbToHed
    from PIL import Image
    image = Image.open("/Users/nicole/Desktop/medium_score.png")
  2. rgb_hed = RgbToHed()
  3. rgb_hed(image)
  4. rgb_hed(rgb_hed(image))

Expected behavior
4. should raise the Exception "Input image must be RGB." Instead, it will simply convert the color again.

IMAGE 2020-09-11 11:27:05

IMAGE 2020-09-11 11:27:36

Write README.md

A README is needed. Write a summary of what this thing is 🍡

Add option to change extraction masks

Currently, Histolab extracts tiles from the biggest tissue box of the slide (for backward compatibility with previous work).

I'd like to have the possibility to change the area to extract from, for example from the segmented tissue area.

Another cool thing to add could be the possibility for the users to supply their own binary mask for the extraction.

To achieve this, there are two viable options:

  1. add a parameter to the extract method of the tilers, like 'mode' or something like this, to control the extraction area. This would be easy and compatible with the previous API, but users must use one of the modes we are providing and cannot implement a custom one
  2. provide a different API to provide a mask, either one of the Histolab masks or a custom extraction mask

Gray or Grey in filters?

In the filters subpackage there are a lot of occurrences of gray and grey. We should decide which is the spelling we want to keep.

Score tiles

Add function to score the tile and discuss together the old tiles.py

Use sparse arrays for tissue box masks

Is your feature request related to a problem? Please describe.
Tissue box retrieval and tiles extraction is too slow.

Describe the solution you'd like
Use sparse arrays instead of regular np arrays to save masks

Scikit-image future warning 2

Describe the bug
Scikit-image shows FutureWarnings:

FutureWarning: The new recommended value for bg_label is 0. Until version 0.19, the default bg_label value is -1. From version 0.19, the bg_label default value will be 0. To avoid this warning, please explicitly set bg_label value.

To Reproduce
Steps to reproduce the behavior:

from PIL import Image

from histolab.filters.image_filters_functional import kmeans_segmentation

img = Image.open('image.png')
kmeans_segmentation(img)

Software (please complete the following information):

  • OS: Linux 18.04 LTS
  • Python Version 3.7.7

user warning on histogram filter

UserWarning: This might be a color image. The histogram will be computed on the flattened image. You can instead apply this function to each color channel.

Can we try to apply this function on each color channel automatically if the input image is a colored image?

Cythonize pure numpy functions

Cythonize

  • np_to_pil
  • apply_mask_image
  • mask_percent
  • mask_difference

mask_percent and difference -> https://github.com/histolab/histolab/blob/master/src/histolab/filters/util.py
apply mask image and np_to_pil -> https://github.com/histolab/histolab/blob/master/src/histolab/util.py

Note: this enhancement should decrease the benchmarks time due to the speed of using C for those function that are used often in the codebase.

**THIS IS AN EXPERIMENTAL TASK, BUT IF THE PERFORMANCE WILL BE BETTER THAN THE CURRENT, THIS TASK WILL BE PART OF THE CODEBASE 🥇 **

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.