Binned GLCM 5 Features implemented in CuPy
Project description
📖Wiki
GLCM Bin 5 on CuPy
This is a CuPy reimplementation of my glcmbin5
on my other repository.
This directly utilizes CUDA to speed up the processing of GLCM.
Installation
Python >= 3.7
First, you need to install this
pip install glcm-cupy
Then, you need CuPy. You need to install CuPy manually, as it's dependent on the version of CUDA you have.
I recommend using conda-forge
as it worked for me :)
For CUDA 11.6
, we use
conda install -c conda-forge cupy cudatoolkit=11.6
Replace the version you have on the arg.
conda install -c conda-forge cupy cudatoolkit=__._
Usage
The usage is simple:
>>> from glcm_cupy import GLCM
>>> import numpy as np
>>> from PIL import Image
>>> ar = np.asarray(Image.open("image.jpg"))
>>> ar.shape
(1080, 1920, 3)
>>> g = GLCM(...).run(ar)
>>> g.shape
(1074, 1914, 3, 8)
The last dimension of g
is the GLCM Features.
To retrieve a specific GLCM Feature:
>>> from glcm_cupy import CONTRAST
>>> g[..., CONTRAST].shape
(1074, 1914, 3)
You may also consider simply glcm
if you're not reusing GLCM()
>>> from glcm_cupy import glcm
>>> g = glcm(ar, ...)
Example: Processing an Image
Features
These are the features implemented.
HOMOGENEITY = 0
CONTRAST = 1
ASM = 2
MEAN = 3
VAR = 4
CORRELATION = 5
Don't see one you need? Raise an issue, I'll (hopefully) add it.
Radius & Step Size
- The radius defines the window radius for each GLCM window.
- The step size defines the distance between each window.
- If it's diagonal, it treats a diagonal step as 1. It's not the euclidean distance.
Binning
To reduce GLCM processing time, you can specify bin_from
& bin_to
.
This will bin the image from a range to another.
I highly recommend using this to reduce time taken before raising it.
E.g.
I have an RGB image with a max value of 255.
I limit the max value to 31. This reduces the processing time.
GLCM(..., bin_from=256, bin_to=32).run(ar)
The lower the max value, the smaller the GLCM required. Thus allowing for more GLCMs to run concurrently.
Direction
By default we have the following directions to run GLCM on.
- East:
Direction.EAST
- South East:
Direction.SOUTH_EAST
- South:
Direction.SOUTH
- South West:
Direction.SOUTH_WEST
For each direction, the GLCM will be bi-directional.
We can specify only certain directions here.
>>> from glcm_cupy import GLCM
>>> GLCM()
>>> g = GLCM(directions=(Direction.SOUTH_WEST, Direction.SOUTH))
The result of these directions will be averaged together.
Notes
Q: Why did my image shrink?
The image shrunk due to
step_size
&radius
.The amount of shrink per XY Dimension is
size - 2 * step_size - 2 * radius
Q: What's the difference between this and
glcmbin5
?This is the faster one, and easier to use. I highly recommend avoiding
glcmbin5
as it has C++, which means you need to compile manually.It's the first version of GLCM I made.
CUDA Notes
Why is the kernel split into 4?
The kernel is split into 4 sections
- GLCM Creation
- Features (ASM, Contrast, Homogeneity, GLCM Mean I, GLCM Mean J)
- Features (GLCM Variance I, GLCM Variance J)
- Features (GLCM Correlation)
The reason why it's split is due to (2) being reliant on (1), and (3) on (2), ... .
There are some other solutions tried
__syncthreads()
will not work as we require to sync all blocks.- We can't put all calculations in a block due to the thread limit of 512, 1024, 2048.
- We require 256 * 256 threads minimum to support a GLCM of max value 255.
- Cooperative Groups imposes a 24 block limit.
Thus, the best solution is to split the kernel.
Atomic Add
Threads cannot write to a single pointer in parallel, information will be overwritten and lost. This is the Race Condition.
In order to avoid this, we use Atomic Functions.
... it is guaranteed to be performed without interference from other threads
Custom Atomic Add
Deprecated >=1.7
Currently atomicAdd()
doesn't have the signature to support uint8
or unsigned char
. We get this implementation
from this StackOverflow
Answer
Change Log
1.6
Dropped dependency on J variables as I & J are always the same
1.7
Fix issue with GLCM overflowing by making it float32
1.8
Implement Cross GLCM
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for glcm_cupy-0.1.9-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 55c6d7d8920b5d647813b0b3bb180104a54903c56662272dabfe8d3f67f80489 |
|
MD5 | 6a5218614dd6a75aec8535393504b627 |
|
BLAKE2b-256 | 1d52d78f01d80cc818ebefe5aeb5a300fa1cc35230d001d062b53e2a24949034 |