Professional Documents
Culture Documents
Final Master Thesis K D Van Kempen
Final Master Thesis K D Van Kempen
Supervisors:
Dr. M. Rücker
Eindhoven, 08/10/2021
Master Thesis; K.D. van Kempen
Abstract
Wettability is an important parameter for the analysis of multiphase flow in porous media, which describes
the interactions between the medium and the fluids.
In order to characterise this wettability, several length scales need to be considered, from molecular inter-
actions to the macro scale behaviour, which all have their own influence on the wettability of a medium.
On these length scales, several properties can be determined, such as interfacial tension, contact angles and
capillary pressure-saturation curves.
However several studies are performed on porous rocks to find these properties at different length scales and
attempt to relate the different characteristics, studies on foams mostly only focus on the fabrication and
macro-scale behaviour of these foams.
Here, the pore-scale wettability of a coated PESPU foam is analysed from X-ray computed tomography
(CT) images by manual observations and the calculation of in-situ contact angles. These results are then
compared to the macro-scale behaviour to bridge this gap in the characterisation of foam wetting.
On the macro scale, Amott spontaneous imbibition tests gave an impression of the macro scale behaviour
of the foam. On the pore scale, X-ray computed tomography images enabled observations on the pore scale
wettability and an algorithm was developed to compute the in-situ contact angles of the foam-water-oil
system from these images.
It is shown that these techniques are applicable for foams and enable a deeper understanding of foam wet-
tability on the multiple scales. Thereby, the results obtained here indicate that using these experimental
methods can provide more details on the wetting of a foam and therefore influence on the interpretation of
wettability.
In a broader sense, this study found that the wetting experiments on multiple length scales as used in rock
studies can and should also be used to characterise the wettability of other porous materials and provide
much more in-depth insights on this wettability. Thereby, this study provides a framework on how to develop
such experiments and overcome the obstacles in these experiments that arise from the differences between
the used porous materials.
i
Master Thesis; K.D. van Kempen
Contents
List of Symbols iii
1 Introduction 1
2 Background 2
2.1 Wetting theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2 Experimental characterisation of sponges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3 Experimental characterisation of porous rocks . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4 Results 21
4.1 Amott tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.2 Pore-scale observations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.3 Advanced image analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.4 Pore-scale contact angles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.5 Overall discussion on wettability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5 Conclusion 36
5.1 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.2 Outlook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Bibliography 37
ii
Master Thesis; K.D. van Kempen
List of Symbols
Symbol Variable Unit
A Area m2
c Concentration M or mol/l
κ Permeability m2
p Pressure Pa
pc Capillary pressure Pa
Q Volumetric flowrate m3 /s
γ Interfacial tension N/m or J/m2
µ Viscosity Pa · s
o
θ Contact angle (degree)
ρ Density kg/m3
iii
Master Thesis; K.D. van Kempen
1 Introduction
Since oil spills pose a significant environmental threat, it is important to clean them up as efficiently as
possible. Traditionally, the techniques to clean up these spills also pose a potential environmental risk,
since they either require a lot of work or use toxic chemicals[9]. Thereby, most traditional techniques are
rather costly [9, 12]. In addition, traditional techniques are often unable to clean up small oil droplets[6, 12].
To resolve these issues, an increasing amount of studies focuses on the development of surface engineered
sponges (SEnS) for the removal of oil from water [7, 11, 20, 23, 32], as such sponges might pose a cheap and
durable solution for the cleanup of oil spills or separation of oil from other contaminated streams.
In order to be able to fully understand the wetting and flow phenomena in a sponge, or any porous material,
several factors need to be considered on a wide variety of length scales, namely:
• Molecular interactions
• Nano-scale roughness
• Pore-scale structure/geometry
• Macro scale behaviour
As most studies on sponges are aimed at the the development of SEnS, they mainly focus on molecular
interactions in order to design a suitable coating for the sponge. Besides this, analyses are often performed
to determine the stability of the applied coatings and determine the macro-scale sorption and separation
performance of the sponge. Although some studies briefly mention the influence of processes on the interme-
diate scales, only few studies have been found that actually address the influence of the pore scale structure
or nano-scale roughness in relation to the sponge wetting [11].
In contrast to studies on sponges, wettability studies on porous rocks do tend to consider all mentioned
length scales. Wettability in porous rocks is subject to extensive research, as this is of major importance
to oil production and subsurface CO2 storage. In these studies, macro-scale experiments remain important,
but an increasing amount of studies address the various lower length scale processes.
In this study, this gap in the wettability analysis of foams is bridged by analysing the wetting of a foam as
developed by Cherukupally et al.[12] from the pore-scale perspective using CT digital rock imaging tech-
niques. This data is then compared to measurements on the macro scale by analysing the in-situ contact
angles and fluid distributions of the sponge-decane-water system.
This thesis will firstly discuss the theory behind wetting from the various length scales and the related
experimental techniques. After this, the experimental techniques used in this study will be further explained
and the results will be presented. Finally, these results will be discussed to come to a final conclusion on the
wettability of the foam and the relevance of employing pore-scale techniques.
1
Master Thesis; K.D. van Kempen
2 Background
In order to provide the reader with sufficient prior knowledge on the theory behind wetting, this chapter will
discuss the theoretical background behind wetting. Thereby, the various experimental techniques that are
often performed to analyse this wetting in practice will be discussed.
• Molecular scale;
• Subpore scale;
• Pore scale;
• Macro scale.
On each of these scales, different physical processes can be identified that determine the behaviour on this
scale. Eventually, all these processes will amount to the total wettability of a medium. A graphical overview
of these length scales and relevant parameters can be seen in Figure 2.1 (copied from Rücker [25]). In the
following sections, the details of each length scale in relation to wetting will be discussed.
Figure 2.1: A graphical illustration of wetting on the multiple length scales. Copied from Rücker [25].
2
Master Thesis; K.D. van Kempen
molecular interactions often form the most important design step in the choice of a suitable coating in the
design of SEnS.
Figure 2.2: Example of a force-distance curve for the interactions between two individual molecules(a) with
an indication of the governing forces on those distances(b). Copied from Rücker [25] (who adapted part b.
from Raina[24]).
3
Master Thesis; K.D. van Kempen
(b) Sketches of an oil droplet on a water-wet (left), intermediate wet (middle) and oil-wet (right) surface, illustrating
the different wetting regimes and corresponding contact angles.
Figure 2.3: Some sketches illustrating the intrinsic contact angle and wetting regimes.
In reality, a perfect situation as just described can never exist, which is caused by multiple things. On the
subpore scale, the most important causes for this are surface roughness and chemical heterogeneity. Even
for seemingly flat surfaces, there might still be roughness on lower scales. As a result of this roughness, a
distinction needs to be made between the intrinsic and apparent contact angle. As illustrated in Figure 2.4
the apparent contact angle will be different from the intrinsic contact angle when the surface roughness is not
sufficiently resolved. This effect of surface roughness is described by Wenzel[33], who related both contact
angles directly to roughness:
cos (θ∗ ) = r cos (θi ) (2.2)
where r is the surface roughness as described by
Areal
r= (2.3)
Aprojected
with actual surface area Areal and apparent surface area Aprojected . This latter surface area is the surface
area assuming it would be perfectly flat. As a result of this, surface roughness will make the wetting state
of a system to appear more strong than it is, as the contact angle will lean more towards 0 or 180 degrees
for a water-wet and an oil-wet system respectively.
4
Master Thesis; K.D. van Kempen
Figure 2.4: Illustration on the effect of surface roughness on the apparent and intrinsic contact angle. In a.
a droplet is shown on a rough surface, where the apparent contact angle is θa . In b. the intrinsic contact
angle is shown, which is only seen when the image resolution is high enough to resolve all surface roughness.
Images c. to e. illustrate how pinning on a sharp edge can cause different fluid configurations to be able to
exist, while having the same contact angle. Copied from Rücker[25].
Besides having a different apparent and intrinsic contact angle, surface roughness and chemical heterogeneity
can both lead to a process called ’pinning’. This pinning constrains the triple line of a droplet in place.
Imagine a situation where the triple line is pinned and a droplet grows, shrinks or is imposed to external
flow. Without pinning, all these things would cause the triple line to move, so that the contact angle would
remain the same. However, when the triple line is pinned, it is prohibited to move up to a certain threshold.
Therefore, the contact angle is subject to hysteresis, which leads to the definition of an advancing and
receding contact angle. In order to illustrate this, imagine a droplet on a tilting surface as illustrated in
Figure 2.5. When the surface is tilted, the droplet will be pulled down by gravity, forcing it to slide down the
surface. However, when the triple line is pinned, it is prohibited to move. Therefore, the droplet will stay
in place, but will deform under the influence of gravity. As a result of this, the contact angle at the lower
part of the droplet will decrease and the contact angle at the higher part of the droplet will increase. These
contact angles will keep increasing/decreasing up to the point where the pinning is not strong enough any
more and the droplet will start to slide. At this point, the advancing (θa ) and receding (θr ) contact angles
are defined, which are the lower and upper bounds for the contact angle respectively. As stated, the same
advancing and receding contact angles can be observed when droplets grow or shrink (in which case there
will only be an advancing or receding contact angle respectively) or when a droplet is exposed to a flow of
the surrounding fluid.
Water θr
Oil
θa
Tilted surface
Figure 2.5: Sketch of an oil droplet on a tilted surface, illustrating the advancing and receding contact angle.
5
Master Thesis; K.D. van Kempen
pc = pnw − pw = σκ (2.4)
where pc is the capillary pressure, pnw is the pressure of the nonwetting fluid, pw is the pressure of the
wetting fluid, σ is the interfacial tension between both fluids and κ is the mean curvature of the fluid-fluid
interface. For the narrow tube as just described, the curvature of the fluid-fluid interface is given by the
contact angle and radius of the tube. When a steady state is considered for this situation, the capillary
pressure is 0, so the attraction of the water by the tube walls is balanced by the gravity acting on the water.
The height of the water column is now given by
2σ cos (θ)
h= (2.5)
∆ρgr
where θ is the contact angle, which is here defined as the angle between the fluid meniscus and the tube
walls, ∆ρ is the difference in density between the water and air, g is the gravitational acceleration and r is
the radius of the tube.
Figure 2.6: Illustration of capillary rise when a narrow, water wet tube is placed into a water tank.
Where the illustration of a narrow tube in a water tank is a nearly trivial situation, porous media are much
more complicated. However, the same basic principles of capillary action are relevant on the pore scale of
porous materials. In fact, porous materials can be considered as complicated networks of capillary tubes of
various lengths and radii. Accordingly, wetting on the pore scale mainly depends on the internal structure of
the porous medium and the fluid distributions. One way to describe the characteristics of the pore structure
are the four Minkowski functionals, which are volume, surface, mean curvature and Gaussian curvature [4].
For the assessment of wettability of a porous medium, these Minkowski functionals can be interpreted as
saturation, interfacial surface area between the phases and the curvatures of the fluid-fluid interfaces. For
6
Master Thesis; K.D. van Kempen
the curvatures, the mean curvature is a measure for the capillary pressure as described in Equation 2.4 and
the Gaussian curvature is a measure for connectivity of the phases. Figure 2.7 shows a graphical illustration
of these Minkowski functionals in a porous medium.
Figure 2.7: Graphical illustration of the four Minkowski functionals in relation to wetting of porous media.
Besides the four Minkowski functionals, contact angles also remain an important measure for wettability
on the pore scale. A first analysis of contact angles on the pore scale was from CT images reported by
Prodanović et al. Later, Andrew et al.[3] further elaborated on the procedure and Klise et al.[19] was the
first to automate the in-situ contact angle calculation from CT data. Later, the automatic contact angle
calculation was further improved by Scanziani et al.[28]. As explained on the subpore scale, these contact
angle measurements will not result in a single value for the contact angle, but rather a range of contact
angles, as real world systems are always subject to contact angle hysteresis.
7
Master Thesis; K.D. van Kempen
Figure 2.8: A typical result of an imbibition test. Copied from Falode and Manuel[15].
Another kind of experiments on the macro scale is related to the assessment of flow through porous rocks.
In the most simplified situation with a single phase flow, this flow is described by Darcy’s law, stating
Q κ
=q= ∆p (2.9)
A µL
Where Q is the volumetric flowrate through a sample, A the cross-sectional area of the sample, κ is the
permeabilty, µ is the viscosity of the fluid, L is the length of the sample and ∆p is the externally imposed
pressure drop over the sample. When a multi-phase flow is considered through a porous medium, Darcy’s
law can be rewritten to
ki κ
qi = ∆p (2.10)
µi L
where ki is the relative permeability of a phase and i denotes the phase under consideration. Accordingly,
the second important relation for wetting on the macro scale are relative permeability - saturation rela-
tions. These relations describe how the relative permeabilities in a multi-phase flow situation depend on the
saturation, as illustrated in Figure 2.9.
8
Master Thesis; K.D. van Kempen
Figure 2.9: An example of a relative permeability - saturation relation. Adapted from Blunt[10].
Wetting characterisation
In order to determine the wetting behaviour of the sponges, studies usually revert to optical contact angle
measurements [7, 11, 12, 20, 23, 32]. In order to determine this contact angle, a droplet of oil or water
is placed onto the sponge and the contact angle is determined by the angle between the sponge surface
and the tangent of the droplet near the sponge surface. In Figure 2.10, the results of such a contact angle
measurement as reported by Li et al.[20] are shown. Clearly, the sponge in (d) is much more hydrophobe
than the sponge in (a), because the contact angle is much closer to 180o . Thereby, the video snapshots
clearly show that the modified sponge absorbs the oil droplet much faster than the non-modified sponge.
What is important to notice here, is that this is the contact angle for the sponge-oil-air system, which does
not correspond to the situation when the sponge is in operation (which would typically be a sponge-oil-water
system).
9
Master Thesis; K.D. van Kempen
Figure 2.10: Example of contact angle measurements as reported by Li et al.[20] for the water contact
angle on a non-modified sponge (a) and some differently treated sponges(b-d) and video snapshots of the oil
absorption on the non-modified (e) and modified(f) sponge. Copied from Li et al.[20]
Sorption performance
Apart from measuring the contact angles to quantify the wetting, another set of experiments is often conduc-
ted to test the actual oil removal performance of the sponge. In order to get a better understanding of the
oil sorption performance of the sponge, there are two main experiments that are used. The first experiment
that is done in most studies is to submerge the sponge in an emulsion of oil in water for a while. During
this experiment, the emulsion is continuously stirred and at specific time intervals, a sample is taken of the
emulsion to see how much oil has been absorbed by the sponge. This experiment enables to determine the
sorption kinetics of the sponge and the total maximum oil uptake of the sponge [11, 12]. An example of the
setup used in such an experiment as reported by Cherukupally et al.[11] can be seen in Figure 2.11.
Figure 2.11: A sketch (a) and an image (b) of a setup to measure the sponge kinetics and maximum oil
uptake by submerging the sponge into an oil in water emulsion as reported by Cherukupally et al.[11].
The other experiment that is often done is to determine the selectivity of the sponge. In order to determine
the selectivity of a sponge, there are multiple methods that are proposed by different studies. In both studies
by Cherukupally et al.[11, 12], the mass uptake of pure oil and water is measured for the sponge in order to
draw a conclusion on the selectivity. In Barry et al.[7] and Li et al.[20], a beaker is filled with water and oil,
which are not mixed, and the sponge is placed onto the fluid surface. After the sponge has taken up the oil,
it is emptied and the amount of water and oil that have been taken up are compared to draw a conclusion on
the selectivity. Some images of this, as reported by Li et al. can be seen in Figure 2.12a. Lastly, Wang et al.
[32] reports two other ways to determine the selectivity of the sponge, which are significantly more elaborate.
Firstly, Wang et al. report an experiment where an oil-water mixture is poured over the sponge. In this
experiment, the oil will be absorbed by the sponge and will eventually fall down in a beaker underneath it as
the sponge gets saturated. Since the water is expected to not wet the sponge, it will flow over the surface of
10
Master Thesis; K.D. van Kempen
the sponge as if it were a channel, so that it will end up in a beaker next to the sponge. Again, the amount
of oil in the water beaker and the amount of water in the oil beaker will give an impression of the selectivity
of the sponge. Images of this experiment as reported by Wang et al. can be seen in Figure 2.12b.
The second method mentioned by Wang et al. is to connect the sponge to a vacuum pump and then submerge
it into an emulsion of oil in water. Now, only the oil should be able to pass through the sponge and the
selectivity of the sponge can be found by assessing whether any (or how much) water has passed through
the sponge. Images of this experiment as reported by Wang et al. can be seen in Figure 2.12c.
A last experiment that is often conducted with respect to the performance of sponges is to test to what
extent the sponge can be reused [11, 12, 20, 23]. In order to test this, the sponges under consideration
are cleaned and put in the oil-water emulsion again to see whether, and to what extent, the sponge can be
reused.
As can be seen from these experiments, most studies on sponges have a strong emphasis on the design or
modification of the desired sponge and are less concerned with the actual wetting characterisation of the
sponges.
11
Master Thesis; K.D. van Kempen
(a) Images of the selectivity experiment procedure as reported by Li et al.[20], with (a) the sponge
and a beaker with water and (dyed) oil; (b) the sponge being placed onto the fluid surface; (c) the
sponge being removed from the beaker after absorbing the oil and (d) the oil has been squeezed out
of the sponge into another beaker.
(b) Images of the first selectivity experiment as reported by Wang et al.[32], with blue dyed water
and red dyed oil. Clearly, the red oil falls into the left beaker and the water flows into the right
beaker.
(c) Images of the second selectivity experiment as reported by Wang et al.[32], where the red dyed
oil is clearly separated from the emulsion.
Figure 2.12: Several experiments that are used to draw a conclusion on teh selectivity of a sponge as reported
in literature
12
Master Thesis; K.D. van Kempen
understanding of the wetting behaviour, many recent studies use X-ray micro-computed tomography (µ-CT)
to perform in-situ measurements of the rock structure and fluid distributions [3, 17, 18, 21, 28, 29, 30, 31].
Besides this, some studies focus on the influence of nano-scale roughness by performing AFM measurements
[13, 26, 27, 34].
13
Master Thesis; K.D. van Kempen
(a) Example of a measurement setup for a micro-CT (b) Raw (left), filtered (middle) and segmented (right) CT
measurement with a flow cell at elevated pressure as images as reported by Singh et al.[30].
reported by Lin et al.[21].
(c) An example of the measured in-situ contact angles in a water-wet (left) and mixed-wet
(right) rock sample as reported by Scanziani et al.[28].
Figure 2.13: A sketch of a CT measurement setup with a flow cell as reported by Lin et al.[21] (a), some
resulting CT images as reported by Singh et al.[30] (b) and an example of the measured in-situ contact
angles as reported by Scanziani et al.[28](c).
14
Master Thesis; K.D. van Kempen
15
Master Thesis; K.D. van Kempen
of various hydrocarbons, thus a similar behaviour is expected. However many other studies use decane as
a model oil [1, 5, 8, 16, 17, 25, 28, 30], this has not been chosen in this study. The reason for this is that
Cherukupally is currently also performing experiments on the sponge with dodecane and it is deemed more
important to be consistent with this study. Besides this, dodecane and decane are expected to behave nearly
exactly the same, as the only difference is the slightly longer carbon chains in dodecane. The only relevant
difference between dodecane and decane for this study will be a slightly higher viscosity of dodecane.
When performing the Amott test, the larger end is first filled with dodecane before the sample is placed in
there. It is important to obey this order, as pouring the dodecane over the sponge when it is already in the
reservoir has two major consequences. Firstly, the sponge loses the absorbed water rather quickly when it
is taken out of the water. This way, the sponge would not be fully saturated with water any more, but also
contain air, which would corrupt the experiment. Secondly, having to pour the dodecane in the reservoir
after the sample is placed would cause a higher pressure on the sponge, so that there would be some forced
imbibition at the start of the experiment. When the sponge sample is placed into the Amott cell, the narrow
end is mounted and the rest of the cell is filled with dodecane. As the sponge is already submerged, no fluids
are poured directly onto the sponge now, so there is no more risk of forced imbibition. Lastly, the Amott
cell is placed upside down, so that the amount of water production can be measured, which is denser than
dodecane.
One downside of the Amott test as used here is that the graduations at the narrow end of the Amott cell
only start somewhat past the lid. Due to this, a known amount of water needs to be added at the start of
each Amott test to correct for this part of the cell where no measurements are possible.
(b) The individual parts of the Amott cell, with the reservoir (top), graduated end (middle)
and sample holder (bottom).
16
Master Thesis; K.D. van Kempen
in this case, the samples will be much smaller (4x4x20 mm). These samples will be analysed by taking X-ray
microcomputed tomography scans (later referred to as (X-ray) CT scans) at set times, which enables to
analyse the fluid distributions within the sponge and extract contact angles.
2D detector
Rotation stage
X-ray production
The X-ray light used in the scanner is produced in a so-called X-ray tube. In this X-ray tube, a metal filament
is subjected to a high voltage (typically in the range of 10-100 kV), which causes it to ’shoot’ electrons onto
a target. When this target is hit by the electrons, it produces the X-ray light used to illuminate the X-ray
CT sample. This target can be made of multiple materials, such as molybdenum (used here) or diamond,
depending on the desired X-ray photon energy.
Used setup
All X-ray micro CT images were obtained using a Phoenix Nanotom s nanoCT scanner. The obtained
voxel size was 2.3 µm. In order to obtain the best image quality, several parameters can be changed, from
the energy and power of the X-rays to adding contrast agents to the fluids. The optimal configuration
was determined by visually inspecting either single transmission images or full CT scans. The transmission
17
Master Thesis; K.D. van Kempen
images were used, because they can already provide a good interpretation of the contrast in the scan, without
having to make a full CT scan, which takes much more time.
X-ray CT parameters
The first important parameter that needs to be chosen is the tube voltage in the CT scanner. This tube
voltage will determine the photon energy of the X-rays, where a higher voltage will result in a higher photon
energy (or ’harder’ X-rays). When the X-rays are harder, the X-ray attenuation will be lower. Therefore,
the tube voltage will have to be high enough, so enough signal is obtained at the detector. As the sponge
samples here are made of a relatively low-density plastic, their X-ray attenuation is rather low. Therefore,
the tube voltage might also not be too high, because this would result in a poor contrast of the sponge
material. Here, a tube voltage of 60 kV is used.
The next important parameter is the tube current. This tube current determines the amount of X-ray
photons produced per unit time and thus determines the X-ray power. This tube current is simply set as
high as possible to obtain the maximum possible signal. However the highest possible tube current is chosen,
there is again a trade-off with another setting, which is the spot size. This spot size determines the size of
the X-ray source, where a larger spot will result in more power, but a lower resolution. The CT scanner
used here has 4 spot sizes, which are 0(big), 1 (medium), 2(small) and 3(smalllest). In this study, spot 1 has
been chosen, as this spot size allows sufficient X-ray power, but a small enough resolution. The maximum
tube current in this setting is 240 µA, which results in a power of 14.4 W.
When all X-ray parameters are set, the detector settings can be adjusted. Firstly, the detector time needs to
be set. The detector time is the time over which the detector takes a single image and thus determines the
amount of signal. The larger the X-ray power is, the lower the detector time can be, so a lower amount of
time is needed to obtain a full CT scan. On the other hand, a higher detector time results in a higher signal
level and a lower noise level. Since the tube voltage here is rather low and the fluids around the sample will
cause some signal loss, the detector time here is set rather high, at 1500 ms.
Besides the detector time, the amount of images taken at each rotation position can be set. As for the
detector time, a lower amount of images will result in a lower time for the CT scan, but a higher amount of
images will result in a lower noise level. In this study, it has been chosen to use 8 images at each rotation
position.
Contrast agents
Besides the X-ray and detector settings, there is one other parameter that can be changed with respect to
the acquisition of CT images, which is the use of contrast agents. As a CT scan relies on the difference in
X-ray attenuation of different materials, all materials must have a sufficiently different X-ray attenuation to
provide contrast in the CT scan. When materials have a too similar X-ray attenuation, contrast agents can
be added to change this. It is important to notice that these contrast agents can only increase the X-ray
attenuation of a fluid. Another important realisation is that adding a contrast agents can change the results
of the experiment, as other chemicals are introduced.
In this study, 0.1 M potassium iodide (KI) has been added to the water, instead of the 0.1 M NaCl as used in
the Amott test. This concentration has been chosen, as it provides a good contrast in the image, while also
corresponding to the salt concentration as used in the Amott test. As the salt concentrations are identical,
the difference in behaviour between the two experiments should be minimised. The KI might still behave
differently than the NaCl, but it is required to obtain enough contrast. Thereby, the main potential influence
of adding salts to the water is expected to be caused by the formation of a so-called DLVO layer, which is
a double layer of counter-ions that might form at the water-sponge interface. As this layer only depends on
the concentration and charge of the ions, which are identical for the KI and NaCl, the influence of changing
NaCl for KI is expected to be low.
18
Master Thesis; K.D. van Kempen
grayvalue. From this CT image of the sponge and the fluids, observations on the wetting state of the sponge
can be made and contact angles can be calculated.
In this study, the CT scans are performed after a large enough amount of time, to ensure a steady state fluid
distribution. Imaging any dynamic conditions is outside the scope of this study.
Sample holder
As a CT scan relies on the reconstruction of a 3D volume from the 2D transmission images at several rotation
positions of the sample, it is of vital importance that the sample does not move or deform during the image
acquisition. In order to constrain the sponge during image acquisition, it is placed into a sample holder that
is specifically designed for imaging porous samples under wet conditions. This sample holder was developed
by Bartels et al. [8] and consists of a 3D-printed sample holder that is placed inside a tube that may contain
fluids. Some images of the sample holder can be seen in Figure 3.3.
However the sample holder was designed for the analysis of porous samples under wet conditions, Bartels
et al. used the sample holder to study (Ketton) rock samples, which poses some significant differences to
this study, which should be discussed. Firstly, rock samples have a high stiffness, or can even be considered
incompressible, whereas the sponge samples used here can simply be squeezed. As a result of this, clamping
the samples into the sample holder is no problem for rock samples, but could have a significant effect on the
behaviour of sponge samples, as this clamping might alter the shape and thus the internal structure of the
sponge. In this study, the samples are not much bigger than the clamps of the holder, so the force exerted
by the sample holder on the sponge is rather small and no significant compression is observed. Thereby, the
sponge is only clamped in the middle, so the protruding parts are not affected. Lastly, all sample preparation
actions on the sponge (as soon as it contains any fluid) are performed while the sponge is in the sample
holder, so the structure of the sponge will not change during the experiments.
The second difference between the rocks as studied by Bartels et al. and the sponges studied here is the
wettability of the samples. The rocks as studied by Bartels et al. are all water-wet or mixed-wet, while the
sponges used here are oil-wet. If the fluid inside the sample would be a wetting fluid for the sample holder,
this would mean that the holder could draw out this fluid, which would corrupt the results. Since the sample
holders are made of an oil-wet plastic, this will not pose any problems in this study.
When performing the first experiments with this sample holder, one part of it has been changed, which is
the cylinder at the top that holds the fluids. Since this tube is filled with fluids (dodecane in this case) and
is significantly wider than the sponge sample, all this fluid around the sample will decrease the amount of
transmitted X-ray light and thus significantly decrease the amount of signal that reaches the detector. In
order to reduce this signal loss, a narrower tube has been used in this study (internal diameter of 14 mm
instead of 16 mm).
(a) CT sample holder (b) CT sample holder with the top cylinder re-
when fully assembled. moved, so the sample holder is visble
19
Master Thesis; K.D. van Kempen
20
Master Thesis; K.D. van Kempen
4 Results
With a proper understanding of the performed experiments, the resulting data can be analysed to form a
conclusion on the wetting of the sponge. This section will discuss these results, starting at the largest scales,
as this gives the first impression on the sponge wetting. After this, initial observations on the CT scans
will give a further impression on the wetting of the sponges. Lastly, advanced image analysis can give more
quantitative data on the wetting of the sponge. This quantitative analysis of the CT scans will be split into
two parts, discussing the Minkowski functionals and the in-situ contact angles of the sponge-brine-dodecane
system.
Table 4.1: Difference between the initially added amount of water in the Amott experiment and the first
measurement point.
There are multiple things that might cause the discrepancy between the added amount of water and the
first measurement. Firstly, the first data point is only obtained 2 minutes after the start of the experiment,
because the sponge sample is first placed in the Amott cell, before the narrow end can be mounted and the
rest of the cell can be filled with dodecane. Therefore, the sponge will already have produced some water.
Thereby, the sponge tends to loose any fluid it contains rather quickly in air, so some water might have
dripped out of it while putting it from the water container into the Amott cell.
In case of the second sample, the added amount of water was higher than the first measurement. This might
be caused by water droplets remaining on the sample holder, the cell walls, or between them both after the
Amott cell is flipped.
This discrepancy in the initial water volume is rather big compared to the total produced water volume,
but is not expected to greatly influence the results of the experiment. Once the experiment is started, all
produced water falls into the narrow, graduated end as expected and can be measured. Therefore, the
production over time of the sponge can still be accurately measured. Even when the first two minutes of
production can’t be accurately measured, this influence is considered low, as the entire time scale of the
experiment is much bigger.
21
Master Thesis; K.D. van Kempen
1.4 2
Measured water production [ml]
0.8
1
0.6
0.4
0.5
Sample 1
0.2 Sample 1
Sample 2
Sample 2
0 0
0 50 100 150 200 0 5 10 15 20
Time [h] Time [days]
(a) Produced volume of water in the Amott test dur- (b) Produced volume of water in the Amott test dur-
ing the first 5 days of the experiment. ing the entire experiment.
Figure 4.1: Measured water production in the Amott test over time.
22
Master Thesis; K.D. van Kempen
(a) Transmission image of the (b) Transmission image of the (c) Transmission image of the
sponge using a tube voltage of 50 sponge using a tube voltage of 60 sponge using a tube voltage of 70
kV. kV. kV.
Figure 4.2: Transmission images of the sponge using different X-ray tube voltages and identical window
levelling. All other parameters remain as described in section 3.3.
Considering the other X-ray and detector settings (tube current, detector time, number of images), no
images will be shown, as the influence of these settings is rather trivial. Increasing these other parameters
will simply increase the signal level, reduce the noise level or do both. Besides this, these parameters have
a low influence on the scan, except that the detector settings directly influence the scan time and should be
chosen such that the quality is sufficient.
The last scan parameter is the amount of contrast agent (potassium iodide) added to the water. In Figure 4.3,
three transmission images of the sponge can be seen with no KI, 0.1M KI and 0.3M KI added to the water.
When no KI is added (Figure 4.3a), there is no contrast between the sponge fibres and the brine. When the
brine is prepared with 0.1M KI instead of NaCl, the sponge fibres can be seen in the sponge. When 0.3M KI
is added, the contrast between the sponge and brine seems to decrease. One striking observation here is the
way the contrast between the sponge and brine seems to improve when 0.1M KI is added. As the iodide ions
have a high molar mass, adding the KI to the water should increase the X-ray attenuation of the water. As a
result of this, the water in Figure 4.3b should be darker than the water in Figure 4.3a, while the sponge fibres
keep the same X-ray attenuation. However, when assessing the images, the sponge fibres appear darker than
the brine when 0.1M KI is added and thus have a higher X-ray attenuation. This indicates that the sponge
must have absorbed iodide ions from the brine, which is not expected. As the sponge is designed to absorb
oil, which mainly consists of nonpolar fluids, it would be expected to repel charged particles. The absorption
of iodide ions here thus indicates that the sponge might not be as oil-wet as expected from the data as
presented by Cherukupally et al.[12]. Upon asking about this behaviour, Cherukupally clarified that the
sponge indeed contains other active sites such as chlorine, carboxylic, and amine groups. As a result of this,
it is possible that the sponge fibres absorb the iodide ions, or that chlorine atoms in the sponge are replaced
with iodide. A more detailed chemical characterisation of the sponge is currently done by Cherukupally to
validate this assumption. This absorption of iodide ions by the sponge fibres also explains why the contrast
between the brine and sponge material gets worse for 0.3M KI, as now the sponge fibres don’t take up any
more iodide ions, but the X-ray attenuation of the brine does still get higher.
23
Master Thesis; K.D. van Kempen
(a) Transmission image of the (b) Transmission image of the (c) Transmission image of the
sponge without any contrast sponge with 0.1M KI added to the sponge with 0.3M KI added to the
agents. water. water.
Figure 4.3: Transmission images of the sponge using different X-ray tube voltages, where the window levelling
on each individual image is changed to obtain the best contrast. All other parameters remain as described
in section 3.3.
24
Master Thesis; K.D. van Kempen
(a) Horizontal slice of a CT scan of the the SEnS (b) Vertical slice of a CT scan of the the SEnS after
after imbibition under optimal conditions. imbibition under optimal conditions.
(c) 3D view of a CT scan of the the SEnS after imbib- (d) 2D image slice with a droplet, illustrating the
ition under optimal conditions. The view is cropped existence of membranes below the image resolution.
with a cylinder to eliminate the bright circle that
can be seen in the horizontal plane. Thereby, the
low graylevel pixels are set transparent, so that the
dodecane surrounding the sponge is transparent.
Figure 4.4: Examples of a horizontal (a) and vertical (b) image slice and a 3D view (c) of a CT scan of
the SEnS under optimal conditions and a 2D slice illustrating the existence of membranes below the image
resolution (d).
Knowing the characteristics which are found in all CT scans, the scans can be further analysed to assess
the wettability of the sponge. Firstly, images for the SEnS and the uncoated PESPU sponge are compared.
Figure 4.5 shows two horizontal slices of the SEnS (left) and the uncoated PESPU sponge (right) after 1
day of imbibition. A first important observation is the difference in contrast between the sponge and brine.
In the scan of the uncoated PESPU sponge, the sponge fibres can hardly be distinguished from the brine.
Moreover, if the fibres in the uncoated PESPU sponge are visible, they appear darker than the brine instead
of brighter. This indicates that, in contrast to the SEnS, the uncoated PESPU sponge does not absorb any
iodide ions. However this is not a direct observation on the wettability of the sponge in relation to oil, it does
indicate that the SEnS has a higher attraction to charged (or polar) substances. As oil is mainly nonpolar,
this would imply that the SEnS is less oil-wet than the uncoated PESPU sponge. As the contrast in the
scans of the PESPU sponge is too poor for a proper segmentation of brine and sponge material, no advanced
image analysis is possible on this data.
When comparing the distribution of oil and water within the uncoated PESPU sponge, the wetting seems
rather heterogeneous. The sponge does get imbibed with dodecane, but some water droplets remain in the
sponge. Even more so, the remaining water droplets reside in areas with higher curvature. Since capillary
pressure is higher in areas of high curvature, the wetting fluid is expected to reside here, which is an even
stronger indication of mixed wettability of the uncoated PESPU sponge. In the SEnS, some remaining water
droplets are found as well (none visible in the image), but the number of water droplets is significantly lower.
25
Master Thesis; K.D. van Kempen
Thereby, if any water droplets are left behind here, they appear to reside less often in areas with higher
curvature. Contrarily, the SEnS does appear to contain some brine films near the fibres, which indicates a
water-wet situation.
(a) Horizontal slice of a CT scan of the the SEnS (b) Horizontal slice of a CT scan of the uncoated
after 1 day of imbibition under optimal conditions. PESPU sponge after 1 day of imbibition under op-
timal conditions.
Figure 4.5: Horizontal slices in the top parts of the SEnS (a) and uncoated PESPU sponge (b) after 1 day
of imbibition to obtain a first indication of the difference in wettability.
Another comparison can be made between the wetting state of the SEnS under optimal and suboptimal
conditions. Figure 4.6 shows two images of the SEnS after 1 day of imbibition under optimal conditions
(left, pH of brine is 5.6) and suboptimal conditions (right, pH of brine is 7). These images show a significant
difference in wettability, where the suboptimal conditions indeed show many more remaining water droplets
onto the sponge surface. Thereby, these water droplets are rather small (for example, much smaller than
in the uncoated PESPU sponge), which indicates a higher capillary pressure and thus a more water-wet
situation. This is consistent to the study by Cherukupally et al. [11].
(a) Horizontal slice of a CT scan of the SEnS (b) Horizontal slice of a CT scan of the SEnS after
after 1 day of imbibition under optimal conditions 1 day of imbibition under suboptimal conditions
(pH=5.6). (pH=7).
Figure 4.6: Horizontal slices in the top parts of the SEnS using a brine with a pH 0f 5.6 (a) and 7 (b) after
1 day of imbibition.
26
Master Thesis; K.D. van Kempen
27
Master Thesis; K.D. van Kempen
(a) Horizontal slice of a CT scan of the SEnS, il- (b) Small part of a horizontal slice of a CT scan of
lustrating the gradual increase in image brightness the SEnS, illustrating the relatively high noise level
towards the outside. and small sponge features that undermine the use of
a thresholding or watershed image segmentation.
Figure 4.7: Images illustrating why traditional segmentation techniques are insufficient at segmenting the
obtained CT scans.
(a) Horizontal image slice of a CT scan of the SEnS. (b) Horizontal segmented image slice of a CT scan of
the SEnS.
(c) Detail of a horizontal image slice of a CT scan of (d) Detail of a segmented horizontal slice of a CT
the SEnS. scan of the SEnS.
Figure 4.8: Grayscale (a,c) and segmented (b,d) horizontal image slices of a CT scan of the SEnS with a full
slice (a,b) and a detail of an image slice(c,d). In the full slices (a,b) the field of view is cropped to eliminate
the bright circle that is found in all horizontal image slices.
28
Master Thesis; K.D. van Kempen
Minkowski functionals
Now the image is segmented, further data can be extracted from the CT image files. Firstly, the four
Minkowski functionals will be discussed, starting with the saturation. However saturation seems like a
straightforward measurement from a macro scale point of view, this is a rather challenging measurement on
smaller scales. On a macro scale, saturation can simply be defined as the amount of pore volume that is
occupied by a certain phase. On the pore scale, however, the pore volume is not clearly defined, as there
is no clear ’edge’ of the sponge. Due to the high resolution and small volume of the data, the sponge can
no longer be seen as a well-defined object with a certain dimension. As the sponge fibres are very small
and the pore size is much bigger, the sponge should now be considered a large structure of fibres, which are
surrounded by fluids. Therefore, no clear outer boundary of the sponge can be defined. In order to be able
to still derive the saturation of the sponge, a rectangular box is manually defined, such that it wraps around
the sponge in the most suitable way. An example of how this box was defined is shown in Figure 4.9. As a
result of this, the saturations found here are highly dependent on the user input and the resulting saturations
can only be used as an indicative measure for wettability. Another important realisation here is that the
sponge is hardly ever fully within the field of view of the CT scans. Therefore, a part of the information
on the saturation is missing. This is resolved by the assumption that the sponge is isotropic and perfectly
symmetrical. Using this assumption, the saturation of the sponge can be found by just taking a quarter of
the sponge, as this would be representative for the entire volume.
The interfacial areas between all phases can directly be extracted from Dragonfly and are evaluated over the
same volume as used for the saturations. In order to determine the curvatures of the oil-brine interfaces, the
interface needs to be meshed. This can also be directly done by the Dragonfly software. A major downside
here is that the resulting values for the curvature show a very large range of values (standard deviation is
much more than the mean), even when it is tested on a perfect sphere. The resulting data will still be shown
for completion, but it is important to realise that any conclusions drawn from the values for curvature are
only indicative.
The Minkowski functionals have been determined for the SEnS under under optimal (pH=5.6) and subop-
timal (pH=7) conditions, so that it can be shown that the Minkowski functionals indeed are a good measure
for wettebility. The resulting values are shown in Table 4.2. As can be seen, the residual water saturation is
lower under optimal conditions, indicating a more oil-wet situation.
The same conclusion can be drawn for the interfacial surfaces, where the SEnS under optimal conditions
displays a relatively higher oil-sponge interfacial surface and a lower water-sponge surface compared to the
suboptimal conditions. Still, the water-sponge interfacial surface is much higher than the oil-sponge interfa-
cial surface for both cases. This is caused by the high residual water saturation in the sponge. One important
observation here is that the total interfacial surfaces for both cases are very similar (only a difference of 1.2%)
which indicates the definition of the cropping box is well chosen for both scans.
Also the mean curvature of the oil-brine interfaces support a more oil-wet situation for the optimal con-
ditions, showing a higher curvature for the optimal case. As defined by Equation 2.4, a higher curvature
directly indicates a higher capillary pressure and thus a stronger wetting.
Lastly, the Gaussian curvature needs to be discussed. For the Gaussian curvatures, the values are very high.
The reason for these, seemingly odd, values can be found in the significance of the Gaussian curvatures. As
explained in section 2.1, the Gaussian curvature is a measure for connectivity. However, the connectivity
of the fluid layers in all CT scans is trivial, as both the water and the oil mainly appear as single volumes.
Indeed, some residual water droplets are found in the scans, but the vast majority of water exists as a single
bulk in the sponge. Therefore, the significance of the Gaussian curvatures is negligible.
29
Master Thesis; K.D. van Kempen
Table 4.2: The minkowski functionals as found for the SEnS under optimal (pH=5.6) and suboptimal (pH=7)
conditions.
pH 5.6 pH 7
Residual water saturation [-] 0.57 0.62
Interfacial areas [mm2 ] Oil-brine 13.78 (20.0%) 12.75 (18.3%)
Oil-sponge 12.99 (21.5%) 11.02 (15.8%)
Water-sponge 42.12 (61.1%) 45.94 (65.9%)
Total 68.89 69.71
Mean mean curvature [mm−1 ] 20.13 13.91
Mean Gaussian curvature [mm−1 ] 1.200 · 109 0.747 · 109
(a) A horizontal image slice illustrating how the crop- (b) A vertical image slice illustrating how the crop-
ping box for the determination of the saturation was ping box for the determination of the saturation was
defined. defined.
Figure 4.9: A horizontal (a) and vertical (b) image slice illustrating how the cropping box for the determin-
ation of the saturation was defined. The box is shown as the white rectangle in the images.
30
Master Thesis; K.D. van Kempen
the grey part is the water droplet. Like before, all is surrounded by oil, which is set transparent to be able to
see the droplet. On important realisation here is that Dragonfly uses linear interpolation of voxels to make
the image appear more smooth. Therefore, it might appear as if the sponge fibre is covered with a water
film, which is not the case. The surface only appears grey due to the interpolation with the oil voxels (which
are set transparent here, but are still incorporated in the interpolation).
Figure 4.10: An illustration of a water droplet (grey) onto a sponge fibre (white), with the triple point voxels
marked in blue. For illustrative purposes, the image is cropped by a plane halfway through the droplet, so
the triple line is better visible there. All oil voxels are set transparent.
Figure 4.11: An illustration of how the oblique slices are extracted from the volume. The extracted image
slice is shown and the grey handle on the image slice indicates that the normal of the plane is in the direction
of the triple line (blue). These oblique slices are perpendicular to the triple line and will form the image
planes from which the contact angle is found.
31
Master Thesis; K.D. van Kempen
(a) An illustration of how the interfaces are fitted. (b) A vertical image slice illustrating how the crop-
The contact angle can be directly computed from ping box for the determination of the saturation was
the angle between the circular and linear fit at the defined (blue is water, green is oil). In the left image,
intersection at the triple point. In the image, yellow the angle α is indeed measured through the water. In
represents the sponge material, green is the brine and the right image, α is measured through the oil, so the
blue is the oil. The darker blue edge is the edge of contact angle θ = 180 − α. Adapted from Scanziani
the (partial) oblique slice used for this illustration. et al.[28].
Figure 4.12: Images illustrating the fitting procedure (a) and check for the acute or obtuse contact angle
(b).
Validation
Before the contact angle calculation algorithm is used on the obtained CT scans of the sponge, it is first
tested against a dataset of which the contact angles are known. The contact angle calculation algorithm is
tested with a CT image of an oil droplet trapped in a Ketton rock sample, obtained by Scanziani et al.[28]
(sample SSb). A segmented 2D slice of this dataset can be seen in Figure 4.13. Table 4.3 shows a comparison
of the contact angle calculation method as developed here compared to the results as reported by Scanziani
et al. As mentioned before, the code as developed by Scanziani et al. was not just transcoded to work in
the Dragonfly environment, but also optimised. In order to keep track of the developments, the transcoded
version of the script was first compared to the data of Scanziani et al., after which the improvements were
32
Master Thesis; K.D. van Kempen
implemented. As can be seen, the code developed here gives similar values for the contact angle, but also
results in a slightly higher standard deviation. One major improvement that is made is the runtime of the
code. The runtime of the code by Scanziani et al. is unknown, but it can be assumed that this code was
even slower than the transcoded code here. The reason for this is that the code by Scanziani et al. contained
some repeated unnecesary for-loops, which were already removed in the just transcoded version.
There are two why the resulting contact angle for the optimised code is different from the code by Scanziani
et al., which are the different way of implementing the moving mean on the triple line and the implementation
of the compatibility for vertical (or very steep) solid interfaces.
Table 4.3: Comparison of the contact angle calculation algorithms based on resulting contact angles, standard
deviation and runtime.
Figure 4.13: A 2D slice of the validation data. Adapted from Scanziani et al.[28].
33
Master Thesis; K.D. van Kempen
Figure 4.14: An illustration to show the line fitting procedure gives a wrong fit when there is fluid on both
sides of the solid material, due to the thin fibres in the sponge.
Figure 4.15: An example of a place where the segmentation model missed a part of the sponge fibre between
oil and water, which would lead to a misleading contact angle measurement.
In order to calculate the contact angles, a droplet was selected that had a good segmentation, which resided
on a fibre near the top of the sponge. This droplet is the droplet that was also used in all illustrations on the
contact angle calculation algorithm thus far. This droplet is taken from the scan of the suboptimal wetting
situation (pH=7), as the other scan contained nearly no droplets suitable for a contact angle analysis. The
mean contact angle for this droplet is 76.2 degrees, with a standard deviation of 13.9 degrees. The distribution
of the contact angles is shown in Figure 4.16.
34
Master Thesis; K.D. van Kempen
As the selected droplet here was a droplet that remained after dodecane had intruded a pore, the contact
angle having a value near 90 degrees can be expected. After all, no droplets would remain in an oil-
wet situation and for a water-wet situation, no oil would intrude the pore without any flow forcing. One
important realisation here is that these contact angles are vastly different from the contact angles as reported
by Cherukupally et al.[12]. Cherukupally et al. performed macro-scale, optical contact angle measurements
using crude oil or water on a film that should represent the SEnS sponge. This contact angle was measured
in air. The resulting contact angles reported by Cherukupally et al. were 139 degrees for water and 15
degrees for crude oil.
35
Master Thesis; K.D. van Kempen
5 Conclusion
5.1 Conclusion
In this study, a first analysis has been made of the wetting of a coated polyesther polyurethane foam on
the pore scale by making use of digital rock imaging techniques. This foam (or surface engineered sponge,
SEnS) is developed by Cherukupally et al.[12] for the purpose of oil absorption.
First, macro scale spontaneous imbibition tests showed that the foams do exhibit spontaneous imbibition
and have a high residual water saturation. Having shown that the sponge exhibits spontaneous imbibition,
CT scans have been made to be able to analyse the wetting of the sponges on the pore scale. From the
first observations on these scans, residual water droplets are found on the sponge fibres, indicating a het-
erogeneous wetting on some spots in the sponge. Furthermore, the absorption of iodide ions from the brine
indicated that the SEnS attracts charged particles, which contradicts the claim that the sponge is oil-wet,
as oil is a nonpolar fluid. Another observation that can directly be made from a visual inspection of the CT
image data is that sub-resolution membranes exist in the sponge, which might hinder the imbibition of oil
in the sponge and explain the high residual water saturation.
Moving further, numerical data on the wetting of the sponge was obtained, using the four Minkowski func-
tionals and in-situ contact angle measurements. In order to obtain these measurements, the sponge has been
segmented using a deep learning tool. A major drawback of this technique is that the segmentation model
is a complete black box, but the image resolution and noise level prohibited the use of less complicated
segmentation methods.
The Minkowski functionals showed only an indicative measure of the wettability, as a domain needs to be
chosen to evaluate these functionals on. This is a result of the assessment of wettability on the pore scale,
where the sponge dimensions are poorly defined, due to the small size of the fibres and large pore size. This
domain has been chosen by manually fitting a box to the sponge. Using this manually fitted domain, a
comparison was made between an optimal and a suboptimal system, where all Minkowski functionals indeed
showed a coherent impression of wettability.
More importantly, an algorithm was developed to calculate contact angles on the pore scale, based on the
method developed by Scanziani et al.[28]. In this algorithm, the triple line is found, an oblique slice is
extracted at every triple point, perpendicular to the triple line and all contact angles at these points are
evaluated by fitting the solid and fluid-fluid interfaces. Using this algorithm, contact angles were calculated
for a residual droplet onto a sponge fibre, showing an average contact angle of 72.6 degrees.
All in all, the analysis of the wetting of the SEnS revealed a significantly different behaviour than expected.
Whereas the data reported by Cherukupally indicate a strongly oil-wet sponge, being able to absorb all oil
from an emulsion within 3 hours, Amott spontaneous imbibition tests in this study only reached steady
state after two weeks, with a high residual water saturation of about 0.8 on the macro scale. Thereby, Cher-
ukupally et al. reported contact angles for water and crude oil in air of 139 and 15 degrees respectively. Also
these values differ vastly from the average contact angle of 72.6 degrees found on a residual water droplet
on the sponge here.
All these observations lead to the conclusion that an analysis of sponge wetting on the pore scale using digital
rock imaging techniques poses a valuable addition to the understanding of sponge wettability, uncovering
behaviour that is otherwise not found.
5.2 Outlook
This study is expected to form a starting point for further analyses of wettability of sponges on the multiple
length scales, especially on the pore scale. When such analyses are performed, sponges could be designed in
a more informed manner, potentially resulting in a better design.
In order to further elaborate on the findings of this study, CT images should be obtained with a lower amount
of signal loss or a higher resolution. This would enable the use of more classical segmentation methods, which
would also enable a proper sensitivity and error analysis on the segmented data.
36
Master Thesis; K.D. van Kempen
Bibliography
[1] Ahmed AlRatrout, Ali Q Raeini, Branko Bijeljic, and Martin J Blunt. Automatic measurement of
contact angle in pore-space images. Advances in Water Resources, 109:158–169, 2017.
[2] Earl Amott. Observations Relating to the Wettability of Porous Rock. Transactions of the AIME,
216(01):156–162, 1959.
[3] M. Andrew, B. Bijeljic, and M. J. Blunt. Pore-scale contact angle measurements at reservoir conditions
using X-ray microtomography. Advances in Water Resources, 68:24–31, 2014.
[4] Ryan T. Armstrong, James E. McClure, Vanessa Robins, Zhishang Liu, Christoph H. Arns, Steffen
Schlüter, and Steffen Berg. Porous media characterization using minkowski functionals: Theories,
applications and future directions. Transport in Porous Media, 130(1):305–335, Nov 2018.
[5] Ryan T. Armstrong, Holger Ott, Apostolos Georgiadis, Maja Rücker, Alex Schwing, and Steffen Berg.
Subsecond pore-scale displacement processes and relaxation dynamics in multiphase flow. Water Re-
sources Research, 50(12):9162–9176, 2014.
[6] E. Barry, J. A. Libera, A. U. Mane, J. R. Avila, D. Devitis, K. Van Dyke, J. W. Elam, and S. B. Darling.
Mitigating oil spills in the water column. Environmental Science: Water Research and Technology,
4(1):40–47, 2018.
[7] E. Barry, A. U. Mane, J. A. Libera, J. W. Elam, and S. B. Darling. Advanced oil sorbents using
sequential infiltration synthesis. Journal of Materials Chemistry A, 5(6):2929–2935, 2017.
[8] W. B. Bartels, M. Rücker, M. Boone, T. Bultreys, H. Mahani, S. Berg, S. M. Hassanizadeh, and
V. Cnudde. Imaging Spontaneous Imbibition in Full Darcy-Scale Samples at Pore-Scale Resolution by
Fast X-ray Tomography. Water Resources Research, 55(8):7072–7085, 2019.
[9] A. Bayat, S. F. Aghamiri, A. Moheb, and G. R. Vakili-Nezhaad. Oil spill cleanup from sea water by
sorbent materials. Chemical Engineering and Technology, 28(12):1525–1528, 2005.
[10] Martin J. Blunt. Multiphase Flow in Permeable Media: A Pore-Scale Perspective. Cambridge University
Press, 2017.
[11] P. Cherukupally, E. J. Acosta, J. P. Hinestroza, A. M. Bilton, and C. B. Park. Acid-Base Polymeric
Foams for the Adsorption of Micro-oil Droplets from Industrial Effluents. Environmental Science and
Technology, 51(15):8552–8560, 2017.
[12] P. Cherukupally, W. Sun, D.R. Williams, G.A. Ozin, and A.M. Bilton. Wax-wetting sponges for oil
droplets recovery from frigid waters.
[13] Yajun Deng, Lei Xu, Hailong Lu, Hao Wang, and Yongmin Shi. Direct measurement of the contact
angle of water droplet on quartz in a reservoir rock with atomic force microscopy. Chemical Engineering
Science, 177:445–454, 2018.
[14] K. J. Dobson, S. B. Coban, S. A. McDonald, J. N. Walsh, R. C. Atwood, and P. J. Withers. 4-d imaging
of sub-second dynamics in pore-scale processes using real-time synchrotron X-ray tomography. Solid
Earth, 7(4):1059–1073, 2016.
[15] Olugbenga Falode and Edo Manuel. Wettability effects on capillary pressure, relative permeability, and
irredcucible saturation using porous plate. Journal of Petroleum Engineering, 2014:465418, Aug 2014.
[16] Ying Gao, Qingyang Lin, Branko Bijeljic, and Martin J Blunt. Pore-scale dynamics and the multiphase
Darcy law. Physical Review Fluids, 5(1):13801, 2020.
[17] G. Garfi, C. M. John, S. Berg, and S. Krevor. The Sensitivity of Estimates of Multiphase Fluid and
Solid Properties of Porous Rocks to Image Processing. Transport in Porous Media, 131(3):985–1005,
2020.
37
Master Thesis; K.D. van Kempen
38
Master Thesis; K.D. van Kempen
Figure A.1: An illustration of how the triple point voxel can be defined in either phase a, b, or c (done here)
or in all phases (done by Scanziani et al.[28].
39
Master Thesis; K.D. van Kempen
check evaluates whether the first and last points used for the line fit are further apart in the x- or y-direction.
This way, it can be easily verified if the slope of the line is (roughly) more than 1 or less than -1. If this is
the case, which means the slope of the line fit might be very steep, the x- and y-coordinates will be flipped
for the line fit, so the risk of this vertical line fit is averted. After all, when the axes are flipped, a vertical
line appears as a horizontal line. As a result of this, some other parts of the code have been changed as well,
to be compatible with these flipped axes.
Besides this, some other improvements have been implemented which only improve the performance of the
code in terms of memory usage and computation time. Examples of this are unnecessary repeated for-loops
and instances where data was saved twice.
Later, the Dragonfly team made two final changes, which were the implementation of an existing NumPy
function for finding the interface points instead of scanning through the image and adding a check to see
whether the circle fit curves in the right direction (concave vs convex).
#F i t c i r c l e t o f l u i d −f l u i d i n t e r f a c e
circledata , x average oil , y average oil = fit circular droplet interface (
t r ip l e C on t a c tI m a ge A s N p Ar r a y , IPx , IPy , k l i n e )
i f c i r c l e d a t a i s None :
r e t u r n ’No c i r c l e f i t ’ , None
#Find t h e i n t e r c e p t i o n o f t h e f i t t e d i n t e r f a c e s
i n t e r c e p t i o n = l i n e C i r c ( t ri p l e C on t a ct I m a ge A s N p Ar r a y , linearfit , vertical line ,
circledata , x average oil ,
y a v e r a g e o i l , IPx , IPy )
i f i n t e r c e p t i o n i s None :
r e t u r n ’No i n t e r c e p t i o n ’ , None
#C a l c u l a t e t h e Contact a n g l e
raw angle = compute CA from fitdata ( l i n e a r f i t , v e r t i c a l l i n e , c i r c l e d a t a , i n t e r c e p t i o n )
f i n a l a n g l e = a c u t e o r o b t u s e C A ( t ri p l e Co n t ac t I m a ge A s N pA r r a y , IPx , IPy , c i r c l e d a t a ,
raw angle )
return ’ Success ’ , f i n a l a n g l e
d e f c i r c l e F i t B y P r a t t (Cx , Cy) :
#−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
#
# C i r c l e f i t by P r a t t
# V. Pratt , ” D i r e c t l e a s t −s q u a r e s f i t t i n g o f a l g e b r a i c s u r f a c e s ” ,
# Computer Graphics , Vol . 2 1 , p a g e s 145−152 ( 1 9 8 7 )
#
# I n p u t : XY( n , 2 ) i s t h e a r r a y o f c o o r d i n a t e s o f n p o i n t s x ( i )=XY( i , 1 ) , y ( i )=XY( i , 2 )
#
# Output : Par = [ a b R ] i s t h e f i t t i n g c i r c l e :
# c e n t e r ( a , b ) and r a d i u s R
#
# Note : t h i s f i t d o e s not u s e b u i l t −i n m a t r i x f u n c t i o n s ( e x c e p t ”mean ” ) ,
# s o i t can be e a s i l y programmed i n any programming l a n g u a g e
#
#−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
N = l e n ( Cx ) # Number o f data p o i n t s
x c e n t r o i d = np . mean ( Cx ) # t h e c e n t r o i d o f t h e data s e t
y c e n t r o i d = np . mean ( Cy )
40
Master Thesis; K.D. van Kempen
c e n t r o i d=np . a r r a y ( [ x c e n t r o i d , y c e n t r o i d ] )
f o r i in range ( N ) :
Xi = Cx [ i ] − x c e n t r o i d # c e n t e r i n g data
Yi = Cy [ i ] − y c e n t r o i d # c e n t e r i n g data
Z i = Xi ∗ Xi + Yi ∗ Yi
Mxy = Mxy + Xi ∗ Yi
Mxx = Mxx + Xi ∗ Xi
Myy = Myy + Yi ∗ Yi
Mxz = Mxz + Xi ∗ Z i
Myz = Myz + Yi ∗ Z i
Mzz = Mzz + Z i ∗ Z i
Mxx = Mxx/N
Myy = Myy/N
Mxy = Mxy/N
Mxz = Mxz/N
Myz = Myz/N
Mzz = Mzz/N
# computing t h e c o e f f i c i e n t s o f t h e c h a r a c t e r i s t i c p o l y n o m i a l
Mz = Mxx + Myy
Cov xy = Mxx∗Myy − Mxy∗Mxy
Mxz2 = Mxz∗Mxz
Myz2 = Myz∗Myz
e p s i l o n =1e −12
ynew=1e+20
IterMax=20
xnew = 0
f o r i t e r i n r a n g e ( IterMax ) :
y o l d = ynew
ynew = A0 + xnew ∗ ( A1 + xnew ∗ ( A2 + 4∗ xnew∗xnew ) )
i f xnew < 0 :
p r i n t ( ’ Newton−P r a t t n e g a t i v e r o o t : x= ’ , xnew , ’ \n ’ )
xnew = 0
# computing t h e c i r c l e p a r a m e t e r s
41
Master Thesis; K.D. van Kempen
r e t u r n Par
t h e t a c i r c l e = np . a r c t a n ( s i n t h e t a c i r c l e / c o s t h e t a c i r c l e )
t h e t a t a n g e n t = t h e t a c i r c l e + np . p i /2
t h e t a c o n t a c t r a d i a n t = abs ( t h e t a t a n g e n t − t h e t a s e c a n t )
if t h e t a c o n t a c t r a d i a n t > np . p i / 2 :
t h e t a c o n t a c t r a d i a n t = np . p i − t h e t a c o n t a c t r a d i a n t
# i n c a s e k l i n e i s b i g g e r than t h e image s i z e
m i n i d x = min ( k l i n e , IPx )
x i d x = np . maximum( np . z e r o s ( x i n d i c e s r o c k . shape ) , IPx − m i n i d x + x i n d i c e s r o c k )
y i d x = np . maximum( np . z e r o s ( y i n d i c e s r o c k . shape ) , IPy − m i n i d x + y i n d i c e s r o c k )
#Now, a s t r a i g h t l i n e i s f i t t e d t h r o u g h t h e r o c k i n t e r f a c e p i x e l s .
#S i n c e S c a n z i a n i ’ s code d i d not s u p p o r t v e r t i c a l l i n e s , I added t h i s v i a t h e b o o l e a n ’
vertical line ’
#I f t h e l i n e i s v e r t i c a l , l i n e a r f i t t i n g d o e s not work , s i n c e t h e s l o p e w i l l be i n f i n i t e
#I n o r d e r t o r e s o l v e t h i s , t h e x− and y a x i s a r e f l i p p e d
#Here , t h e l i n e w i l l be c a l l e d ’ v e r t i c a l ’ i f i t has a s l o p e o f >1 o r <−1
i f l e n ( Lx ) != 0 and l e n ( Ly ) != 0 :
i f abs ( Lx [ 0 ] − Lx [ − 1 ] ) < abs ( Ly [ 0 ] − Ly [ − 1 ] ) :
v e r t i c a l l i n e = True
42
Master Thesis; K.D. van Kempen
l i n e a r f i t = np . p o l y f i t ( Ly , Lx , 1 )
else :
l i n e a r f i t = np . p o l y f i t ( Lx , Ly , 1 )
p r i n t ( ’ no l i n e a r f i t ’ )
r e t u r n None , None
#I n i t i a l i s e a r r a y s
Cx = np . a r r a y ( [ ] , dtype=i n t )
Cy = np . a r r a y ( [ ] , dtype=i n t )
#Again , S c a n z i a n i used 2 s e p a r a t e n e s t e d l o o p s t o :
# − f i n d the f l u i d / f l u i d i n t e r f a c e
# − o ut pu t t h e c o r r e s p o n d i n g p i x e l l o c a t i o n s
# This s h o u l d do t h e same i n way l e s s i t e r a t i o n s
#
#Also , S c a n z i a n i i t e r a t e d o v e r t h e e n t i r e image and l a t e r
#removed t h e p o i n t s o u t s i d e o f t h e s e a r c h window ( IP+−k l i n e )
# I i m m e d i a t e l y i t e r a t e o v e r o n l y IP+−k l i n e , which s a v e s a
# l o t of unnecessary i t e r a t i o n s
# i n c a s e k l i n e i s b i g g e r than t h e image s i z e
m i n i d x = min ( k l i n e , IPx )
x i d x = np . maximum( np . z e r o s ( x i n d i c e s o i l . shape ) , IPx − m i n i d x + x i n d i c e s o i l )
y i d x = np . maximum( np . z e r o s ( y i n d i c e s o i l . shape ) , IPy − m i n i d x + y i n d i c e s o i l )
n e i g h b o r s = np . a r r a y ( [ pad img [ l i s t ( ( y i d x ) . a s t y p e ( i n t ) ) , l i s t ( ( x i d x −1) . a s t y p e ( i n t ) ) ] ,
pad img [ l i s t ( ( y i d x ) . a s t y p e ( i n t ) ) , l i s t ( ( x i d x +1) . a s t y p e ( i n t ) ) ] ,
pad img [ l i s t ( ( y i d x −1) . a s t y p e ( i n t ) ) , l i s t ( ( x i d x ) . a s t y p e ( i n t ) ) ] ,
pad img [ l i s t ( ( y i d x +1) . a s t y p e ( i n t ) ) , l i s t ( ( x i d x ) . a s t y p e ( i n t ) ) ] ] )
#Find t h e water p i x e l s t h a t a r e i n c o n t a c t with o i l
r e s t i n d i c e s = np . where ( np . any ( n e i g h b o r s == 1 , a x i s =0) )
Cx = np . append (Cx , np . t a k e ( y i d x , r e s t i n d i c e s [ 0 ] ) )
Cy = np . append (Cy , np . t a k e ( x i d x , r e s t i n d i c e s [ 0 ] ) )
#F i t a c i r c l e t o t h e f l u i d −f l u i d i n t e r f a c e p i x e l s
i f l e n (Cx) == 0 :
r e t u r n None , None , None
c i r c l e d a t a = c i r c l e F i t B y P r a t t (Cx , Cy)
return circledata , x average oil , y average oil
d e f l i n e C i r c ( img , l i n e a r f i t , v e r t i c a l l i n e , c i r c l e d a t a , x a v e r a g e o i l , y a v e r a g e o i l , IPx ,
IPy ) :
pad img = np . pad ( img [ 0 , 0 , : , : ] , 1 , mode= ’ c o n s t a n t ’ )
slope = l i n e a r f i t [ 0 ]
intercept = l i n e a r f i t [1]
L = L i n e S t r i n g ( [ ( 0 , i n t e r c e p t ) , ( pad img . shape [ 1 ] , pad img . shape [ 1 ] ∗ s l o p e + i n t e r c e p t ) ] )
i f not v e r t i c a l l i n e :
#Find t h e i n t e r c e p t i o n o f t h e f i t t e d i n t e r f a c e s
# Make l i n e (L) and c i r c l e (C) o b j e c t s and f i n d i n t e r s e c t i o n s
try :
C = Point ( c i r c l e d a t a [ 0 ] , c i r c l e d a t a [ 1 ] ) . b u f f e r ( c i r c l e d a t a [ 2 ] )
P o i l = Point ( y a v e r a g e o i l , x a v e r a g e o i l )
i f not P o i l . w i t h i n (C) :
p r i n t ( ’ p o i n t not i n c i r c l e ’ )
r e t u r n None
43
Master Thesis; K.D. van Kempen
except :
p r i n t ( ’ no c i r c l e fit ’)
r e t u r n None
i n t e r c e p t = C . i n t e r s e c t i o n (L)
i f l e n ( i n t e r c e p t . c o o r d s ) == 0 :
p r i n t ( ’ no i n t e r c e p t i o n ’ )
r e t u r n None
#There a r e a l w a y s 2 i n t e r s e c t i o n s ; keep o n l y t h e one t h a t r e p r e s e n t s t h e t r i p l e
point
#The v a l u e o f <3 i n t h e i f −s t a t e m e n t i s a r b i t r a r i l y c h o s e n ; t h i s might be done more
e l e g a n t l y , but then I g u e s s i t would c o s t more c a l c u l a t i o n power
#S c a n z i a n i used a d i f f e r e n t approach h e r e , but I t h i n k t h i s i s more r o b u s t
i f f l o a t ( d i s t a n c e . e u c l i d e a n ( i n t e r c e p t . c o o r d s [ 0 ] , P o i n t ( IPx , IPy ) ) ) < \
f l o a t ( d i s t a n c e . e u c l i d e a n ( i n t e r c e p t . c o o r d s [ 1 ] , P o i n t ( IPx , IPy ) ) ) :
x i n t e r c e p t = f l o a t ( i n t e r c e p t . coords [ 0 ] [ 0 ] )
y i n t e r c e p t = f l o a t ( i n t e r c e p t . coords [ 0 ] [ 1 ] )
else :
x i n t e r c e p t = f l o a t ( i n t e r c e p t . coords [ 1 ] [ 0 ] )
y i n t e r c e p t = f l o a t ( i n t e r c e p t . coords [ 1 ] [ 1 ] )
else :
#Same a s o t h e r , o n l y a x e s a r e f l i p e d
try :
C = Point ( c i r c l e d a t a [ 1 ] , c i r c l e d a t a [ 0 ] ) . b u f f e r ( c i r c l e d a t a [ 2 ] )
P o i l = Point ( x a v e r a g e o i l , y a v e r a g e o i l )
i f not P o i l . w i t h i n (C) :
p r i n t ( ’ p o i n t not i n c i r c l e ’ )
r e t u r n None
except :
p r i n t ( ’ no c i r c l e f i t ’ )
r e t u r n None
i n t e r c e p t = C . i n t e r s e c t i o n (L)
i f l e n ( i n t e r c e p t . c o o r d s ) == 0 :
p r i n t ( ’ no i n t e r c e p t i o n ’ )
r e t u r n None
i n t e r c e p t i o n = np . a r r a y ( [ x i n t e r c e p t , y i n t e r c e p t ] )
return interception
d e f p l o t v a l u e s ( pad img , v e r t i c a l l i n e , L , C) :
# P l o t l i n e , c i r c l e and image
ax = p l t . s u b p l o t ( 1 , 1 , 1 )
ax . s e t a s p e c t ( ’ e q u a l ’ )
p l t . imshow ( pad img )
xL , yL = L . c o o r d s . xy
xC , yC = C . e x t e r i o r . xy
i f not v e r t i c a l l i n e :
ax . p l o t (yC , xC , ’ g− ’ )
ax . p l o t ( yL , xL , ’ r− ’ )
else :
ax . p l o t (xC , yC , ’ g− ’ )
ax . p l o t ( xL , yL , ’ r− ’ )
p l t . show ( )
m normal = np . tan ( t h e t a n o r m a l )
44
Master Thesis; K.D. van Kempen
x n o r m a l = np . a r r a y ( r a n g e ( IPx−k , IPx+k ) )
y n o r m a l = IPy + m normal ∗ ( x n o r m a l − IPx )
x normal new = x n o r m a l
y normal new = y n o r m a l
it = 0
f o r i in range ( l e n ( x normal ) ) :
i f np . c e i l ( x n o r m a l [ i ] ) < 0 o r np . c e i l ( y n o r m a l [ i ] ) < 0 :
x normal new = np . d e l e t e ( x normal new , i −i t )
y normal new = np . d e l e t e ( y normal new , i −i t )
i t +=1
x normal new = x n o r m a l
y normal new = y n o r m a l
it = 0
f o r i in range ( l e n ( x normal ) ) :
i f np . round ( x n o r m a l [ i ] ) < 0 o r np . round ( y n o r m a l [ i ] ) < 0 :
x normal new = np . d e l e t e ( x normal new , i −i t )
y normal new = np . d e l e t e ( y normal new , i −i t )
i t +=1
label = 0
i f l e n ( x normal new new ) > 3:
f o r i in range ( len ( x normal new new ) ) :
i f img [ t −1 , z −1 , i n t ( np . c e i l ( x normal new new [ i ] ) ) , i n t ( np . c e i l (
y normal new new [ i ] ) ) ] == 1 :
l a b e l+=1
if l a b e l == 0 :
t h e t a c o n t a c t r a d i a n t = np . p i − t h e t a c o n t a c t r a d i a n t
t h e t a c o n t a c t d e g r e e = np . r a d 2 d e g ( t h e t a c o n t a c t r a d i a n t )
else :
t h e t a c o n t a c t d e g r e e = np . NaN
: a u t h o r : ORS Team
45
Master Thesis; K.D. van Kempen
: c o n t a c t : h t t p : / / t h e o b j e c t s . com
: e m a i l : i n f o @ t h e o b j e c t s . com
: o r g a n i z a t i o n : O b j e c t R e s e a r c h Systems (ORS) , I n c .
: a d d r e s s : 760 St−Paul West , s u i t e 1 0 1 , M o n t r a l , Q u b e c , Canada , H3C 1M4
: c o p y r i g h t : O b j e c t R e s e a r c h Systems (ORS) , I n c . A l l r i g h t s r e s e r v e d 2 0 2 1 .
: d a t e : mai 03 2021 1 7 : 2 0
: d r a g o n f l y V e r s i o n : 2 0 2 1 . 3 . 0 . 1 0 0 0 (D)
: UUID : 556 c c c 1 b a c 5 5 1 1 e b 8 7 3 6 0 c 9 d 9 2 7 6 7 3 4 f
”””
version = ’ 1.0.0 ’
im po rt numpy a s np
from time i mpo rt time
from math im por t s q r t
from s c i p y . s p a t i a l im por t d i s t a n c e
from m a t p l o t l i b im por t p y p l o t a s p l t
from s h a p e l y . geometry imp ort L i n e S t r i n g
from s h a p e l y . geometry imp ort P o i n t
c l a s s addTriplePointContactAngleVertexScalarValue 556ccc1bac5511eb87360c9d9276734f (
ContextualMenuItem ) :
@classmethod
def getIsSelectionValid ( cls , aCollectionOfObjects ) :
”””
: param a C o l l e c t i o n O f O b j e c t s : a l i s t o f o b j e c t s c u r r e n t l y b e i n g s e l e c t e d , i . e . on
which t h e menu item c o u l d be a p p l i e d .
: r e t u r n : i f True , t h e menu item w i l l be d i s p l a y e d .
”””
i f l e n ( a C o l l e c t i o n O f O b j e c t s ) != 4 :
return
@classmethod
def getMenuItemForSelection ( cls , aCollectionOfObjects ) :
”””
Returns t h e menu item
: param a C o l l e c t i o n O f O b j e c t s : a l i s t o f o b j e c t s c u r r e n t l y b e i n g s e l e c t e d , i . e . on
which t h e menu item w i l l be a p p l i e d .
: r e t u r n : Menu
”””
@classmethod
46
Master Thesis; K.D. van Kempen
d e f menuItemEntryPoint ( c l s , c o l l e c t i o n S t r i n g ) :
”””
W i l l be e x e c u t e d when t h e menu item i s s e l e c t e d .
: param c o l l e c t i o n S t r i n g : a l i s t o f o b j e c t s r e p r e s e n t a t i o n c u r r e n t l y b e i n g s e l e c t e d ,
i . e . on which t h e menu item w i l l be a p p l i e d .
”””
e l e c t r o l y t e R O I : ROI = r o i s [ 0 ]
f i r s t C o n d u c t o r R O I : ROI = r o i s [ 1 ]
secondConductorROI : ROI = r o i s [ 2 ]
c l s . a d d T r i p l e P o i n t C o n t a c t A n g l e V e r t e x S c a l a r V a l u e ( aGraph , e l e c t r o l y t e R O I ,
f i r s t C o n d u c t o r R O I , secondConductorROI )
@classmethod
@showWaitCursorWhileExecuting
@run in background waiting until finished
d e f a d d T r i p l e P o i n t C o n t a c t A n g l e V e r t e x S c a l a r V a l u e ( c l s , aGraph , e l e c t r o l y t e R O I ,
f i r s t C o n d u c t o r R O I , secondConductorROI ) :
p r o g r e s s = P r o g r e s s ( l o g g i n g=True )
p r o g r e s s . s t a r t W o r k i n g P r o g r e s s W i t h I D (ORS PB WORKING, True , l o g g i n g=True )
c l s . a d d T r i p l e P o i n t C o n t a c t A n g l e V e r t e x S c a l a r V a l u e ( aGraph , e l e c t r o l y t e R O I ,
f i r s t C o n d u c t o r R O I , secondConductorROI , p r o g r e s s )
i f p r o g r e s s i s not None :
p r o g r e s s . d e l e t e O b j e c t ( l o g g i n g=True )
@classmethod
@interfaceMethod
d e f a d d T r i p l e P o i n t C o n t a c t A n g l e V e r t e x S c a l a r V a l u e ( c l s , aGraph , e l e c t r o l y t e R O I ,
f i r s t C o n d u c t o r R O I , secondConductorROI , p r o g r e s s ) :
”””
Add v e r t e x s c a l a r v a l u e s t o t h e graph , d e s c r i b i n g t r i p l e p o i n t c o n t a c t a n g l e
i f e l e c t r o l y t e R O I i s None :
return
i f f i r s t C o n d u c t o r R O I i s None :
return
i f secondConductorROI i s None :
return
i f aGraph i s None :
return
# S e t up s c a l a r s l o t i n graph f o r a n g l e v a l u e s
i n d e x S l o t = aGraph . g e t V e r t e x S c a l a r V a l u e s S l o t C o u n t ( )
aGraph . s e t V e r t e x S c a l a r V a l u e s S l o t C o u n t ( i n d e x S l o t + 1 )
aGraph . s e t V e r t e x S c a l a r V a l u e D e s c r i p t i o n ( i n d e x S l o t , ’ t r i p l e p o i n t c o n t a c t a n g l e ’ , 0 )
47
Master Thesis; K.D. van Kempen
aGraph . s e t V e r t e x S c a l a r V a l u e D i m e n s i o n U n i t ( i n d e x S l o t , DimensionUnit . g e t R e g i s t e r e d U n i t (
’CANONICAL DIMENSION DEGREE ’ ) , 0 )
v e r t i c e s = aGraph . g e t V e r t i c e s ( 0 )
v e r t e x C o u n t = aGraph . getVe rtexC ount ( 0 )
# P r e d e c e s s o r s and s u c c e s s o r s a r e needed t o c a l c u l a t e t h e normal o f t h e p l a n e , −1 i f
no v a l u e
p r e d e c e s s o r s A n d S u c c e s s o r s = aGraph . g e t V e r t i c e s P r e d e c e s s o r A n d S u c c e s s o r ( 0 )
numNoIntercepts = 0
nbNonZero = np . c o u n t n o n z e r o ( np . a r r a y ( [ y0 , y1 , y2 , y3 , y4 ] ) )
yAverage = ( y0 + y1 + y2 + y3 + y4 ) / nbNonZero
# keep new y v a l u e f o r v e r t e x i n d e x
arrayNewYValues . atPut ( v e r t e x I n d e x , yAverage )
# C r e a t e i n t e r s e c t i n g p l a n e and c a l c u l a t e a n g l e f o r e v e r y t r i p l e p o i n t c o n t a c t
f o r vertexIndex in range ( vertexCount ) :
sourceIndex = predecessorsAndSuccessors . at (2∗ vertexIndex )
t a r g e t I n d e x = p r e d e c e s s o r s A n d S u c c e s s o r s . a t ( 2 ∗ v e r t e x I n d e x +1)
# Only compute i f v e r t e x i s not a s i n g l e p o i n t a l o n e
i f s o u r c e I n d e x == t a r g e t I n d e x :
p r i n t ( ’ Same s o u r c e and t a r g e t i n d e x ’ )
numNoIntercepts += 1
continue
normalDirectionOfPlane . normalize ()
upDirectionOfPlane = normalDirectionOfPlane . getAPerpendicular ( ) . getNormalized ( )
48
Master Thesis; K.D. van Kempen
# Convert i n t e r s e c t i n g p l a n e t o ORS o b j e c t ( r e c t a n g l e )
rectangleOfOrientedPlane = Rectangle ()
d i r e c t i o n 0 = normalDirectionOfPlane . getCrossProductWith ( upDirectionOfPlane )
direction0 . normalize ()
d i r e c t i o n 1 = upDirectionOfPlane
direction1 . normalize ()
rectangleOfOrientedPlane . setDirection0 ( direction0 )
rectangleOfOrientedPlane . setDirection1 ( direction1 )
rectangleOfOrientedPlane . setDirection0Size ( recSizeInVoxels ∗ recSpacing )
rectangleOfOrientedPlane . setDirection1Size ( recSizeInVoxels ∗ recSpacing )
rectangleOfOrientedPlane . setDirection0Spacing ( recSpacing )
rectangleOfOrientedPlane . setDirection1Spacing ( recSpacing )
rectangleOfOrientedPlane . setOrigin ( currentVertex − ( direction0 ∗ recSizeInVoxels ∗
recSpacing /2) −
( d i r e c t i o n 1 ∗ r e c S i z e I n V o x e l s ∗ recSpacing /2) )
# C r e a t e a c h a n n e l from p l a n e t o u s e a s image f o r t r i p l e p o i n t c o n t a c t
computation
tempChannel = Channel ( )
tempChannel . setAsTemporaryObject ( )
tempChannel . copyShapeFromRectangle ( r e c t a n g l e O f O r i e n t e d P l a n e , r e c S p a c i n g ,
electrolyteROI . getTSize () )
tempChannel . initializeDataForUCHAR ( )
tempChannel . overwriteValueWithROI ( e l e c t r o l y t e R O I , 1 )
tempChannel . overwriteValueWithROI ( f i r s t C o n d u c t o r R O I , 2 )
tempChannel . overwriteValueWithROI ( secondConductorROI , 3 )
# Use c o o r d i n a t e s i n v o x e l s
m i d d l e V e r t e x I n V o x e l s = tempChannel . g e t W o r l d T o V o x e l C o o r d i n a t e s ( c u r r e n t V e r t e x )
# tempChannel . ato mic Save ( ’ d : \ \ temp1 \ \ ’ + r e p r ( v e r t e x I n d e x ) + ’ . ORSObject ’ , F a l s e
)
# Returns None i f s o m e t h i n g went wrong , t h e p r e v i o u s l i n e a l l o w s e x p o r t o f
channel to v i s u a l i z e the i n t e r s e c t i n g plane
timea = time ( )
tempChannelAsNpArray = createNumpyArrayFromChannel ( tempChannel , F a l s e )
k line = 5
f o r window i n r a n g e ( 0 , 3 1 ) :
k l i n e += 1
e r r , c o n t a c t A n g l e = c o n t a c t a n g l e ( tempChannelAsNpArray , k l i n e , i n t (
m i d d l e V e r t e x I n V o x e l s . getX ( ) ) , i n t ( m i d d l e V e r t e x I n V o x e l s . getY ( ) ) )
i f c o n t a c t A n g l e i s not None :
break
i f c o n t a c t A n g l e i s None :
# I f t h e r e was a problem c a l c u l a t i n g t h e c o n t a c t a n g l e , s e t t h e s c a l a r v a l u e
to 0
contactAngle = 0
numNoIntercepts += 1
tempChannel . d e l e t e O b j e c t ( )
#Add c o n t a c t a n g l e t o v e r t e x s c a l a r v a l u e
aGraph . s e t V e r t e x S c a l a r V a l u e ( i n d e x S l o t , v e r t e x I n d e x , c o n t a c t A n g l e , 0 )
p r i n t ( f ’ V er te x i n d e x : { v e r t e x I n d e x } count e r r o r s : { numNoIntercepts }
e r r o r type : { e r r } time : { time ( )−timea } ’ )
d e f c o n t a c t a n g l e ( t r i pl e C o nt a c t Im a g e As N p A r ra y , k l i n e , IPx , IPy ) :
#F i t s t r a i g h t l i n e t o m a t r i x ( r o c k ) i n t e r f a c e
l i n e a r f i t , v e r t i c a l l i n e = f i t l i n e a r r o c k i n t e r f a c e ( tr i p l eC o n t ac t I m ag e A s Np A r r ay , IPx ,
IPy , k l i n e )
i f l i n e a r f i t i s None o r v e r t i c a l l i n e i s None :
r e t u r n ’No l i n e a r f i t ’ , None
#F i t c i r c l e t o f l u i d −f l u i d i n t e r f a c e
circledata , x average oil , y average oil = fit circular droplet interface (
t r ip l e C on t a c tI m a ge A s N p Ar r a y , IPx , IPy , k l i n e )
i f c i r c l e d a t a i s None :
r e t u r n ’No c i r c l e f i t ’ , None
#Find t h e i n t e r c e p t i o n o f t h e f i t t e d i n t e r f a c e s
i n t e r c e p t i o n = l i n e C i r c ( t ri p l e C on t a ct I m a ge A s N p Ar r a y , linearfit , vertical line ,
circledata , x average oil ,
y a v e r a g e o i l , IPx , IPy )
i f i n t e r c e p t i o n i s None :
49
Master Thesis; K.D. van Kempen
r e t u r n ’No i n t e r c e p t i o n ’ , None
#C a l c u l a t e t h e Contact a n g l e
raw angle = compute CA from fitdata ( l i n e a r f i t , v e r t i c a l l i n e , c i r c l e d a t a , i n t e r c e p t i o n )
f i n a l a n g l e = a c u t e o r o b t u s e C A ( t ri p l e Co n t ac t I m a ge A s N pA r r a y , IPx , IPy , c i r c l e d a t a ,
raw angle )
return ’ Success ’ , f i n a l a n g l e
d e f c i r c l e F i t B y P r a t t (Cx , Cy) :
#−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
#
# C i r c l e f i t by P r a t t
# V. Pratt , ” D i r e c t l e a s t −s q u a r e s f i t t i n g o f a l g e b r a i c s u r f a c e s ” ,
# Computer Graphics , Vol . 2 1 , p a g e s 145−152 ( 1 9 8 7 )
#
# I n p u t : XY( n , 2 ) i s t h e a r r a y o f c o o r d i n a t e s o f n p o i n t s x ( i )=XY( i , 1 ) , y ( i )=XY( i , 2 )
#
# Output : Par = [ a b R ] i s t h e f i t t i n g c i r c l e :
# c e n t e r ( a , b ) and r a d i u s R
#
# Note : t h i s f i t d o e s not u s e b u i l t −i n m a t r i x f u n c t i o n s ( e x c e p t ”mean ” ) ,
# s o i t can be e a s i l y programmed i n any programming l a n g u a g e
#
#−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
N = l e n ( Cx ) # Number o f data p o i n t s
x c e n t r o i d = np . mean ( Cx ) # t h e c e n t r o i d o f t h e data s e t
y c e n t r o i d = np . mean ( Cy )
c e n t r o i d=np . a r r a y ( [ x c e n t r o i d , y c e n t r o i d ] )
f o r i in range ( N ) :
Xi = Cx [ i ] − x c e n t r o i d # c e n t e r i n g data
Yi = Cy [ i ] − y c e n t r o i d # c e n t e r i n g data
Z i = Xi ∗ Xi + Yi ∗ Yi
Mxy = Mxy + Xi ∗ Yi
Mxx = Mxx + Xi ∗ Xi
Myy = Myy + Yi ∗ Yi
Mxz = Mxz + Xi ∗ Z i
Myz = Myz + Yi ∗ Z i
Mzz = Mzz + Z i ∗ Z i
Mxx = Mxx/N
Myy = Myy/N
Mxy = Mxy/N
Mxz = Mxz/N
Myz = Myz/N
Mzz = Mzz/N
# computing t h e c o e f f i c i e n t s o f t h e c h a r a c t e r i s t i c p o l y n o m i a l
Mz = Mxx + Myy
Cov xy = Mxx∗Myy − Mxy∗Mxy
Mxz2 = Mxz∗Mxz
Myz2 = Myz∗Myz
e p s i l o n =1e −12
ynew=1e+20
50
Master Thesis; K.D. van Kempen
IterMax=20
xnew = 0
f o r i t e r i n r a n g e ( IterMax ) :
y o l d = ynew
ynew = A0 + xnew ∗ ( A1 + xnew ∗ ( A2 + 4∗ xnew∗xnew ) )
i f xnew < 0 :
p r i n t ( ’ Newton−P r a t t n e g a t i v e r o o t : x= ’ , xnew , ’ \n ’ )
xnew = 0
# computing t h e c i r c l e p a r a m e t e r s
r e t u r n Par
t h e t a c i r c l e = np . a r c t a n ( s i n t h e t a c i r c l e / c o s t h e t a c i r c l e )
t h e t a t a n g e n t = t h e t a c i r c l e + np . p i /2
t h e t a c o n t a c t r a d i a n t = abs ( t h e t a t a n g e n t − t h e t a s e c a n t )
if t h e t a c o n t a c t r a d i a n t > np . p i / 2 :
t h e t a c o n t a c t r a d i a n t = np . p i − t h e t a c o n t a c t r a d i a n t
51
Master Thesis; K.D. van Kempen
# Find t h e r o c k i n d i c e s
y i n d i c e s r o c k , x i n d i c e s r o c k = np . where ( pad img [ max ( 0 , IPy−k l i n e ) : min ( nrows , IPy+
k line ) ,
max ( 0 , IPx−k l i n e ) : min ( n c o l s , IPx+k l i n e ) ] ==
3)
# i n c a s e k l i n e i s b i g g e r than t h e image s i z e
m i n i d x = min ( k l i n e , IPx )
x i d x = np . maximum( np . z e r o s ( x i n d i c e s r o c k . shape ) , IPx − m i n i d x + x i n d i c e s r o c k )
y i d x = np . maximum( np . z e r o s ( y i n d i c e s r o c k . shape ) , IPy − m i n i d x + y i n d i c e s r o c k )
#Now, a s t r a i g h t l i n e i s f i t t e d t h r o u g h t h e r o c k i n t e r f a c e p i x e l s .
#S i n c e S c a n z i a n i ’ s code d i d not s u p p o r t v e r t i c a l l i n e s , I added t h i s v i a t h e b o o l e a n ’
vertical line ’
#I f t h e l i n e i s v e r t i c a l , l i n e a r f i t t i n g d o e s not work , s i n c e t h e s l o p e w i l l be i n f i n i t e
#I n o r d e r t o r e s o l v e t h i s , t h e x− and y a x i s a r e f l i p p e d
#Here , t h e l i n e w i l l be c a l l e d ’ v e r t i c a l ’ i f i t has a s l o p e o f >1 o r <−1
i f l e n ( Lx ) != 0 and l e n ( Ly ) != 0 :
i f abs ( Lx [ 0 ] − Lx [ − 1 ] ) < abs ( Ly [ 0 ] − Ly [ − 1 ] ) :
v e r t i c a l l i n e = True
l i n e a r f i t = np . p o l y f i t ( Ly , Lx , 1 )
else :
l i n e a r f i t = np . p o l y f i t ( Lx , Ly , 1 )
p r i n t ( ’ no l i n e a r f i t ’ )
r e t u r n None , None
#I n i t i a l i s e a r r a y s
Cx = np . a r r a y ( [ ] , dtype=i n t )
Cy = np . a r r a y ( [ ] , dtype=i n t )
#Again , S c a n z i a n i used 2 s e p a r a t e n e s t e d l o o p s t o :
# − f i n d the f l u i d / f l u i d i n t e r f a c e
# − o ut pu t t h e c o r r e s p o n d i n g p i x e l l o c a t i o n s
# This s h o u l d do t h e same i n way l e s s i t e r a t i o n s
#
#Also , S c a n z i a n i i t e r a t e d o v e r t h e e n t i r e image and l a t e r
#removed t h e p o i n t s o u t s i d e o f t h e s e a r c h window ( IP+−k l i n e )
# I i m m e d i a t e l y i t e r a t e o v e r o n l y IP+−k l i n e , which s a v e s a
# l o t of unnecessary i t e r a t i o n s
# i n c a s e k l i n e i s b i g g e r than t h e image s i z e
m i n i d x = min ( k l i n e , IPx )
x i d x = np . maximum( np . z e r o s ( x i n d i c e s o i l . shape ) , IPx − m i n i d x + x i n d i c e s o i l )
y i d x = np . maximum( np . z e r o s ( y i n d i c e s o i l . shape ) , IPy − m i n i d x + y i n d i c e s o i l )
n e i g h b o r s = np . a r r a y ( [ pad img [ l i s t ( ( y i d x ) . a s t y p e ( i n t ) ) , l i s t ( ( x i d x −1) . a s t y p e ( i n t ) ) ] ,
pad img [ l i s t ( ( y i d x ) . a s t y p e ( i n t ) ) , l i s t ( ( x i d x +1) . a s t y p e ( i n t ) ) ] ,
pad img [ l i s t ( ( y i d x −1) . a s t y p e ( i n t ) ) , l i s t ( ( x i d x ) . a s t y p e ( i n t ) ) ] ,
pad img [ l i s t ( ( y i d x +1) . a s t y p e ( i n t ) ) , l i s t ( ( x i d x ) . a s t y p e ( i n t ) ) ] ] )
#Find t h e water p i x e l s t h a t a r e i n c o n t a c t with o i l
52
Master Thesis; K.D. van Kempen
#F i t a c i r c l e t o t h e f l u i d −f l u i d i n t e r f a c e p i x e l s
i f l e n (Cx) == 0 :
r e t u r n None , None , None
c i r c l e d a t a = c i r c l e F i t B y P r a t t (Cx , Cy)
return circledata , x average oil , y average oil
d e f l i n e C i r c ( img , l i n e a r f i t , v e r t i c a l l i n e , c i r c l e d a t a , x a v e r a g e o i l , y a v e r a g e o i l , IPx ,
IPy ) :
pad img = np . pad ( img [ 0 , 0 , : , : ] , 1 , mode= ’ c o n s t a n t ’ )
slope = l i n e a r f i t [ 0 ]
intercept = l i n e a r f i t [1]
L = L i n e S t r i n g ( [ ( 0 , i n t e r c e p t ) , ( pad img . shape [ 1 ] , pad img . shape [ 1 ] ∗ s l o p e + i n t e r c e p t ) ] )
i f not v e r t i c a l l i n e :
#Find t h e i n t e r c e p t i o n o f t h e f i t t e d i n t e r f a c e s
# Make l i n e (L) and c i r c l e (C) o b j e c t s and f i n d i n t e r s e c t i o n s
try :
C = Point ( c i r c l e d a t a [ 0 ] , c i r c l e d a t a [ 1 ] ) . b u f f e r ( c i r c l e d a t a [ 2 ] )
P o i l = Point ( y a v e r a g e o i l , x a v e r a g e o i l )
i f not P o i l . w i t h i n (C) :
p r i n t ( ’ p o i n t not i n c i r c l e ’ )
r e t u r n None
except :
p r i n t ( ’ no c i r c l e f i t ’ )
r e t u r n None
i n t e r c e p t = C . i n t e r s e c t i o n (L)
i f l e n ( i n t e r c e p t . c o o r d s ) == 0 :
p r i n t ( ’ no i n t e r c e p t i o n ’ )
r e t u r n None
#There a r e a l w a y s 2 i n t e r s e c t i o n s ; keep o n l y t h e one t h a t r e p r e s e n t s t h e t r i p l e
point
#The v a l u e o f <3 i n t h e i f −s t a t e m e n t i s a r b i t r a r i l y c h o s e n ; t h i s might be done more
e l e g a n t l y , but then I g u e s s i t would c o s t more c a l c u l a t i o n power
#S c a n z i a n i used a d i f f e r e n t approach h e r e , but I t h i n k t h i s i s more r o b u s t
i f f l o a t ( d i s t a n c e . e u c l i d e a n ( i n t e r c e p t . c o o r d s [ 0 ] , P o i n t ( IPx , IPy ) ) ) < \
f l o a t ( d i s t a n c e . e u c l i d e a n ( i n t e r c e p t . c o o r d s [ 1 ] , P o i n t ( IPx , IPy ) ) ) :
x i n t e r c e p t = f l o a t ( i n t e r c e p t . coords [ 0 ] [ 0 ] )
y i n t e r c e p t = f l o a t ( i n t e r c e p t . coords [ 0 ] [ 1 ] )
else :
x i n t e r c e p t = f l o a t ( i n t e r c e p t . coords [ 1 ] [ 0 ] )
y i n t e r c e p t = f l o a t ( i n t e r c e p t . coords [ 1 ] [ 1 ] )
else :
#Same a s o t h e r , o n l y a x e s a r e f l i p e d
try :
C = Point ( c i r c l e d a t a [ 1 ] , c i r c l e d a t a [ 0 ] ) . b u f f e r ( c i r c l e d a t a [ 2 ] )
P o i l = Point ( x a v e r a g e o i l , y a v e r a g e o i l )
i f not P o i l . w i t h i n (C) :
p r i n t ( ’ p o i n t not i n c i r c l e ’ )
r e t u r n None
except :
p r i n t ( ’ no c i r c l e f i t ’ )
r e t u r n None
i n t e r c e p t = C . i n t e r s e c t i o n (L)
i f l e n ( i n t e r c e p t . c o o r d s ) == 0 :
p r i n t ( ’ no i n t e r c e p t i o n ’ )
r e t u r n None
53
Master Thesis; K.D. van Kempen
x i n t e r c e p t = f l o a t ( i n t e r c e p t . coords [ 1 ] [ 1 ] )
y i n t e r c e p t = f l o a t ( i n t e r c e p t . coords [ 1 ] [ 0 ] )
i n t e r c e p t i o n = np . a r r a y ( [ x i n t e r c e p t , y i n t e r c e p t ] )
return interception
d e f p l o t v a l u e s ( pad img , v e r t i c a l l i n e , L , C) :
# P l o t l i n e , c i r c l e and image
ax = p l t . s u b p l o t ( 1 , 1 , 1 )
ax . s e t a s p e c t ( ’ e q u a l ’ )
p l t . imshow ( pad img )
xL , yL = L . c o o r d s . xy
xC , yC = C . e x t e r i o r . xy
i f not v e r t i c a l l i n e :
ax . p l o t (yC , xC , ’ g− ’ )
ax . p l o t ( yL , xL , ’ r− ’ )
else :
ax . p l o t (xC , yC , ’ g− ’ )
ax . p l o t ( xL , yL , ’ r− ’ )
p l t . show ( )
m normal = np . tan ( t h e t a n o r m a l )
x n o r m a l = np . a r r a y ( r a n g e ( IPx−k , IPx+k ) )
y n o r m a l = IPy + m normal ∗ ( x n o r m a l − IPx )
x normal new = x n o r m a l
y normal new = y n o r m a l
it = 0
f o r i in range ( l e n ( x normal ) ) :
i f np . c e i l ( x n o r m a l [ i ] ) < 0 o r np . c e i l ( y n o r m a l [ i ] ) < 0 :
x normal new = np . d e l e t e ( x normal new , i −i t )
y normal new = np . d e l e t e ( y normal new , i −i t )
i t +=1
x normal new = x n o r m a l
y normal new = y n o r m a l
it = 0
f o r i in range ( l e n ( x normal ) ) :
i f np . round ( x n o r m a l [ i ] ) < 0 o r np . round ( y n o r m a l [ i ] ) < 0 :
x normal new = np . d e l e t e ( x normal new , i −i t )
y normal new = np . d e l e t e ( y normal new , i −i t )
i t +=1
54
Master Thesis; K.D. van Kempen
label = 0
i f l e n ( x normal new new ) > 3:
f o r i in range ( len ( x normal new new ) ) :
i f img [ t −1 , z −1 , i n t ( np . c e i l ( x normal new new [ i ] ) ) , i n t ( np . c e i l (
y normal new new [ i ] ) ) ] == 1 :
l a b e l+=1
if l a b e l == 0 :
t h e t a c o n t a c t r a d i a n t = np . p i − t h e t a c o n t a c t r a d i a n t
t h e t a c o n t a c t d e g r e e = np . r a d 2 d e g ( t h e t a c o n t a c t r a d i a n t )
else :
t h e t a c o n t a c t d e g r e e = np . NaN
55