In the rapidly evolving landscape of scientific research and technology, the field of image analysis and processing has become indispensable, providing unprecedented insight into complex phenomena. This project aims to utilize image processing techniques, using the R programming language, to analyze and characterize bead microparticles. Microparticles find extensive utility in various scientific domains, including medical diagnostics, environmental monitoring, and materials science.
The rise of high-resolution imaging technologies has led to an exponential increase in the volume and complexity of image data, requiring sophisticated computational methods for efficient analysis. In this context, R is a standout programming language that excels in statistical computing and graphics. Leveraging the rich ecosystem of R packages, this project aims to develop an automated image analysis pipeline for bead microparticles.
The primary objectives of this project include: - Image Preprocessing: Implementing techniques to fill and reconnect discontinuous lines and edges. Discard coagulated duplets, multiplets, and beads that are too close together as they may excite each other and produce a false positive signal. - Segmentation and Feature Extraction: Applying algorithms to accurately identify and segment sperical objects (e.g, microparticles). Extracting relevant features such as quantity, size, and intensity for comprehensive characterization. - Visualization: Implementing interactive tools with Tcl/Tk via the tcltk package for the selection of thresholds and smoothing factors. Generating images to control the appropriate functioning of algorithms, for example the reconnection of lines. - Automatization: Combining algorithms for medium-throughput analysis of image data.
This project aims to meet the immediate need for effective bead microparticle analysis and contribute to the broader field of image processing methodologies in the R programming environment. By providing a comprehensive and adaptable framework, the work empowers researchers and practitioners to extract meaningful insights from image data, thus enhancing our understanding of bead microparticles and their diverse applications.
Now available on CRAN so try:
install.packages("biopixR")
or try the latest version of biopixR:
install.package("devtools")
devtools::install_github("Brauckhoff/biopixR")
The objective of this task is to extract important data from an image
of microbeads. The first step involves identifying individual microbeads
and acquiring their coordinates using the objectDetection
function, utilizing edge detection and labeling for thorough analysis
and identification of distinct edges. This will enable precise
coordinate extraction and provide a basis for further analysis using the
biopixR package.
library(biopixR)
res_objectDetection <-
objectDetection(beads, alpha = 0.75, sigma = 0.1)
plot(beads)
with(
res_objectDetection$centers,
points(
res_objectDetection$centers$mx,
res_objectDetection$centers$my,
col = factor(res_objectDetection$centers$value),
pch = 19
)
)
During examination, precise identification and marking of each
individual bead were achieved, aligning with our intended objective. The
objectDetection
functionality successfully detects each
bead using a singular center point and varying colors for
differentiation. Using an alternative visualization method that utilizes
the internal changePixelColor
function can provide a more
comprehensive view of the results (based on
https://CRAN.R-project.org/package=countcolors).
changePixelColor(
beads,
res_objectDetection$coordinates,
color = "purple",
visualize = TRUE
)
For precise analysis, the next step entails eliminating doublets and
multiplets using the sizeFilter
. The filter is applied
using the previously obtained coordinates and centers, as well as
predetermined upper and lower limits. This algorithm calculates the
number of pixels in each labeled object, allowing users to establish
limits for rejecting doublets and multiplets. If the number of detected
objects is higher, the algorithm can automatically calculate limits
using the IQR of the size distribution.
res_sizeFilter <- sizeFilter(
centers = res_objectDetection$centers,
coordinates = res_objectDetection$coordinates,
lowerlimit = 50,
upperlimit = 150
)
changePixelColor(
beads,
res_sizeFilter$coordinates,
color = "darkgreen",
visualize = TRUE
)
This function examines each collected center and scans a specified radius for positive pixels. If another positive pixel from a different object is detected within this range, both are rejected due to their proximity. The radius can be manually selected or determined automatically.
res_proximityFilter <-
proximityFilter(
centers = res_sizeFilter$centers,
coordinates = res_objectDetection$coordinates,
radius = 'auto'
)
changePixelColor(
beads,
res_proximityFilter$coordinates,
color = "darkgreen",
visualize = TRUE
)
text(
res_proximityFilter$centers$mx,
res_proximityFilter$centers$my,
res_proximityFilter$centers$value,
col = "grey"
)
In conclusion, obtaining meaningful information from the filtered
dataset is essential. The main findings encompass the number of objects
that remained and were discarded, object size, signal intensity, and
area density. The resultAnalytics
function of biopixR
extracts and calculates the described parameters. The function requires
input parameters in the form of coordinates, object size, and the
original image. The coordinates can be obtained through any of the three
previously mentioned functions, allowing for flexibility in selectively
applying or omitting specific filters.
result <-
resultAnalytics(
img = beads,
coordinates = res_proximityFilter$coordinates,
unfiltered = res_objectDetection$coordinates
)
result$detailed
beadnumber | size | intensity | x | y | relative_distance |
---|---|---|---|---|---|
3 | 83 | 0.644 | 9.18 | 37.8 | 72.2 |
4 | 84 | 0.670 | 53.11 | 39.4 | 55.6 |
5 | 84 | 0.637 | 108.50 | 43.7 | 80.6 |
7 | 73 | 0.647 | 35.05 | 97.8 | 60.3 |
8 | 85 | 0.576 | 58.36 | 101.1 | 60.4 |
result$summary
number_of_beads | mean_size | mean_intensity | bead_density | estimated_rejected | mean_distance |
---|---|---|---|---|---|
5 | 82 | 0.63 | 0.08 | 10 | 65.8 |
For more detailed information about the features and capabilities of the package feel free to consult our vignettes.
The objective of this example is to address discontinuous edges by filling gaps in lines. To demonstrate the versatility of the package, an algorithm is used to fill gaps in these discontinuous edges, providing valuable insights into the distribution of droplets and microbeads. To demonstrate the algorithm’s functionality, a simplified overview of the preprocessing process is presented, focusing on thresholding and detecting line endings.
thresh <- threshold(droplets, "13%") |> plot()
thresh_cimg <- as.cimg(thresh)
thresh_magick <- cimg2magick(thresh_cimg)
neg_thresh <- image_negate(thresh_magick)
neg_thresh_cimg <- magick2cimg(neg_thresh)
neg_thresh_m <- mirror(neg_thresh_cimg, axis = "x")
neg_thresh_m |> plot()
Detection of line ends:
# same orientation for 'cimg' and 'magick-image'
thresh_clean_m <- mirror(neg_thresh_m, axis = "x")
thresh_clean_magick <- cimg2magick(thresh_clean_m)
# getting coordinates of all line ends
mo1_lineends <- image_morphology(thresh_clean_magick,
"HitAndMiss", "LineEnds")
# transform extracted coordinates into data frame
lineends_cimg <- magick2cimg(mo1_lineends)
end_points <- which(lineends_cimg == TRUE, arr.ind = TRUE)
end_points_df <- as.data.frame(end_points)
colnames(end_points_df) <- c("x", "y", "dim3", "dim4")
# highlighted line ends
changePixelColor(neg_thresh_m,
end_points_df,
color = "green",
visualize = TRUE)
The fillLineGaps function from the package is utilized to address the challenge of discontinuous edges. After applying a threshold, the function identifies line endpoints and connects them to the nearest neighboring edge, ensuring more continuous partition boundaries. Additionally, the objectDetection function is incorporated to exclude specific objects, such as microbeads, to prevent unwanted connections. The resulting output displays the line ends reconnected and microbeads removed.
closed_gaps <- fillLineGaps(droplets,
droplet_beads,
threshold = "13%",
alpha = 1,
sigma = 0.1,
radius = 5,
iterations = 3,
visualize = FALSE)
closed_gaps |> plot()
Animation displaying the closing of gaps with the fillLineGaps function:
After closing the gaps in the lines, important information is extracted and displayed as shown below. The process of feature extraction is described in detail in our vignettes.
partitions | empty_partitions | bead_partitions | single_bead | multiple_beads |
---|---|---|---|---|
125 | 121 | 4 | 3 | 1 |
For more detailed information about the features and capabilities of the package feel free to consult our vignettes.
The following functions are inherited functionality from other
packages and were enhanced or adapted by the package authors: -
edgeDetection
based on cannyEdges
from the
imager package (https://cran.r-project.org/package=imager) -
interactive_objectDetection
based on
interactive_blur
from the magickGUI package
(https://cran.r-project.org/package=magickGUI) -
changePixelColor
based on changePixelColor
from the countcolors package
(https://cran.r-project.org/package=countcolors) -
haralickCluster
partially based on
GLCMFeatures
from the radiomics package
(https://cran.r-project.org/package=radiomics)