Skip to main content

cv2geojson

cv2geojson is an open-source project to export annotation contours extracted using OpenCV-python package to GeoJSON format.

Contents

Introduction

Contours can be defined as continuous curves that connect points of the same color or intensity along a boundary. They are commonly used for shape analysis, object detection, and recognition. For instance, in liver pathology, fat vacuoles can be identified as circular white blobs (check out this link for an example). The traditional method to extract contours in OpenCV is by utilizing cv2.findContours. However, these extracted contours are not easily visualized in third-party software tools such as QuPath. To overcome this limitation, the cv2geojson Python package provides a seamless bridge between the contours extracted using OpenCV and the geometries represented as GeoJSON objects. By converting the extracted contours to the GeoJSON format, they can be easily visualized and utilized in various software tools.

Example 1

In digital pathology, images can be quite large. For example, download the whole slide image with tissue sample ID GTEX-12584-1526 from histology page. This image has 45,815x38,091 pixels which requires about 5GB of storage uncompressed. Rather than storing a binary mask for the foreground segmentation, the mask can be converted to polygons and stored as a geojson file. The image below shows a snapshot from the QuPath software. The foreground contour is blue.

QuPath Snapshot 2
Snapshot from QuPath software visualising foreground segmentation

Example 2

Here is a dummy example to demonstrate the utility of cv2geojson package.

import cv2 as cv
from cv2geojson import find_geocontours, export_annotations

# read sample image
img = cv.imread('./example/img_01.png')
mask = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# Extract annotation contours
geocontours = find_geocontours(mask, mode='imagej')

# convert geocontours to geojson.Feature format
features = [contour.export_feature(color=(0, 255, 0), label='roi') for contour in geocontours]
export_annotations(features, './example/img_01.geojson')
QuPath Snapshot 2

Installation

The recommended way to install is via pip:

pip install cv2geojson

Main Methods

find_geocontours(mask, mode='opencv')

This function, similar to cv2.findContours, retrieves contours from the binary mask and grouped them as geometries similar to GeoJSON objects. The geometries are a useful tool for shape analysis or object detection.

  • Parameters:
    • mask: {numpy.ndarray}: binary mask of value 255 or 0
    • mode: {str}: the contour represetnation method; either 'imagej' or 'opencv'
  • Returns:
    • geocontours: {cv2geojson.geocontours}: a list of detected geomtries: Polgy, Point, or LineString

Note: OpenCV contours are based on pixel centers whereas imagej contours are based on pixel edges. Both methods are plausible options but imagej method is recommended for visualisation in QuPath. Here is a short script to demonstrate the differences between the two methods.

import numpy as np
from cv2geojson import find_geocontours

# define a binary mask
mask = np.array([[0,   0, 0, 0, 0],
                 [0,   0, 0, 0, 0],
                 [0, 255, 0, 0, 0],
                 [0,   0, 0, 0, 0],
                 [0,   0, 0, 0, 0]], dtype=np.uint8)

# extract geocontours
geocontour_opencv = find_geocontours(mask, mode='opencv')[0]
geocontour_imagej = find_geocontours(mask, mode='imagej')[0]

print(f'Poplygon Coordinates using OpenCV method: {geocontour_opencv.export_geometry()}')
print(f'Poplygon Coordinates using ImageJ method: {geocontour_imagej.export_geometry()}')

The following result is printed:

Poplygon Coordinates using OpenCV method: {"coordinates": [1, 2], "type": "Point"}
Poplygon Coordinates using ImageJ method: {"coordinates": [[[1, 2], [1, 3], [2, 3], [2, 2], [1, 2]]], "type": "Polygon"}

draw_geocontours(mask, geocontours, scale=1, offset=(0, 0), mode='opencv')

This function, similar to cv2.drawContours, draw geocontours to the corresponding binary mask.

  • Parameters:
    • mask: {numpy.ndarray}: binary mask of value 255 or 0
    • goecontours: {list: cv2geojson.GeoContour}
    • scale: {int}: downsampling ratio
    • offset: {tuple: 2}: offset displacement
    • mode: {str}: either 'imagej' or 'opencv'

export_annotations(features, path_to_geojson)

This function write GeoJSON.Feature objects to a file.

  • Parameters:
    • features: {list: geojson.feature.Feature}
    • path_to_geojson: {str}

Here is a short script to demonstrate its usage. Also see export_feature

import numpy as np
from cv2geojson import find_geocontours, export_annotations

# define a binary mask
mask = np.array([[0,   0,   0,   0, 0],
                 [0,   0,   0,   0, 0],
                 [0, 255, 255, 255, 0],
                 [0, 255, 255, 255, 0],
                 [0,   0,   0,   0, 0],
                 [0,   0,   0,   0, 0]], dtype=np.uint8)

# extract geocontours
geocontours = find_geocontours(mask, mode='imagej')

# export features
features = []
for geocontour in geocontours:
    features.append(geocontour.export_feature(color=(255, 0, 0),
                                              label='rectangle',
                                              name='ID1'))
export_annotations(features, 'test.geojson')

load_annotations(path_to_geojson)

This function read GeoJSON objects from a file and convert them to cv2geojson.GeoContour.

  • Parameters:path_to_geojson: {str}
  • Returns: geocontours: {list: cv2geojson.GeoContour}

class GeoContour

The library implements a new class, cv2geojson.GeoContour, which facilitates the seamless integration of contours extracted using cv2.findContours and geometries defined as GeoJSON objects. An instance of this class can be initialized by providing either contours or GeoJSON objects. Here is an example of how to initialize the class using both a GeoJSON object and NumPy contours:

import numpy as np
from geojson import LineString
from cv2geojson import GeoContour

# initialise GeoContour class with a geojson LineString object
geometry = LineString([(1, 2), (5, 15)])
geocontour_1 = GeoContour(geometry=geometry)

# initialise GeoContour class with contours
geocontour_2 = GeoContour(contours=[np.array([[1, 2], [5, 15]])]) 

Attributes:

contours

 list of numpy.ndarray: the coordinates of the geometry

type

 str: Point, LineString, or Polygon

Methods:

get_contours(self, scale=1, offset=(0, 0))

  • Parameters:
    • scale: {int}: the down-scaling ratio
    • offset: {tuple: 2}
  • Returns: contours: {list of numpy.ndarray}: (contours - offset)/scale

export_geometry(self)

  • Returns: {geojson.Point, geojson.LineString, geojson.Polgyon}

export_feature(self, color=None, label=None, name=None)

  • Parameters:
    • color: {tuple: 3}: (r, g, b) in range 0 to 255
    • label: {str}: the class name for the identified geometry
    • name: {str}: the unique ID given to the identified geometry
  • Returns: {geojson.Feature}: append provided properties to the geometry

area(self, resolution=1.0)

  • Parameters:
    • resolution: {float}: the pixel size in micro-meter
  • Returns: {float}: the total area of polygon in micro-meter-squared

min_enclosing_circle(self)

  • Returns:
    • center: {tuple: 2}: (x, y) coordinates
    • radius: {float}: radius in pixels

circularity(self)

  • Returns: {float}: $4\pi \text{Area}/\text{Perimeter}^2$

solidity(self)

  • Returns: {float}: the polygon area divided by its convex hull area

aspect_ratio(self)

  • Returns: {float}: the width of the enclosing rectangle divided by its height

elongation(self)

  • Returns: {float}: the minor to major diameter of the enclosing oval

holes_num(self)

  • Returns: {int}: the number of holes in the polygon

fill_hole(self, resolution=1.0, hole_size=-1.0)

Remove any holes in the polygon larger than hole_size

  • Parameters:
    • resolution: {float}: the pixel size in micro-meter
    • hole_size: {float}: the hole area in micro-meter-squared. If -1, all holes will be filled.

scale_up(self, ratio=1, offset=(0, 0))

Scale up the coodinates: x_new = (ratio * x_old) + offset

  • Parameters:
    • ratio: {int}
    • offset: {tuple: 2}

scale_down(self, ratio=1, offset=(0, 0))

Scale down the coodinates: x_new = (x_old - offset) / ratio

  • Parameters:
    • ratio: {int}
    • offset: {tuple: 2}

copy(self)

  • Returns: {cv2geojson.GeoContour}

Metadata

Release files for cv2geojson 0.0.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cv2geojson 0.0.9
File Size Uploaded
cv2geojson-0.0.9.tar.gz 12.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cv2geojson 0.0.9
File Interpreter ABI Platform
cv2geojson-0.0.9-py3-none-any.whl Python 3 none any Details

Total release size: 21.2 kB

Release files / cv2geojson-0.0.9.tar.gz

Download URL cv2geojson-0.0.9.tar.gz
Size 12.0 kB
Tags Source
SHA-256 checksum
How to use checksums
185c198a842beb0f7ab5b79d6a59a438b5d0692b24b299349a00d181ec86cb09
BLAKE2b-256 checksum
How to use checksums
341b9b603f5e1868d4efbf21da3d383d8590b67cdef2dae84d348ddcb63dcb8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.9.13

Release files / cv2geojson-0.0.9-py3-none-any.whl

Download URL cv2geojson-0.0.9-py3-none-any.whl
Size 9.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ace3d167456de7849d6e4e454d1d6ccce060615c243134a662f175fd8089317d
BLAKE2b-256 checksum
How to use checksums
2ecd820626c7fab7627c59514f4e8234b1b1b1cfd083dd78c780bacbbaccf3c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.9.13

Release history Release notifications | RSS feed

This release

0.0.9 This release

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page