Download as pdf or txt
Download as pdf or txt
You are on page 1of 59

Department of Mechanical Engineering - Energy Technology

Translating digital rock imaging


techniques to the analysis of
pore-scale wetting of foams to
bridge the gap between
molecular interactions and
macro-scale wetting
Master Thesis

K.D. van Kempen 1002991

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

3 Materials and methods 15


3.1 Sample production . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2 Macro scale experiments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3 Pore-scale wetting experiments and X-Ray CT acquisition . . . . . . . . . . . . . . . . . . . . 16
3.4 Postprocessing of CT images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

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

A Contact angle calculation algorithm 39


A.1 Changes with respect to Scanziani et al. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
A.2 Code written by author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
A.3 Final total Python code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

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.

2.1 Wetting theory


General background
Wetting is a property that describes to what extent a solid prefers to be in contact with one fluid as opposed to
another fluid. Correspondingly, wetting is an important parameter when assessing multiphase flow through a
porous medium, such as porous rocks or sponges. Often, this wetting is considered for media in combination
with water (or brine) and oil. In these cases, solids that have stronger interactions with water are called
’water-wet’ and solids with a stronger interaction with oil are called ’oil-wet’. As briefly mentioned in the
Introduction, wetting can be described on several length scales, which are:

• 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].

Wetting on the molecular scale


On the molecular scale, the wetting of a medium is determined by molecular interactions between the
solid and the fluids. These molecular interactions are governed by elastic forces, van der Waals forces and
electrostatic forces between individual molecules. The combination of these forces will amount to a force-
distance curve that describes the forces acting between two molecules at different distances. An example of
such a curve can be seen in Figure 2.2 (copied from Rücker [25]). This is the first measure for wettability, as
this describes to what extent fluid molecules get attracted or repulsed by the solid phase molecules. These

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]).

Wetting on the subpore scale


On a slightly larger scale, moving from a 1D to a 2D description, molecular interactions amount to surface
energies (also referred to as surface tension, depending on the scope of the writer). These surface energies
determine how much energy is required to form or break the surface of a phase. When looking at the contact
between two phases, this surface energy is referred to as interfacial energy or interfacial tension. Still, this
property defines how much energy is required to form a certain amount of surface. An important parameter
with relation to wetting on this scale is the intrinsic contact angle of a system. This intrinsic contact angle
is defined as the angle that a droplet makes with an atomically flat, homogeneous, perfect surface in the
presence of another fluid, while in thermal equilibrium. This contact angle is typically defined through
the denser phase. The contact angle is a direct consequence of the force balance between all interfacial
tensions acting on the triple point. This triple point is the point where both the solid surface as both liquid
phases meet. In Figure 2.3a a sketch of this situation can be seen, with the intrinsic contact angle θi and
interfacial tensions between the solid and the water, the solid and the oil and the oil and water, γsw , γso and
γow respectively. As this is a force balance, it can be analytically solved, which is described by the Young
equation:
γso − γsw
cos (θi ) = (2.1)
γow
This contact angle is often used as a measure for wetting, as it is easily measured with optical techniques and
gives a direct and easy to interpret impression of wettability. For this contact angle, three different regimes
can be recognised. The first regime is the water-wet regime, where the solid prefers to be in contact with the
water. This regime is illustrated by the left droplet in Figure 2.3b, where the contact angle is less than 90
degrees. The second regime is the mixed wet regime, which is illustrated by the middle droplet in the same
image. The contact angle in this case is exactly 90 degrees and the solid has no preference for either the oil
or the water. For the most right droplet in the sketch, the contact angle is more than 90 degrees and this
situation is called oil-wet. Here, the solid prefers to be in contact with the oil. Consequently, if the contact
angle is closer to 0 or 180 degrees, the system is more strongly water-wet or oil-wet.

3
Master Thesis; K.D. van Kempen

(a) Sketch of an oil droplet on a perfect solid


surface with the intrinsic contact angle and all
interfacial tensions. This sketch illustrates the
origin of the intrinsic contact angle and forms
the basis for the Young equation.

(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

Wetting on the pore scale


Moving from the subpore to the pore scale, the description of wettability changes again. Here, wettability
is merely considered in 3 dimensions instead of 2. While on the subpore scale surfaces and surface energies
governed the behaviour, the behaviour on the pore scale is merely described by fluid distributions, internal
structure of the medium, capillary pressures and flow behaviour. The most important process to wetting
on the pore scale is capillary rise. Where surface energies governed the subpore scale, these surface energies
amount to capillary rise on the pore scale. The most basic example of capillary rise is found when a narrow
tube is placed into a water tank, as illustrated in Figure 2.6. For the purpose of this illustration, assume the
tube is water-wet. As the tube is water-wet, it will attract the water, which causes the water to rise in the
tube, up to a height h above the water surface in the water tank. This phenomenon is called capillary rise.
The relevant driving force for this capillary rise on the pore scale is capillary pressure, which is the integrated
amount of surface attraction near the walls. Capillary pressure is defined as the pressure difference between
the wetting and nonwetting phase and is given by the Young-Laplace equation as

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.

Wetting on the macro scale


On the macro scale, the relevant parameters are all considering bulk properties. The description of wet-
tability no longer concerns about interactions between molecules or surfaces, but describes properties like
saturations, capillary pressures, permeabilities and (multiphase) flow. An important realisation here is that
all wettability characteristics on the macro scale can depend on the history of the sample under consideration
and are thus not independent variables as was the case thus far.
In order to determine wetting on the macro scale, capillary pressure - saturation curves and relative permeab-
ility - saturation curves are the most important measures. Considering these capillary pressure - saturation
relations, the most important experiment is an Amott test [2]. In an Amott experiment, a sample is first
saturated with a nonwetting fluid. After this, the sample is subjected to spontaneous and forced imbibition
by the wetting fluid, and later the nonwetting fluid. In order to illustrate what happens here, Figure 2.8
shows a typical plot of the saturation against capillary pressure for a water-wet rock. At the start of the
Amott test, the sample is in the top left corner of the figure, having the maximum possible oil saturation
and, accordingly, the highest possible capillary pressure, as the sample is submerged into water, which wants
to intrude the sample. As the water intrudes the sample, the saturation increases and the capillary pressure
decreases. Once the capillary pressure is down to 0, no more water will intrude the sample, as there is no
more driving force. Now, the sample is subjected to a higher water pressure, for example by centrifuging,
which causes even more water to intrude the sample, up to the point of irreducible oil saturation, where
no more oil can be produced. Now, the process is turned around and the same steps are repeated while
oil imbibes the sample. This experiments then give rise to the two Amott indices, which together form the
Amott-Harvey index, describing wettability on the macro scale. The Amott-Harvey index is defined as
AI = Iw − Io (2.6)
where the Amott indices Iw and Io are defined as
∆Sws
Iw = (2.7)
Swi + Sor
∆Sos
Io = (2.8)
Swi + Sor
These saturations are the saturations as given in Figure 2.8, indicating the amount of spontaneous imbibition,
irreducible water saturation, irreducible oil saturation and the amount of secondary drainage respectively.

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].

2.2 Experimental characterisation of sponges


Chemical composition and surface energy
In the studies on sponges mentioned in the Introduction, the sponges that were developed were tested in
multiple ways. As these studies mainly focus on the development of the sponge, a relatively large amount of
effort is done to analyse the chemical composition and intrinsic properties of the sponge surface. In order to
do this, multiple techniques are used, such as energy-dispersive X-ray spectroscopy (EDX) [20, 23, 32] and
mass spectroscopy [7, 12] to determine the chemical composition of the sponge, inverse gas chromatography
(IGC) [11, 12] to determine the surface energy of the sponge, scanning electron microscopy (SEM) [7, 11, 12,
20, 23, 32] and atomic force microscopy (AFM) [11] to visualise the sponge surface and mechanical testing
[7, 12, 23] to see whether the applied coatings shear off under mechanical loads. These techniques are mainly
used to show that the sponge surface is indeed altered as intended and will not be further discussed, since
this is outside the scope of this study.

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

2.3 Experimental characterisation of porous rocks


Another porous material that is the subject of extensive research is porous rock in relation to oil production.
In this field of work, the behaviour of the rock is typically characterised in a different manner with more
extensive experiments, which might also be relevant for the analysis of sponges wetting. In short, all sources
on sponges only describe the wetting of the sponge on a macro scale, with sometimes a minor qualitative
discussion of the influence of roughness or other smaller scale mechanisms that might influence wetting[11].
For porous rocks, many analyses are preformed on multiple length scales, such as nano-scale roughness, the
influence of pore sizes, contact angle hysteresis, capillary pressures, saturations and permeabilities. In order
to determine these quantities, the most basic, macro-scale experiment is an imbibition, or Amott, experiment
as described in section 2.1 [2, 26]. In such an experiment, the porous rock is subjected to passive and active
(forced) imbibition to get a first impression of the wetting characteristics of the rock. In order to deepen the

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].

X-ray computed tomography measurements


A micro computed tomography (µ-CT) scanner enables to image the interior structure of a sample, based
on the differences in X-ray attenuation of the various phases that are present in the sample. In the case
of porous rocks, these phases are usually the rock itself, water (or brine) and oil. Since oil and water both
have a low X-ray attenuation coefficient one or both of these are usually doped with a contrast agent to be
able to distinguish them. One important note here is that the sample preparation in these measurements
is typically different from the previously mentioned experiments. In these CT measurements, the sample is
usually placed into a flow cell at higher pressures in order to simulate reservoir conditions. Now, the sample
is usually flushed with brine and oil consecutively [3, 17, 28, 29, 30, 31]. In some studies, the brine and oil
are flushed through the rock simultaneously, but this is done significantly less often [21]. An illustration of
this flow cell, as reported by Lin et al. [21] can be seen in Figure 2.13a.
When the sample is prepared, a CT image is obtained. Now, this CT image can be used to determine various
quantities, such as contact angles, saturations, interfacial areas, interfacial curvatures, pore sizes and with
further calculations or modelling steps even capillary pressures and permeabilities. In order to derive these
parameters, the raw CT data is usually filtered and segmented, so that the various phases are identified.
From this segmented data, the required parameters can be calculated. An example of the resulting images
as reported by Singh et al. [30] can be seen in Figure 2.13b. In Figure 2.13c, the results of a contact angle
measurement as reported by Scanziani et al.[28] can be seen. This image is also shown to illustrate that the
contact angle can have more than one value as a result of contact angle hysteresis, pore scale effects and
potential other processes. Therefore, the single contact angle as reported by most sponge studies is a major
simplification of the real behaviour of the sponge.
In some cases, a synchrotron is used as an X-ray source, which enables much lower imaging times and thus
enables the imaging of dynamic processes within the rock, such as the development of advancing and receding
contact angles [14, 18].
Besides the experimental techniques discussed thus far, studies discussing wetting of porous rocks also employ
other techniques, such as Atomic Force Microscopy measurements and permeability measurements. As these
techniques are outside the scope of this study, they will not be discussed.
What becomes immediately clear here is that the analysis of wetting related to porous rocks is done in a
much more extensive way and broader range of length scales. As a result of this, the wetting of porous rocks
is much more thoroughly described and understood, which is not the case for sponges.

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

3 Materials and methods


With a proper understanding of the theoretical background behind wetting and the corresponding exper-
imental techniques, suitable experiments for this study have been designed. This chapter will discuss the
experiments as performed in this study and elaborate on the employed techniques.

3.1 Sample production


The sponges used in this study are polyester polyurethane (PESPU) foams, coated with nanosilicon func-
tionalised with paraffin-like octadecyl ligands. These foams were designed and fabricated by Cherukupally
et al.[12] and were designed for the adsorption of oil droplets from water. By coating the PESPU foams, the
surface of the foam is altered, such that it has stronger interactions with oil. Therefore, the sponge should
have more or faster oil adsorption and be more selective towards oil instead of water.
The sponge samples were shipped in samples of 4x4x2 cm. Since the samples used in this study need to be
smaller than that, they have been cut using a hot wire as advised by Cherukupally. By cutting the sponges
this way, no strain is imposed on the sponge, so the coating cannot shear off and there is no risk of plastic
deformation due to the cutting.

3.2 Macro scale experiments


Before doing any micro-scale experiments, the macro scale behaviour is determined to get a better initial
understanding of the sponge. By doing this, a better micro-scale experiment can be developed and the
behaviour of the sponge can be compared to the data as presented by Cherukupally et al. [12]. Thereby, the
macro scale experiments provide a way to link the micro scale observations to the macro scale behaviour under
the same conditions, as the experiments proposed here differ slightly from the experiments as performed by
Cherukupally et al. In order to determine the macro scale behaviour, Amott spontaneous imbibition tests
are performed.

Amott spontaneous imbibition tests


In an Amott spontaneous imbibition test [2] (further referred to as Amott test), a sponge is first saturated
with a nonwetting fluid. When the sponge is fully saturated with the nonwetting fluid, it is submerged into a
wetting fluid. When the sponge is submerged into the wetting fluid, this fluid will start to intrude the sample
and thus displace the nonwetting fluid, because the sponge has a stronger interaction with the wetting fluid.
This amount of displaced non-wetting fluid, or production, is measured over time in a so-called Amott cell.
An Amott cell consists of a larger reservoir where the sample is located, which has a narrow, graduated end
that enables to read the produced volume. An image of the Amott cell as used in this study can be seen in
Figure 3.1. Figure 3.1a shows the Amott cell as it is used and Figure 3.1b shows the main components of the
Amott cell. An important part of the Amott cell is the yellow sample holder. This sample holder has a dual
purpose, which is to hold the sponge sample in place and make sure it has as few as possible contact with the
walls of the Amott cell. Minimising the contact with the cell walls is important, so that all accessible pores
are in contact with the surrounding fluid, and are thus not blocked. Although this experiment does not fully
describe the wetting behaviour of the sponge, it does give a first impression of the preferential wetting and
time scales of sorption.
In this study, a sponge sample of 2x2x2 cm is used. The nonwetting fluid in the Amott test is water with
0.1 M NaCl and a pH of 5.6, as Cherukupally et al.[12] reported that this will result in the best oil sorption
performance of the sponge. In order to saturate the sponge with this water (or brine), it is submerged and
gently squeezed.
The wetting fluid used in this study is dodecane. However the sponge was designed for the adsorption of
crude oil, it has been chosen not to use this, as crude oil contains some toxic chemicals and has a complicated
chemical composition. Using dodecane significantly lowers the risk of toxicity and allows the main focus of
this study to be on the wetting of the sponge on the pore scale, eliminating potential influence of the many
chemicals that are found in crude oil. Dodecane can be used as a model oil, since oil also mainly consists

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.

(a) The Amott cell when it is fully mounted.

(b) The individual parts of the Amott cell, with the reservoir (top), graduated end (middle)
and sample holder (bottom).

Figure 3.1: The Amott cell as used in this study.

3.3 Pore-scale wetting experiments and X-Ray CT acquisition


In order to study the wetting behaviour of the sponge at the pore scale, another set of experiments is
conducted. As for the macro scale experiments, the basis of the experiments here is an Amott test, however

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.

X-ray (micro)computed tomography


Basic principles of X-ray CT
X-ray computed tomography (CT) is an imaging technique that enables to take 3D images within an opaque
sample by making use of the difference in X-ray attenuation of the materials within the sample. A sketch
of a CT imaging setup can be seen in Figure 3.2. In the CT scanner, a conical X-ray beam illuminates a
sample, which is placed on a rotating stage, in front of a 2D detector. Now, the detector takes a so-called
’transmission image’. This transmission image is a 2D projection of the X-ray attenuation of the sample and
thus shows areas of higher and lower X-ray attenuation within the sample. When a transmission image is
obtained, the sample is rotated and another transmission image is taken. Typically, hundreds or thousands
of transmission images are taken to obtain a single CT scan.
Since all transmission images are taken at a different rotation position of the sample, the graylevel of each
pixel of each image represents the integrated X-ray attenuation over a different line along the sample. Due
to this, a CT reconstruction algorithm is able to combine the information of all transmission images into
a single 3D volume, where each voxel represents the X-ray attenuation of the material at the respective
position.

2D detector

Sample X-ray source

Rotation stage

Figure 3.2: A sketch of the CT image acquisition setup.

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.

Sample preparation and handling


The samples for the CT scans were prepared in a similar manner to the large scale samples. Firstly, the
sample is saturated with the same brine as for the macro scale experiment. After this, it is submerged into
dodecane, which will now intrude the sponge and displace the water.
When the sponge is submerged in the dodecane, CT scans will show the fluid distributions in the sponge and
might even give an impression of moving fluid interfaces during image acquisition, as these moving interfaces
will cause moving artifacts in the reconstructed 3D-volume, which will appear as voxels with intermediate

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

Figure 3.3: Some images of the CT sample holder

19
Master Thesis; K.D. van Kempen

3.4 Postprocessing of CT images


After all transmission images are acquired, the images are reconstructed to form a 3D volume. This is done
by the Phoenix Datos|x 2 software that comes with the CT scanner. This software can automatically correct
for beam hardening artifacts and small sample movements during image acquisition, which allows for a more
reliable image reconstruction. After image reconstruction, the adaptive Gaussian filter in VGStudio MAX
2.2 is used to filter the reconstructed image. All further image processing and analysis is done in Dragonfly
2021.3 and will be discussed later.

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.

4.1 Amott tests


Figure 4.1 shows the measured water production of two SEnS samples over time, where Figure 4.1a shows
the early measurement points that are hard to see in Figure 4.1b due to the long duration of the experiment.
The first observation that can be made here is that the sponges stop producing water after about two weeks,
once they have produced 1.7 and 1.5 ml of water. Since the dimensions of the sponge are 2x2x2 cm, meaning
that it can contain about 8 ml of fluids, the residual water saturation is about 0.79 and 0.81 for both samples.
Another observation that can be made from the production is that it is not continuous, but merely stepwise.
When the dodecane intrudes the sponge and displaces the water, the water first accumulates in a droplet
on the bottom of the sponge. This droplet first needs to reach a sufficient size before it detaches from the
sponge and falls into the graduated end of the Amott cell.
It is important to notice that the measured volumes shown in Figure 4.1 were artificially put at 0 at the start
of the experiment. As discussed in section 3.2, a little bit of water was added at the start of each experiment
in order to be able to read the produced volume. However, the amount of water that was added here did not
correspond to the first reading of the experiment. In Table 4.1 the difference between the two values can be
seen for each sample.

Table 4.1: Difference between the initially added amount of water in the Amott experiment and the first
measurement point.

Sample Difference in water volume at start of experiment [ml]


1 0.4
2 -0.6

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]

Measured water production [ml]


1.2
1.5
1

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.

Comparison to sorption experiments as performed by Cherukupally


When comparing the results of the Amott test to the sorption experiments as performed by Cherukupally
et al.[12], the results give a vastly different impression of the wettability of the sponge. In the study by
Cherukupally et al., the sponges were submerged into an emulsion of 1 g crude oil in 100 ml water and
the oil concentration in the water was measured over time. This experiment resulted in an oil removal
efficiency of 90-99% within 3 hours. Compared to the Amott experiment, the experiment as performed by
Cherukupally et al. has a much shorter time scale and seems to indicate a much better oil wetting.

4.2 Pore-scale observations


Scanning parameters
As discussed in section 3.3, several parameters can be changed regarding the CT image acquisition to improve
the image quality. Here, some images using different scanning parameters are compared to illustrate how
the settings were chosen.
Figure 4.2 shows three transmission images of the sponge using X-ray tube voltages of 50, 60 and 70 kV,
where the same window levelling was applied. When comparing these images, it appears that all three
voltages give sufficient contrast to identify the three phases (sponge, water, oil), but the signal level for a
tube voltage of 50 kV is significantly lower. When comparing the images for 60 and 70 kV, the signal levels
seem comparable. Therefore, a tube voltage of 60 kV was chosen, since this does give a higher signal level,
but also has a lower risk of beam hardening.

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.

Observations on the final scans


Having optimised the scanning parameters, the final CT scans can be analysed to draw a conclusion on the
wettability of the sponge. Before using any advanced image analysis, a first impression of the wettability of
the sponge can be obtained by a visual inspection of the scans. Figure 4.4 shows a vertical and horizontal
slice and a 3D view of a scan of the SEnS after imbibition under optimal conditions to give an initial
impression of the obtained CT scans. It is important to realise that the greylevel of the images is inverse to
the transmission images shown before. The transmission images shown before are the images as captured by
the detector of the CT scanner and are thus darker in regions of higher X-ray attenuation, as the detector
receives less radiation in these areas. When a 3D volume is reconstructed from these images, the regions
with higher X-ray attenuation are represented by brighter voxels.
In these images, the darkest phase is the dodecane, the intermediate greylevel represents the brine and the
brightest features are the sponge fibres. In the 3D view, the bright circle that can be seen in the horizontal
slice is cropped out and the darkest voxels are made transparent, so that only the water and sponge material
are shown. From these images, it can be seen that there is indeed a rather high residual water saturation,
as the most of the sponge still appears filled with brine.
One distinct feature that is found in all images is the bright ring that can be seen in the horizontal plane
of the image, which corresponds to the bright edges in the vertical view. This bright ring is a result of the
sample holder being larger than the field of view of the X-ray detector. Due to this, parts of the sample
holder will move in and out of the field of view while the sample is rotating and the X-ray attenuations of
these parts will virtually accumulate at this circle, causing it to appear as very bright. Due to this, all data
outside of this circle can be considered as unreliable, as this partially consists of information from outside
the field of view. Therefore, all information outside of this circle will be ignored.
Another important realisation on the image resolution can be drawn from Figure 4.4d. This image shows a
zoomed in 2D slice of the image, with a droplet. However no sponge material can be seen at the right side
of droplets A and B , the shape of these droplets indicates that there must be a membrane, as otherwise
this shape could never exist. Therefore, it can be concluded that there are membranes between the sponge
fibres at some points, which are thinner than the image resolution.

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

4.3 Advanced image analysis


Image segmentation
Segmentation techniques
The first step to obtain more detailed data from the CT image files from advances image analysis is to segment
the image. By segmenting the image, all voxels get labelled, such that a computer can distinguish the different
phases. In this case, these phases are the sponge material, dodecane and brine. Image segmentation is one
of the most critcal steps in the image analysis, as a wrong segmentation will cause all further analysis to
be flawed. Several techniques exist to segment an image with various degrees of complexity. The most
straightforward segmentation technique is histogram thresholding, where all voxels within a certain range of
greylevel are labelled to a certain phase. This is a very fast and straightforward method, but has a major
downside when there is not enough contrast or too much noise in an image. More advances methods, such as
K-means segmentation and watershed transforms rely on placing ’seeds’ in an image and letting these seeds
grow, based on the level of similarity of the neighbouring voxels. These methods are computationally more
expensive, but generally give better results. Lastly, machine learning and deep learning tools can be used to
segment an image. These methods rely on a user input, where a (partially) segmented image is given, which
is used to train the segmentation model. Machine learning and deep learning methods are significantly more
computationally expensive compared to the previously mentioned methods, but have the potential to give a
better segmentation, provided enough training[22]. A major downside of these methods is that the generated
segmentation models are a complete black box, so the user is unaware of how or why it is working. Thereby,
as a result of this, the user cannot perform any sensitivity analysis on the resulting segmented image, as
there are no user inputs.

Chosen segmentation technique


In this study, a deep learning segmentation model has been trained to segment the images. To illustrate this
choice, Figure 4.7 shows two images that highlight features of the CT image files that cause the traditional
segmentation methods to give too poor results.
Figure 4.7a shows a full horizontal 2D slice of a CT image. As discussed, parts of the sample holder moving
outside of the field of view cause the bright ring to appear here. Besides this, the image also contains a
gradual increase in brightness towards the edges of the image. This effect is much weaker than the bright
ring, but does prohibit the use of thresholding segmentation, as the increase in brightness towards the edges
is higher than the difference in greylevel between brine and sponge material.
Figure 4.7b shows a detail of a horizontal 2D slice to further illustrate why thresholding will not work, as well
as watershed segmentation and other region growing techniques. As can be seen, the noise level here is in a
similar range as the contrast between the brine and sponge material, which makes thresholding impossible.
This noise level also makes techniques like watershedding impossible. A watershed transform relies on an
image where the edges between phases are rather clearly defined, as these edges will define to what extent
and in what direction regions can be grown. In this case, the noise in the image will give rise to a vast
amount of edges in the image when an edge finding filter is used. Therefore, any region growing technique
cannot properly distinguish the brine from the sponge material. This noise could be reduced by filtering the
image. However, as some of the sponge fibres or the membranes between them are just a few voxels wide,
any noise-reducing filter would also filter out the sponge material.
Figure 4.8 shows a full horizontal image slice and a detail of a horizontal image slice of a CT scan of the
SEnS to illustrate the finally achieved segmentation using the deep learning segmentation model.

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.

4.4 Pore-scale contact angles


Contact angle calculation algorithm
In order to calculate the contact angles of the oil/water/sponge system, the method as developed by Scan-
ziani et al. [28] has been used. Since a different image processing software was used in this study, the code
by Scanziani has been transcoded to work with the available software (Dragonfly 2121.3). While developing
this code, the Dragonfly team helped to implement several parts of it into the software. In order to do this,
the process was split into multiple parts, which will be explained below. While developing the contact angle
calculation algorithm, some improvements have also been implemented to make the code more reliable or
improve the performance. This section will discuss the general procedure of the contact angle calculation
algorithm. A more in-depth explanation with a discussion on the improvements and other differences com-
pared to the code as developed by Scanziani et al. can be seen in Appendix A. The starting point of this
algorithm is an already segmented image.

Step 1: triple line extraction


The first step in the calculation of the contact angle is the determination of the triple line. This triple line
(or three-phase line) is the line where the three phases (water, oil and sponge material) meet. At any point
(three-phase voxel) on this triple line, the contact angle can be determined. The value for the contact angle
might be vary along this triple line, as the inner surface of the sponge is not flat, which, along with other
processes, will cause contact angle hysteresis. In Figure 4.10, an illustration is shown of a droplet onto a
sponge fibre, with the triple line voxels marked blue. In the image, the white part is the sponge fibre, and

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.

Step 2: Extracting oblique slices


Now the triple line is found, an oblique slice is extracted at each three-phase voxel. This oblique slide will
be perpendicular to the three-phase line, as this is the image plane on which the contact angle should be
determined. The orientation of this oblique slice can be rather easily found, as the normal of this plane
is given by the direction of the triple line. Before evaluating the direction of the triple line, all points are
subjected to a moving mean. This is done, because the triple line is thus far only defined on the discrete
voxels, which would result in a rater irregular triple line. Eventually, on each of the oblique slices, so on each
triple point, the contact angle will be determined. The 2D image that is obtained here is now forwarded
to the contact angle calculation algorithm to extract the contact angle. Figure 4.11 shows an illustration of
how the oblique slice is extracted from the 3D image.

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

Step 3: calculating the contact angle from the oblique slices


Now a 2D oblique slice is obtained, the contact angle can be extracted from this slice. In order to do this,
the first step is to evaluate which sponge pixels border on a non-sponge pixel. These points are then used,
within a small interrogation window around the triple point, to fit a straight line to the solid interface. In a
similar manner, the fluid-fluid interface pixels are identified and a circular fit is made on these points.
Now the both interfaces are fitted, the interception points of the line and circle are calculated. Since a line
and a circle mostly have 2 interception points (except in case of a tangent line or when they don’t intercept
at all), only the interception which lies at the triple point should be considered. Due to this strategy, the
code is rather insensitive to the way the triple point is defined in step 1, as this triple point only serves to
find the correct interception of the line and circle fit, which is simply the interception closest to the triple
point. Knowing the correct interception of the line and circle fit, the angle between the two fits can be
calculated by evaluating the slope of the line and the local slope of the circle.
The last step in the determination of the contact angle is to check whether the contact angle is acute or
obtuse. Contact angles are usually defined through the denser phase, but thus far only the interfaces have
been considered, so it is still unknown whether the calculated angle is measured through the denser or the
lighter phase. In order to check this, a line is drawn through the triple point, perpendicular to the circular fit
of the fluid-fluid interface. If this line passes through the lighter phase, the contact angle is acute. If this line
passes through the denser phase, the contact angle is obtuse. This last step is illustrated by Figure 4.12b.
Up to this step, the contact angle was only known as the α as shown in the image. When the angle α
is measured through the oil, as illustrated in the right part, the contact angle is given by θ = 180 − α.
Otherwise, θ = α

(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.

Scanziani et al.[28] Transcoded version Transcoded and optimised


Mean contact angle [deg] 42.2 42.1 37.3
Standard deviation [deg] 14.6 29.6 22.7
Runtime of code unknown ∼30 min ∼30 s

Figure 4.13: A 2D slice of the validation data. Adapted from Scanziani et al.[28].

Resulting contact angles


Differences with validation data
One important difference between the validation dataset is that the CT image of the sponge contains small
fibres, whereas the solid material in the validation data was thicker. Therefore, when calculating the line fit
on the solid interface, the line fitting might be off. As shown in Figure 4.14, when a fibre is thin enough,
the line fitting procedure will not only see the interface at the side of the droplet, but also the interface at
the other end of the fibre, resulting in a fit going through the center of the fibre instead of the surface. This
is easily resolved by labelling the water at the other end of the fibre as fibre material as well. This can be
done when single water droplets are selected when calculating the contact angle.

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.

Selected droplet for contact angle calculation


Whereas the optimal segmentation was selected for the analysis of the sponge, the segmentation still contains
some flaws which could severely affect the result of the contact angle calculation. An example of this can
be seen in Figure 4.15, where a part of the sponge fibre between oil and water is missing. This would result
in the code finding a triple point and calculating a contact angle here, whereas there is no triple point here.
Thereby, the sponge fibre on such points is so thin that the fitting procedures would not be able to provide
a correct fit. This slight flaw in the segmentation is not expected to have an important influence on the
previously discussed results, as these errors are expected to pose only a small difference in the total volume
and interfacial areas of the image.

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

Figure 4.16: Contact angle distribution for the selected droplet.

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.

4.5 Overall discussion on wettability


Combining all the measurements performed on the sponge, it appears much less oil-wet than would be
expected from the data as reported by Cherukupally et al. Amott spontaneous imbibition tests showed a
rather high residual water saturation of about 80%. On the micro scale, a different residual water saturation
was found, of 57%. This rather big difference in residual saturation is explained by the fact that the oil only
imbibes the outer regions of the sponge. As the samples for the CT scans are much smaller, these samples
have a relatively much larger outer surface area. Therefore, these CT samples will exhibit relatively more
oil imbibition.
On the pore scale, visual observations give a rather contradictory impression of wettability. On the one
hand, the dodecane seems to intrude the sponge rather poorly. On the other hand, this might be caused
by sub-resolution membranes hindering the intrusion of oil in the sponge. When the fluid distributions
in the sponge are compared to situations with a lower expected oil wetting, the scans do show expected
behaviour. The less oil-wet samples exhibit more residual water droplets in regions with higher curvature,
indeed indicating a more water-wet situation.
Lastly, contact angle measurements show behaviour corresponding to the observed wetting situation for the
sample prepared with pH=7, where the average contact angle of a residual water droplet is 76.2 degrees.

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

[18] C. Garing, J. A. de Chalendar, M. Voltolini, J. B. Ajo-Franklin, and S. M. Benson. Pore-scale capillary


pressure analysis using multi-scale X-ray micromotography. Advances in Water Resources, 104:223–241,
2017.
[19] Katherine A. Klise, Dylan Moriarty, Hongkyu Yoon, and Zuleima Karpyn. Automated contact angle
estimation for three-dimensional x-ray microtomography data. Advances in Water Resources, 95:152–
160, 2016. Pore scale modeling and experiments.
[20] B. Li, X. Liu, X. Zhang, J. Zou, W. Chai, and Y. Lou. Rapid adsorption for oil using superhydro-
phobic and superoleophilic polyurethane sponge. Journal of Chemical Technology and Biotechnology,
90(11):2106–2112, 2015.
[21] Q. Lin, B. Bijeljic, R. Pini, M. J. Blunt, and S. Krevor. Imaging and Measurement of Pore-Scale Inter-
facial Curvature to Determine Capillary Pressure Simultaneously With Relative Permeability. Water
Resources Research, 54(9):7046–7060, 2018.
[22] Geert Litjens, Thijs Kooi, Babak Ehteshami Bejnordi, Arnaud Arindra Adiyoso Setio, Francesco Ciompi,
Mohsen Ghafoorian, Jeroen A.W.M. van der Laak, Bram van Ginneken, and Clara I. Sánchez. A survey
on deep learning in medical image analysis. Medical Image Analysis, 42:60–88, 2017.
[23] H. Y. Mi, X. Jing, H. X. Huang, and L. S. Turng. Controlling Superwettability by Microstructure and
Surface Energy Manipulation on Three-Dimensional Substrates for Versatile Gravity-Driven Oil/Water
Separation. ACS Applied Materials and Interfaces, 9(43):37529–37535, 2017.
[24] Gargi Raina. Atomic force microscopy as a nanometrology tool: Some issues and future targets.
MAPAN, 12 2013.
[25] M. Rücker. Wettability and wettability alteration at the pore- and nano- scales. PhD thesis, Imperial
College London, 2018.
[26] M. Rücker, W.B. Bartels, G. Garfi, M. Shams, T. Bultreys, M. Boone, S. Pieterse, G.C. Maitland,
S. Krevor, V. Cnudde, H. Mahani, S. Berg, A. Georgiadis, and P.F. Luckham. Relationship between
wetting and capillary pressure in a crude oil/brine/rock system: From nano-scale to core-scale. Journal
of Colloid and Interface Science, 562:159 – 169, 2020.
[27] George Claudiu Savulescu, Maja Rucker, Alessio Scanziani, Ronny Pinni, Apostolos Georgiadis, and
Paul F Luckham. 3D characterization of seawater micro-droplets in n-decane on a calcite surface using
atomic force microscopy. Journal of Colloid and Interface Science (submitted), pages 1–13, 2021.
[28] A. Scanziani, K. Singh, M. J. Blunt, and A. Guadagnini. Automatic method for estimation of in situ
effective contact angle from X-ray micro tomography images of two-phase flow in porous media. Journal
of Colloid and Interface Science, 496(November 2019):51–59, 2017.
[29] A. Scanziani, K. Singh, T. Bultreys, B. Bijeljic, and M. J. Blunt. In situ characterization of immiscible
three-phase flow at the pore scale for a water-wet carbonate rock. Advances in Water Resources,
121(June):446–455, 2018.
[30] K. Singh, B. Bijeljic, and M. J. Blunt. Imaging of oil layers, curvature and contact angle in a mixed-wet
and a water-wet carbonate rock. Water Resources Research, 52(3):1716–1728, 2016.
[31] C. Sun, J. E. McClure, P. Mostaghimi, A. L. Herring, M. Shabaninejad, St. Berg, and R. T. Armstrong.
Linking continuum-scale state of wetting to pore-scale contact angles in porous media. Journal of
Colloid and Interface Science, 561:173–180, 2020.
[32] H. Wang, J. Yang, X. Liu, Z. Tao, Z. Wang, and R. Yue. A robust 3D superhydrophobic sponge for in
situ continuous oil removing. Journal of Materials Science, 54(2):1255–1266, 2019.
[33] Robert N. Wenzel. Resistance of solid surfaces to wetting by water. Industrial & Engineering Chemistry,
28(8):988–994, 1936.
[34] Tak Sing Wong, Adam Po Hao Huang, and Chih Ming Ho. Wetting behaviors of individual nanostruc-
tures. Langmuir, 25(12):6599–6603, 2009.

38
Master Thesis; K.D. van Kempen

A Contact angle calculation algorithm


A.1 Changes with respect to Scanziani et al.
Step1: triple line extraction
In order to find the triple line, Scanziani labelled all voxels that neighbour two other phases (for example
a sponge voxel that neighbours a water and an oil voxel) as three-phase contact voxels. Since there are 3
phases, the triple line in this case will have a width of 3 voxels (one in the oil phase, one in the water phase
and one in the solid phase). An illustration of this is shown in Figure A.1. In the current study, the triple
line is only defined on the voxels of one target phase (so either sponge, water or oil), because this is imposed
by the Dragonfly software. This should have no effect on the final result, since the triple line only serves to
find the orientation of the image plane from which the contact angle will be calculated. The only difference
now is that the triple line will be only one voxel wide, instead of three voxels wide. The choice of the target
phase here might cause the direction of the triple line to be slightly different, but this effect is expected to
be negligible.
Another difference here is that the code by Scanziani first found all triple points, then exported a 3D
volume with only the triple line and then scanned this entire 3D volume in a separate Matlab script to
find the triple points again and find the direction of the triple line at each point. In the current code, the
3D volume is only scanned once to find the triple line, after which the coordinates of the triple point are
immediately saved. Due to this, the 3D volume only needs to be scanned once instead of twice. Thereby, all
calculations happen within the Dragonfly software, so no separate script is required. This part of the code
already existed in Dragonfly.

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].

Step2: Extraction of oblique slices


This part of the codes only differs from the code by Scanziani et al. on one point, which is the implementation
of the moving mean on the triple line. Scanziani et al. used a moving mean filter that used the point under
consideration and 3 points to one side of this point. Here, the moving mean is calculated using two points
on both sides of the point under consideration. It is expected that this will result in a better description of
the triple line, as there is a risk of losing valuable information when only looking to one side of the point
under consideration. This part of the code was fully developed by the Dragonfly team.

Step3: calculating the contact angle from the oblique slices


The most important improvement that has been implemented is related to the line fitting procedure of the
solid interface. Since this line fitting relies on a fit of the form y = mx + b, the line fitting will not work
for vertical (or very steep) lines, because the slope will be infinite and there will be no intercept with the
vertical axis, so b will be undetermined. In order to solve this, a simple check is added to the script. This

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).

A.2 Code written by author


This part of the code was mostly written by the author, however some parts of the code have later been
improved by the Dragonfly team, as discussed in the previous section. The imports of all required packages
is left out here; the full code, inclusing all required packages can be found in the next section.
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 :
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 ] )

# computing moments ( n o t e : a l l moments w i l l be normed , i . e . d i v i d e d by n )


Mxx=0
Myy=0
Mxy=0
Mxz=0
Myz=0
Mzz=0

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

A2 = 4∗ Cov xy − 3∗Mz∗Mz − Mzz


A1 = Mzz∗Mz + 4∗ Cov xy ∗Mz − Mxz2 − Myz2 − Mz∗Mz∗Mz
A0 = Mxz2∗Myy + Myz2∗Mxx − Mzz∗ Cov xy − 2∗Mxz∗Myz∗Mxy + Mz∗Mz∗ Cov xy
A22 = A2 + A2

e p s i l o n =1e −12
ynew=1e+20
IterMax=20
xnew = 0

# Newton ’ s method s t a r t i n g a t x=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 abs ( ynew ) > abs ( y o l d ) :


p r i n t ( ’ Newton−P r a t t g o e s wrong d i r e c t i o n : | ynew | > | y o l d | ’ )
xnew = 0
break

Dy = A1 + xnew ∗ ( A22 + 16∗ xnew∗xnew )


x o l d = xnew
xnew = x o l d − ynew/Dy

i f abs ( ( xnew−x o l d ) /xnew ) < e p s i l o n :


break

if i t e r >= ( IterMax −1) :


p r i n t ( ’ Newton−P r a t t w i l l not c o n v e r g e ’ )
xnew = 0

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

DET = xnew∗xnew − xnew∗Mz + Cov xy


Ce nt er = np . a r r a y ( [ Mxz∗ (Myy−xnew )−Myz∗Mxy, Myz∗ (Mxx−xnew )−Mxz∗Mxy ] ) /DET/2
Radius = s q r t ( np . dot ( Center , C en ter ) + Mz + 2∗ xnew )
Ce nt er = Ce nte r + c e n t r o i d

Par = np . append ( Center , Radius )

r e t u r n Par

def compute CA from fitdata ( l i n e , v e r t i c a l , c i r c , i n t e r c e p t ) :


i f v e r t i c a l == F a l s e :
t h e t a s e c a n t = np . a r c t a n ( l i n e [ 0 ] )
i f theta secant < 0:
t h e t a s e c a n t += np . p i
else :
t h e t a s e c a n t = np . p i /2 − np . a r c t a n ( l i n e [ 0 ] )
i f theta secant < 0:
t h e t a s e c a n t += np . p i

cos theta circle = ( intercept [0] − circ [0] ) / circ [2]


sin theta circle = ( intercept [1] − circ [1] ) / circ [2]

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

return theta contact radiant

d e f f i t l i n e a r r o c k i n t e r f a c e ( img , IPx , IPy , k l i n e ) :


# I n i t i a l i s e arrays
v e r t i c a l l i n e = False
Lx = np . a r r a y ( [ ] , dtype=i n t )
Ly = np . a r r a y ( [ ] , dtype=i n t )

t , z , nrows , n c o l s = img . shape

# Add padding i n c a s e t h e k−l i n e i s a t t h e l i m i t s o f t h e image


pad img = np . pad ( img [ t −1 , z −1 , : , : ] , 1 , mode= ’ c o n s t a n t ’ )
# 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 )

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 ) ) ] ] )
# Keep i n d i c e s i f n e i g h b o r s a r e water o r 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 ) | ( n e i g h b o r s == 2 ) , a x i s =0) )
Lx = np . append ( Lx , y i d x [ r e s t i n d i c e s [ 0 ] ] )
Ly = np . append ( Ly , x i d x [ r e s t i n d i c e s [ 0 ] ] )

#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 )

return l i n e a r f i t , vertical line

p r i n t ( ’ no l i n e a r f i t ’ )
r e t u r n None , None

d e f f i t c i r c u l a r d r o p l e t i n t e r f a c e ( img , IPx , IPy , k l i n e ) :


t , z , nrows , n c o l s = img . shape

#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

# Add padding i n c a s e t h e k−l i n e i s a t t h e l i m i t s o f t h e image


pad img = np . pad ( img [ t −1 , z −1 , : , : ] , 1 , mode= ’ c o n s t a n t ’ )
#Find t h e f l u i d −f l u i d i n t e r f a c e
y i n d i c e s o i l , x i n d i c e s o i l = np . where ( pad img [ max ( 0 , IPy−k l i n e ) : min ( nrows , IPy+k l i n e
),
max ( 0 , IPx−k l i n e ) : min ( n c o l s , IPx+k l i n e ) ] == 2 )

# 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

# keep a v e r a g e p o i n t o f o i l t o make s u r e c i r c l e is fit right


x a v e r a g e o i l = np . mean ( x i d x )
y a v e r a g e o i l = np . mean ( y i d x )

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

if 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 ] [ 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 [ 0 ] [ 0 ] )
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 ] [ 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 ( )

d e f a c u t e o r o b t u s e C A ( img , IPx , IPy , c i r c , t h e t a c o n t a c t r a d i a n t ) :


t , z , nrows , n c o l s = img . shape
k=i n t ( 5 0 )
c o s t h e t a n o r m a l = ( IPx − c i r c [ 0 ] ) / c i r c [ 2 ]
s i n t h e t a n o r m a l = ( IPy − c i r c [ 1 ] ) / c i r c [ 2 ]
t h e t a n o r m a l = np . a r c t a n 2 ( s i n t h e t a n o r m a l , c o s t h e t a n o r m a l )

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 new=x normal new


y normal new new=y normal new
it = 0
f o r i i n r a n g e ( l e n ( x normal new ) ) :
i f np . c e i l ( x normal new [ i ] ) >= n c o l s o r np . c e i l ( y normal new [ i ] ) >= nrows :
x normal new new = np . d e l e t e ( x normal new new , i −i t )
y normal new new = np . d e l e t e ( y normal new new , i −i t )
i t +=1

i f l e n ( x normal new new ) < 2 :


y n o r m a l = np . a r r a y ( r a n g e ( IPy−k , IPy+k ) )
x n o r m a l = IPx + 1 / m normal ∗ ( y n o r m a l − IPy )

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

x normal new new=x normal new


y normal new new=y normal new
it = 0
f o r i i n r a n g e ( l e n ( x normal new ) ) :
i f np . round ( x normal new [ i ] ) >= n c o l s o r np . round ( y normal new [ i ] ) >= nrows :
x normal new new = np . d e l e t e ( x normal new new , i −i t )
y normal new new = np . d e l e t e ( y normal new 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

return theta contact degree

A.3 Final total Python code


”””

: 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

from O R S S e r v i c e C l a s s . menuItems . contextualMenuItem imp ort ContextualMenuItem


from O R S S e r v i c e C l a s s . actionAndMenu . menu i mp ort Menu
from O R S S e r v i c e C l a s s . d e c o r a t o r s . i n f r a s t r u c t u r e i mp ort i n t e r f a c e M e t h o d
from O r s H e l p e r s . L i s t H e l p e r imp or t L i s t H e l p e r
from ORSModel im po rt ROI , Channel , Graph , R e c t a n g l e , P r o g r e s s , ArrayDouble , Vector3 ,
createNumpyArrayFromChannel , DimensionUnit
from COMWrapper . ORS def i mp ort ORS PB WORKING
from O R S S e r v i c e C l a s s . d e c o r a t o r s . d e c o r a t o r s i mp ort showWaitCursorWhileExecuting ,
run in background waiting until finished

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

isThreeROIs = [ i s i n s t a n c e ( obj , ROI) f o r o b j i n a C o l l e c t i o n O f O b j e c t s ] . count ( True ) ==


3
isOneGraph = [ i s i n s t a n c e ( obj , Graph ) f o r o b j i n a C o l l e c t i o n O f O b j e c t s ] . count ( True ) ==
1
r e t u r n isOneGraph and isThreeROIs

@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
”””

collectionString = ListHelper . asPythonCollectionString ( aCollectionOfObjects )


myMenu = Menu( t i t l e = ’Add T r i p l e P o i n t Contact Angle t o Graph ’ ,
id =’
addTriplePointContactAngleVertexScalarValue 556ccc1bac5511eb87360c9d9276734f
’,
s e c t i o n= ’ t o o l s ’ ,
a c t i o n= ’
addTriplePointContactAngleVertexScalarValue 556ccc1bac5511eb87360c9d9276734f
. menuItemEntryPoint ( { c o l l e c t i o n } ) ’ . f o r m a t ( c o l l e c t i o n=s t r (
collectionString )))
r e t u r n myMenu

@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 .
”””

aCollectionOfObjects = ListHelper . fromPythonCollection ( c o l l e c t i o n S t r i n g ,


a s P y t h o n L i s t=True )
rois = []
aGraph = None
for object in aCollectionOfObjects :
i f i s i n s t a n c e ( o b j e c t , Graph ) :
aGraph = o b j e c t
else :
r o i s . append ( o b j e c t )

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

: param aGraph : c r e a t e d Graph


: t y p e aGraph : ORSModel . o r s . Graph
: param e l e c t r o l y t e R O I : background phase r o i
: t y p e e l e c t r o l y t e R O I : ORSModel . o r s . ROI
: param f i r s t C o n d u c t o r R O I : f i r s t c o n d u c t o r phase r o i
: t y p e f i r s t C o n d u c t o r R O I : ORSModel . o r s . ROI
: param secondConductorROI : s e c o n d c o n d u c t o r phase r o i
: t y p e secondConductorROI : ORSModel . o r s . ROI
: param p r o g r e s s : a p r o g r e s s bar
: t y p e p r o g r e s s : ORSModel . o r s . P r o g r e s s
”””

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

# S i z e and s p a c i n g i s from t h e i n p u t ROI


recSizeInVoxels = i n t ( electrolyteROI . getXSize () ∗0.2)
r e c S p a c i n g = e l e c t r o l y t e R O I . g e tX S p a c i n g ( )
# C r e a t e smoothed c u r v e with 4 v a l u e s
arrayNewYValues = ArrayDouble ( )
arrayNewYValues . s e t S i z e ( v e r t e x C o u n t )
arrayNewYValues . s e t A l l ( −1)
y0 = y1 = y2 = y3 = y4 = 0
f o r vertexIndex in range ( vertexCount ) :
# g e t 2 p o i n t s b e f o r e and 2 p o i n t s a f t e r
previousVertexIndex = predecessorsAndSuccessors . at (2∗ vertexIndex )
# Current v e r t e x
y0 = v e r t i c e s . a t ( 3 ∗ v e r t e x I n d e x + 1 )
# Preceding v e r t i c e s
i f not p r e v i o u s V e r t e x I n d e x == −1:
y1 = v e r t i c e s . a t ( 3 ∗ p r e v i o u s V e r t e x I n d e x + 1 )
previousPreviousVertexIndex = predecessorsAndSuccessors . at (2∗
previousVertexIndex )
i f not p r e v i o u s P r e v i o u s V e r t e x I n d e x == −1:
y2 = v e r t i c e s . a t ( 3 ∗ p r e v i o u s P r e v i o u s V e r t e x I n d e x + 1 )
# Next v e r t i c e s
n e x t V e r t e x 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)
i f not n e x t V e r t e x I n d e x == − 1 :
y3 = v e r t i c e s . a t ( 3 ∗ n e x t V e r t e x I n d e x + 1 )
n e x t N e x t V e r t e x 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 ∗ n e x t V e r t e x I n d e x +1)
i f not n e x t N e x t V e r t e x I n d e x == −1:
y4 = v e r t i c e s . a t ( 3 ∗ n e x t N e x t V e r t e x I n d e x + 1 )

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

# C r e a t e p l a n e normal t o v e r t e x ( u s e v e r t e x b e f o r e and a f t e r t o compute )


currentVertex = Vector3 ( v e r t i c e s . at (3∗ vertexIndex ) ,
arrayNewYValues . a t ( v e r t e x I n d e x ) ,
v e r t i c e s . at (3∗ vertexIndex + 2) )
# No s u c c e s s o r , u s e p r e v i o u s and c u r r e n t v e r t i c e s
i f t a r g e t I n d e x == −1:
f i r s t V e r t e x = Vector3 ( v e r t i c e s . at (3∗ sourceIndex ) ,
arrayNewYValues . a t ( s o u r c e I n d e x ) ,
v e r t i c e s . at (3∗ sourceIndex + 2) )
normalDirectionOfPlane : Vector3 = currentVertex − f i r s t V e r t e x
# Use n e x t and c u r r e n t v e r t i c e s
else :
l a s t V e r t e x = Vector3 ( v e r t i c e s . at (3∗ t a r g e t I n d e x ) ,
arrayNewYValues . a t ( t a r g e t I n d e x ) ,
v e r t i c e s . at (3∗ targetIndex + 2) )
normalDirectionOfPlane : Vector3 = l a s t V e r t e x − currentVertex

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 ] )

# computing moments ( n o t e : a l l moments w i l l be normed , i . e . d i v i d e d by n )


Mxx=0
Myy=0
Mxy=0
Mxz=0
Myz=0
Mzz=0

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

A2 = 4∗ Cov xy − 3∗Mz∗Mz − Mzz


A1 = Mzz∗Mz + 4∗ Cov xy ∗Mz − Mxz2 − Myz2 − Mz∗Mz∗Mz
A0 = Mxz2∗Myy + Myz2∗Mxx − Mzz∗ Cov xy − 2∗Mxz∗Myz∗Mxy + Mz∗Mz∗ Cov xy
A22 = A2 + A2

e p s i l o n =1e −12
ynew=1e+20

50
Master Thesis; K.D. van Kempen

IterMax=20
xnew = 0

# Newton ’ s method s t a r t i n g a t x=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 abs ( ynew ) > abs ( y o l d ) :


p r i n t ( ’ Newton−P r a t t g o e s wrong d i r e c t i o n : | ynew | > | y o l d | ’ )
xnew = 0
break

Dy = A1 + xnew ∗ ( A22 + 16∗ xnew∗xnew )


x o l d = xnew
xnew = x o l d − ynew/Dy

i f abs ( ( xnew−x o l d ) /xnew ) < e p s i l o n :


break

if i t e r >= ( IterMax −1) :


p r i n t ( ’ Newton−P r a t t w i l l not c o n v e r g e ’ )
xnew = 0

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

DET = xnew∗xnew − xnew∗Mz + Cov xy


Ce nt er = np . a r r a y ( [ Mxz∗ (Myy−xnew )−Myz∗Mxy, Myz∗ (Mxx−xnew )−Mxz∗Mxy ] ) /DET/2
Radius = s q r t ( np . dot ( Center , C en ter ) + Mz + 2∗ xnew )
Ce nt er = Ce nte r + c e n t r o i d

Par = np . append ( Center , Radius )

r e t u r n Par

def compute CA from fitdata ( l i n e , v e r t i c a l , c i r c , i n t e r c e p t ) :


i f v e r t i c a l == F a l s e :
t h e t a s e c a n t = np . a r c t a n ( l i n e [ 0 ] )
i f theta secant < 0:
t h e t a s e c a n t += np . p i
else :
t h e t a s e c a n t = np . p i /2 − np . a r c t a n ( l i n e [ 0 ] )
i f theta secant < 0:
t h e t a s e c a n t += np . p i

cos theta circle = ( intercept [0] − circ [0] ) / circ [2]


sin theta circle = ( intercept [1] − circ [1] ) / circ [2]

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

return theta contact radiant

d e f f i t l i n e a r r o c k i n t e r f a c e ( img , IPx , IPy , k l i n e ) :


# I n i t i a l i s e arrays
v e r t i c a l l i n e = False
Lx = np . a r r a y ( [ ] , dtype=i n t )
Ly = np . a r r a y ( [ ] , dtype=i n t )

t , z , nrows , n c o l s = img . shape

# Add padding i n c a s e t h e k−l i n e i s a t t h e l i m i t s o f t h e image


pad img = np . pad ( img [ t −1 , z −1 , : , : ] , 1 , mode= ’ c o n s t 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 )

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 ) ) ] ] )
# Keep i n d i c e s i f n e i g h b o r s a r e water o r 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 ) | ( n e i g h b o r s == 2 ) , a x i s =0) )
Lx = np . append ( Lx , y i d x [ r e s t i n d i c e s [ 0 ] ] )
Ly = np . append ( Ly , x i d x [ r e s t i n d i c e s [ 0 ] ] )

#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 )

return l i n e a r f i t , vertical line

p r i n t ( ’ no l i n e a r f i t ’ )
r e t u r n None , None

d e f f i t c i r c u l a r d r o p l e t i n t e r f a c e ( img , IPx , IPy , k l i n e ) :


t , z , nrows , n c o l s = img . shape

#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

# Add padding i n c a s e t h e k−l i n e i s a t t h e l i m i t s o f t h e image


pad img = np . pad ( img [ t −1 , z −1 , : , : ] , 1 , mode= ’ c o n s t a n t ’ )
#Find t h e f l u i d −f l u i d i n t e r f a c e
y i n d i c e s o i l , x i n d i c e s o i l = np . where ( pad img [ max ( 0 , IPy−k l i n e ) : min ( nrows , IPy+k l i n e
),
max ( 0 , IPx−k l i n e ) : min ( n c o l s , IPx+k l i n e ) ] == 2 )

# 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

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

# keep a v e r a g e p o i n t o f o i l t o make s u r e c i r c l e is fit right


x a v e r a g e o i l = np . mean ( x i d x )
y a v e r a g e o i l = np . mean ( y i d x )

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

if 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 ] [ 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 [ 0 ] [ 0 ] )
else :

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 ( )

d e f a c u t e o r o b t u s e C A ( img , IPx , IPy , c i r c , t h e t a c o n t a c t r a d i a n t ) :


t , z , nrows , n c o l s = img . shape
k=i n t ( 5 0 )
c o s t h e t a n o r m a l = ( IPx − c i r c [ 0 ] ) / c i r c [ 2 ]
s i n t h e t a n o r m a l = ( IPy − c i r c [ 1 ] ) / c i r c [ 2 ]
t h e t a n o r m a l = np . a r c t a n 2 ( s i n t h e t a n o r m a l , c o s t h e t a n o r m a l )

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 new=x normal new


y normal new new=y normal new
it = 0
f o r i i n r a n g e ( l e n ( x normal new ) ) :
i f np . c e i l ( x normal new [ i ] ) >= n c o l s o r np . c e i l ( y normal new [ i ] ) >= nrows :
x normal new new = np . d e l e t e ( x normal new new , i −i t )
y normal new new = np . d e l e t e ( y normal new new , i −i t )
i t +=1

i f l e n ( x normal new new ) < 2 :


y n o r m a l = np . a r r a y ( r a n g e ( IPy−k , IPy+k ) )
x n o r m a l = IPx + 1 / m normal ∗ ( y n o r m a l − IPy )

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

x normal new new=x normal new


y normal new new=y normal new
it = 0
f o r i i n r a n g e ( l e n ( x normal new ) ) :
i f np . round ( x normal new [ i ] ) >= n c o l s o r np . round ( y normal new [ i ] ) >= nrows :

54
Master Thesis; K.D. van Kempen

x normal new new = np . d e l e t e ( x normal new new , i −i t )


y normal new new = np . d e l e t e ( y normal new 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

return theta contact degree

55

You might also like