The Brief History of Binary Images
Last Updated on June 3, 2024 by Editorial Team
Author(s): Radmila M.
Originally published on Towards AI.
Introduction
Binary images might be called as the simplest form of images that can take on two values β black and white, or 0 and 1. Basically, a binary image is a 1-bit image because it takes only 1 binary digit to represent each pixel in it.
While binary images may lack the detail found in grayscale or color images, but they are still incredibly effective at isolating objects and shapes within an image and are widely used in many scientific fields, e.g. in applications where the only information required is general shape or outline, for example optical character recognition, as well as in computer vision problems, in medicine and the oil industry, to name a few.
The simplest (and perhaps a little bit βzoomed inβ) example of such a black-and-white image is a chessboard, though it is not a binary one. Here we also have only black and white squares, which can be considered as βpixelsβ. This analog will help to understand the mechanism of calculating the ratio of white pixels over the sum of both black and white ones, which will be called βporosityβ in the case of a binary image of rocks β more information about this concept will be given later.
By the way, QR codes that are widely used in e-commerce in order to scan them and find out more information about goods and zebras that you can see on the cover image are other examples of black-and-white objects π
In this post, I will guide you through the comprehensive procedure of working with binary images using Python, in particular with PoreSpy [1, 2], which is a collection of image analysis tools used to extract information from 3D images of porous materials, typically obtained from X-ray tomography, and DeePore [3], a deep learning workflow for rapid estimation of a wide range of porous material properties based on the binarized micro-CT images. Below I will consider 3 general cases of working with binary images in terms of image analysis, which involves the extraction of measurements from an image.
Here and below, we will use a 3D micro-CT model of the Berea sandstone from the open database of the Imperial College London [4]:
Use Cases for Working with Binary Images in Python
Case 1: Calculating porosity
One of the most significant properties that can be determined during image analysis is the porosity or one-point correlation function from the statistical point of view.
But what is porosity from the physical point of view?
The texture of rocks consists of mineral grains with different shapes and sizes, therefore their pore structure is extremely complex. The most important factors of the pore structure are how much space there is between these grains and what their shapes are. Because of that, porosity is one of the most important rock properties; it can be defined as a measure of space between grains available for storage of different liquids or gases, for instance, water and hydrocarbons. Quantitatively, porosity is the ratio of the pore volume to the total bulk volume.
It is possible to calculate porosity using Python. First, we need to read 3D image given in a .raw
format as a numpy
array. After that, all black pixels can be calculated. Next, white pixels can be found as the difference between im.size
and black pixels. Finally, porosity, or the ratio of white pixels which are related to spaces between grains over the sum of white and black pixels (keep in mind, the latter are associated with grains).
import numpy as np
#3D image
file_name = 'Berea.raw'
voxel_size = 400
dimension = 400
shape = [voxel_size, voxel_size, dimension]
im0 = np.fromfile(file_name, dtype = 'bool', sep='')
im = im0.reshape(shape)
#print(im)
# Finding porosity, i.e. the ratio of white pixels over the sum of black and white ones
black_pix = np.count_nonzero(im)
print('Number of black pixels:', black_pix)
white_pix = im.size - black_pix
print('Number of white pixels:', white_pix)
porosity = white_pix /(white_pix + black_pix)
print('Porosity:', "%.4f"% porosity)
When running this code snippet, one will get that the value of porosity for the considered Berea sandstone micro-CT image is equal to 19.6% (0.196), which coincides with the value stated in the output file on the Imperial College Londonβs website.
The whole output of the above code looks as follows:
Number of black pixels: 51427006
Number of white pixels: 12572994
Porosity: 0.196
By the way, it is possible to plot porosity profiles across three main axes within the given 3D image to see how this parameter varies inside the sample.
In this case, the code should include the following lines (here im
was defined as im0.reshape
in the previous code fragment):
import porespy as ps
import matplotlib.pyplot as plt
prf0 = ps.metrics.porosity_profile(im, axis=0)
prf1 = ps.metrics.porosity_profile(im, axis=1)
prf2 = ps.metrics.porosity_profile(im, axis=2)
plt.plot(prf0, 'b.-')
plt.plot(prf1, 'g.-')
plt.plot(prf2, 'm.-')
plt.plot([0, 400], [0.804, 0.804], 'r--')
plt.ylim([0, 1])
plt.xlabel('Distance, pixels')
plt.show()
As it can be seen, there is no strong porosity fluctuations for all directions within the sample β all curves lie near the red line with the value of 0.804 (i.e. 1 β porosity = 1β0.196). This observation correlates with a known fact that the Berea sandstone is a well-sorted and homogeneous rock.
Case 2: Plotting the two-point correlation function
As it can be seen from the previous case, porosity might be interpreted as a one-point probability function for a void phase (or pores), and it reflects the probability of the chosen point to be inside the considered phase.
Another important characteristic of any binary image is a two-point correlation function, which can be interpreted as the probability of finding two points separated by some distance within the same phase (pores or grains). This two-point correlation function is typically used to investigate the sampleβs heterogeneity since it contains important information about the typical feature size of image objects and depends on both rock particles and pores between them.
We can use the PoreSpy library to display our two-point correlation function of the Berea sandstone (again, im
and all used libraries were defined in the previous code snippets):
# Two-point_correlation_function
data = ps.metrics.two_point_correlation(im)
print(data)
fig, ax = plt.subplots(1, 1)
ax.plot(data.distance, data.probability)
ax.set_xlabel("distance")
ax.set_ylabel("two point correlation function")
plt.show()
In addition, the form of a two-point correlation function itself provides additional information about a type of particle system (non-overlapping vs. overlapping disks depends on the presence or absence of short-range order oscillation on the curve β in our case, we can say that our Berea sandstoneβs system can be represented as something average between these two forms since one might observe just a tiny oscillation for the small values of two-point correlation function).
Case 3: Estimation of different physical properties of the Berea sandstone using CNNs
In order to estimate main physical properties of the studied Berea sandstone, except porosity and two-point correlation function, one might use DeePore library.
For simplicity, we will use only a single .jpg
image of the studied Berea micro-CT sample to train a convolutional neural network (CNN). CNNs have proved to be efficient in image classification, segmentation, and regression. Thus, under DeePore, a CNN structure combined with two dense layers of neurons to make a regression model that is able to estimate all physical properties of porous material in a supervised manner.
The aim of this AI model is to predict multiple physical properties of a porous material, such as absolute permeability, formation factor, pore density, pore and throat radii, etc.
The running code to feed the image looks quite simple:
import DeePore as dp
# load the trained model
model = dp.loadmodel()
# read data (a single image in which 0 indicates void and 1 indicates solid space)
A = dp.feedsampledata(FileName = "Berea.jpg")
# predict properties
all_preds = dp.predict(model, A, res = 5.345)
# res is the spatial resolution of image in micron/pixel
# save results into a text file and print it in console
dp.prettyresult(all_preds,'results.txt')
The output of the code is given below:
### Single-value parameters ###
__________________________________________________
Properties Value
--------------------------------------------------
Absolute Permeability (um2) 19.4896844
Formation Factor (ratio) 6.7449524
Cementation Factor (ratio) 2.1785357
pore density (1/um3) 9e-07
Tortuosity (ratio) 1.3020263
Average Coordination Number 4.3139989
Average Throat Radius (um) 26.5103079
Average Pore Radius (um) 38.9323575
Average Throat Length (um) 107.6904343
Pore to Throat Aspect ratio 6.0990129
Specific Surface (1/um) 2.59e-05
Pore Sphericity (ratio) 4.0701613
Grain Sphericity (ratio) 0.7959781
Average Grain Radius (um) 43.951428
Relative Young Module (ratio) 0.1218423
--------------------------------------------------
To see all the results please refer to this file:
results.txt
Conclusion
In this post, we discovered the main features of the binary images. Although they might seem to be simple, one would agree that this type of images still contains a lot of useful information.
First of all we started from looking at the statistical properties of the micro-CT binary image of the Berea sandstone, which included porosity (a.k.a one-point correlation function) and two-point correlation function.
Furthermore, AI techniques can be effectively utilized for analyzing binary images. Binary images, which represent the presence or absence of certain features (in our case β pores and rock grains), can be processed using AI algorithms for tasks such as feature extraction, segmentation, and pattern recognition, etc. In this post, we used AI to extract the main properties of the studied 3D sample.
Thanks for reading this post β I hope you found it useful for yourself.
References
- PoreSpy website β https://porespy.org/index.html
- Gostick J, Khan ZA, Tranter TG, Kok MDR, Agnaou M, Sadeghi MA, Jervis R. PoreSpy: A Python Toolkit for Quantitative Analysis of Porous Media Images. Journal of Open Source Software, 2019. doi:10.21105/joss.01296
- DeePore Github repo: https://github.com/ArashRabbani/DeePore
- Data (micro-CT image of the Berea sandstone): https://www.imperial.ac.uk/earth-science/research/research-groups/pore-scale-modelling/micro-ct-images-and-networks/berea-sandstone/
Join thousands of data leaders on the AI newsletter. Join over 80,000 subscribers and keep up to date with the latest developments in AI. From research to projects and ideas. If you are building an AI startup, an AI-related product, or a service, we invite you to consider becoming aΒ sponsor.
Published via Towards AI