mercredi 28 avril 2021

Thermal Image Segmentation (Part 2)

In the previous topic we presented a simple way for thermal image segmentation which was adapted to simple images. Now, we will try to process a lit bit complicated thermal images such as this one:



This picture comes from one of our research program in hospital, and as it can be seen, the thermal image is really noisy with a lot of temperature variations. In this case, a RGB approach is unadapted and gives very poor results. 

To process such images, the way I adopted is a semantic segmentation approach which involves the use of neural networks to accurately segment images.

After some research, I found a fantastic library, PixelLib, which is written by a talented programmer, Ayoola Olafenwa. Her code is available here: https://github.com/ayoolaolafenwa/PixelLib.

This library is written with Python. But, since Red  allows to call external programs, it was really easy to use the Ayoola's library, and the result is perfect. Basically the redCV code extracts a RGB image from the thermal image and then applies semantic segmentation for each pixel.



Here we use an instance segmentation method and the program identifies the object as a cup with a probability = 0.99. Good performance.


You'll find here https://pixellib.readthedocs.io/en/latest/ all the documentation. Thanks a lot to Ayoola for sharing her code.






samedi 24 avril 2021

Thermal Image Segmentation with redCV

This  article illustrates how to identify body in thermal images. This code is based on A. Duarte et al. / Procedia Technology 16 (2014) 1560 – 1569. Segmentation algorithms for thermal images paper.

Temperature distribution on the surface of the body or any object can be determined using a method called thermal imaging or thermography. The main advantages of thermography are that it is non-invasive, non-contact, painless and not harmful either to the patients or the medical staff involved. However, thermal images are not easy to process and require specific tools.

According to Duarte's paper, the RGB image model is considered as appropriate for thermal image processing. Colour is a powerful descriptor that simplifies object identification and extraction of a thermograph image.  In the RGB model, the images are segmented by a colour function according to each selected channel. This is easy with Red since thermal images can be loaded as simple ARGB format with A are  the transparency values, R are the red intensities, G are the green intensities whereas B are the blue ones. 

redCV color and zero functions

redCV  includes a useful routine rcvRChannel, that can selectively remove or keep the channel color function. 

So if we remove the Red channel, a zero function is applied to red intensities and the result image only contains Green and Blue intensities, and so on.


Now if we keep the Red channel, the color  function is  kept for Red intensives and the zero function is applied to  Green and Blue channels. It is a fact that the human skin tends to have predominance of red and non-predominance of blue or green, therefore the first step consists in applying the  zero function on the image  to remove the blue and green intensities. Destination image only contains  Red intensities.



redCV thresholding function

The next step now is to segment  the body from the background in image.  Thresholding segmentation algorithms define the boundaries of the images that contain solid objects on a contrast background. This technique gives a binary output from a grey scale image. This method of segmentation applies a single fixed criterion to all pixels in the image simultaneously. The method consists of the selection of an adequate threshold value T, which is a converted binary image from a grey level image. The advantage of getting a binary image is that it simplifies both the complexity of the data and the process of recognition and classification.

This is really easy with redCV, since we can use the rcvThreshold function which transforms  any image to a binary image. In rcvThreshold function, images are automatically converted to grayscale image  before any thresholding.  To mathematically describe rcvThreshold function, a threshold image is defined with a pixel labelling where label 255 corresponds to the object and 0 corresponds to the background. 
The mask image can be defined as a function f(x, y) whereas the threshold image g(x, y) can be defined as follows:
g (x,y) = 255, f (x,y)> T or
g (x,y) = 0, f (x,y) < T
In their publication, Duarte et al. report that the optimal threshold value was found [0.1, 0.4]. In our implementation, we found an optimal threshold value 0.270.

Result

Finally, by using the redCV function rcvAnd, we use a simple pixel by pixel logical And operator with the two images (the original and the mask image)  in order to obtain the result image. 


Result is pretty good and the classical Halo effect observed for most of thermal images is suppressed.  This effect causes the region surrounding a bright object to grow darker and it causes the region around dark objects to grow lighter. This effect can be caused by both the physical operation of cameras containing ferro-electric sensors and back-reflection of IR illumination sources.

redCV not yet updated on GitHub repository 

Code sample

Red [
Title:   "Channel tests "
Author:  "Francois Jouen"
File: %redCVRemoveChannel.red
Needs: 'View
]

{based on A. Duarte et al. / Procedia Technology 16 (2014) 1560 – 1569
Segmentation algorithms for thermal images}

;required libs
#include %../../libs/core/rcvCore.red

isFile: false
margins: 10x10
gSize: 256x256
thresh: 1

loadImage: does [
isFile: false
canvas0/image: canvas1/image: canvas3/image: canvas4/image: none
tmp: request-file 
if not none? tmp [
simg: load tmp   ;--source image
dimg: make image! reduce [simg/size black];--destination image
mimg: make image! reduce [simg/size black];--mask image
rimg: make image! reduce [simg/size black];--final result image
canvas0/image: simg
sl/data: 0%
isFile: true
process
]
]

process: does [
if isFile[
case[
r1/data [rcvRChannel simg dimg 1]
r2/data [rcvRChannel simg dimg 2]
r3/data [rcvRChannel simg dimg 3]
r4/data [rcvRChannel simg dimg 4]
r5/data [rcvRChannel simg dimg 5]
r6/data [rcvRChannel simg dimg 6]
]
canvas1/image: dimg
]
]

process2: does [
if isFile [
rcvThreshold/binary dimg mimg thresh 255;--mask 0 or 255 
rcvAnd simg mimg rimg ;--And source  and mask 
canvas3/image: mimg
canvas4/image: rimg 
]
]

;***************** Test Program ****************************
view win: layout [
title "Thermal images segmentation with redCV"
origin margins space margins
button 60 "Load" [loadImage]
text 100 "Remove Channel"
r1: radio 30 "R" [process]
r2: radio 30 "G" [process]
r3: radio 30 "B" [process]
text 100 "Keep Channel"
r4: radio 30 "R" [process]
r5: radio 30 "G" [process]
r6: radio 30 "B" [process]
sl: slider 255 [thresh: 1 + to-integer (face/data *  254)  
  f/text: form to-float face/data
  process2]
f: field 40 "0.0" 
pad 140x0
button 60 "Quit" [Quit]
return
text 256 "Source" text 256 "Destination" 
                text 256 "Mask" text 256 "Result"
return
canvas0: base gSize black canvas1: base gSize black
canvas3: base gSize black canvas4: base gSize black
do  [r1/data: true]
]