dimanche 15 décembre 2024

Signal processing with Red and Rebol

In many of the data we collect in hospital, we are dealing with time series, some of which show an unexpected variation as a function of time. For example, in our work on the perception of babies' cries by adults, we observed that most of the signals showed a linear temperature drift over the course of the experiment. This is probably linked to the electronics of our camera. For these reasons, I've developed a few simple algorithms in Red and Rebol 3 that solve some of these problems. I mainly use datatype vector!, which is very efficient for numerical calculations with Red or Rebol 3.

One of the first ways is to remove the DC constant from the signal. Simply remove the mean value of the signal for each value of the signal. Rebol and Red have a function (average) that calculates the average of a vector. 

detrendSignal: func [v [vector!]

"Remove continuous component in signal"
][
        ;--basic (x - mean)
        _v: copy v
        _average: average _v    
---average is a native function in Red and Rebol 3
        repeat i _v/length [_v/:i: _v/:i - _average]
        _v
]

Now let's move on to signal normalization. Normalization is basically bringing signals to the same range or a predefined range. A typical example of a predefined range is the statistical approach of the normalization, which is transforming the signal so that its mean is 0 and standard deviation is 1. This is very useful when you want to compare signals with different amplitudes. Simply calculate the standard deviation of the distribution before normalizing the signal.

stddev: func [v [vector!]
"Standard deviation"
][
sigma: 0.0
foreach value v [sigma: sigma + (power (value - average v) 2)]
sqrt sigma / ((v/length) - 1)
]

normalizeSignal: func [v [vector!]
"Z-score algorithm"
][
;--use z-Score algorithm (x - mean / standard deviation)
_v: copy v
_average: average _v;   ;---average is a native function in Red and Rebol 3
_std: stddev _v             ;--get standart deviation
repeat i _v/length [_v/:i: _v/:i - _average / _std]
_v
]

Another way of normalizing data is to use the minimum and maximum values contained in each data series. With this algorithm, the values of each series are in a space [0.0 .. 1.0]. 

minMaxNormalization: func [v [vector!]
"Min Max normalization"
][
;-- use  min-max algorithm (x: x - min / xmax - xmin)
_v: copy v
xmin: _v/minimum xmax: _v/maximum
repeat i _v/length [_v/:i: (_v/:i - xmin) / (xmax - xmin)]
_v
]

But these techniques aren't always effective, because they don't detect the anomalies (outliers) contained in the signal. For this reason, I often use an algorithm based on the median of the distribution.  This algorithm is more robust and minimizes the effects of anomalies. Of course, we need to calculate the median and interquartile range of our signal.

median: func [
"Return the sample median"
sample [vector!]
][
data: sort to block! copy sample
n: length? data
case [
odd?  n [pick data n + 1 / 2]
even? n [(pick data n / 2) + (pick data n / 2 + 1) / 2]
]
]

interquartileRange: func [
"Return the sample Interquartile Range"
sample [vector!]
][
    data: sort to-block copy sample
    n: length? data
    Q1: 0.25 * n ;--(1 / 4)
    Q2: 0.50 * n ;--(2 / 4)
    Q3: 0.75 * n ;--(3 / 4)
    Q4: 1.00 * n ;--(4 / 4)
    Q3 - Q1 ;--IQR
]


medianFilter: func [v [vector!]
"Median filter"
][
;--use median filter (x: x - med / IRQ)
_v: copy v
med: median _v
IQR: interquartileRange _v
repeat i _v/length [_v/:i: (_v/:i - med) / IQR]
_v
]

A sample  





lundi 2 décembre 2024

The Virgina Project

The Virginia project (https://uniter2p2.fr/en/projects/) focuses on studying the thermoregulation of newborns from thermal images. 

The primary goal of this project is to detect any deterioration in the infant’s health as early as possible using their thermal profile. Over 1,000 images of newborns were captured after birth at four different time points, corresponding to Apgar assessments at 1, 3, 5, and 10 minutes after birth. 

The ultimate objective is to analyze the thermal evolution of these infants at these four key moments.

Infrared images were acquired with a FLIR T650sc camera. The T650sc camera is equipped with an uncooled Vanadium Oxide (VOx) microbolometer detector that produces thermal images of 640 x 480 pixels, with an accuracy of +/- 1 °C.

The Virginia software was developed entirely within the R2P2 laboratory (by ldci) using Red programming language (https://www.red-lang.org),  and the redCV library for image processing (https://github.com/ldci/redCV). The Virginia software includes add-on modules for decoding images.


THE FLIR MODULE


This module has been tested with different FLIR cameras. Its main function is to decode the metadata contained in any radiometric file and to extract the visible image (RGB), the infrared image (IR), the color palette associated with the IR image as well as the temperatures (in degrees °C) associated to each pixel.


This module uses two external programs :


ExifTool (
https://exiftool.org), written and maintained by Phil Harvey, is a fabulous program written in Perl that allows you to read and write the metadata of many computer files. ExifTool supports FLIR files. It works on MacOs, Linux and Windows platforms.

 

ImageMagick (https://imagemagick.org/index.php) is a free software, including a library, as well as a set of command line utilities, allowing to create, convert, modify, and display images in a very large number of formats. The FLIR module mainly uses the convert utility for MacOs and Linux versions and the magick utility for Windows.

Once the metadata are extracted, we call a Python library: PixelLib


THE PIXELLIB LIBRARY

 

This superb library written and maintained by Ayoola Olafenwa is used for the semantic segmentation which allows to identify the newborn in the image. We use the latest version of PixelLib (https://github.com/ayoolaolafenwa/PixelLib) which supports PyTorch and is more efficient for segmentation. The PyTorch version of PixelLib uses the PointRend object segmentation architecture by Alexander Kirillov et al.  2019 to replace the Mask R-CNN. PointRend is an excellent neural network for implementing object segmentation. It generates accurate segmentation masks and runs at a high speed that meets the growing demand for real-time computer vision applications.

First, we only look for the class person without looking for other objects in the RGB image. Then, we get the detected mask as a matrix of true or false values. It is then very simple to reconstruct the binary image of the mask by replacing the true values by the white color. With a simple AND logic operator between the FLIR image and the segmentation mask image, we obtain a new image that keeps only the thermal image of the baby. Only the pixel values higher than 0.0.0 (black) will be considered. Here, for example, the values of the baby's crotch will not be included for the various calculations.



After this first operation of body segmentation, we use a double algorithm. The next step is to detect the contours of the body. This operation will detect the contours in the mask as a polygon of vertices connected by a B-Spline curve. The contour detection algorithm uses several techniques.  First, two morphological operators of dilation and erosion are successively applied to smooth the contours of the mask calculated by the semantic segmentation. Then we use the Freeman coding chain technique (FCC). This technique allows the coding with a limited number of bits (8) of the local direction of a contour element defined in the image. This allows the constitution of a chain of codes from an initial pixel, considering that a contour element links two related pixels. 

When the result of the edge detection is adequate we can proceed to the calculation of the body temperatures. We use a ray-tracing algorithm that makes sure that each pixel of the image belongs to the polygon representing the baby's body. This operation allows us to extract from the 2-D temperature matrix only the body temperatures in the form of a vector which is then used for the different calculations. 


The code is not open-source, as we are in the process of registering patents on certain technological innovations.  As soon as this is possible, I will give free access to all sources. The idea was just to show that you can do great things with Red. 



 Freeman H. On the encoding of arbitrary geometric configurations. IRE Transactions on Electronics Computers. 1961. 10:260–268



Panoptic Segmentation. Alexander Kirillov, Kaiming He, Ross Girshick, Carsten Rother, Piotr Dollar; Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), 2019, pp. 9404-9413