1.2. Usage
This package provides the handy Fringes class,
which handles all the required parameters
for configuring the fringe pattern sequence
and provides methods for encoding and decoding them.
1.2.1. Script
You instantiate, parameterize and deploy the Fringes class:
from fringes import Fringes # import the Fringes class
f = Fringes() # instantiate Fringes object
1.2.1.1. Configure
All parameters are accessible by the respective attributes
of the Fringes instance.
They are implemented as properties
(managed attributes), which are parsed when set.
Note that some attributes have sub-dependencies,
hence dependent attributes might change as well.
Circular dependencies are resolved automatically.
f.X = 1920 # set width of fringe patterns to screen width
f.Y = 1080 # set height of fringe patterns to screen height
f.N = 4 # set number of shifts
f.v = [9, 10] # set spatial frequencies
T = f.T # get number of frames
1.2.1.2. Encode
For generating the fringe pattern sequence I, use the method encode().
It returns a Numpy array
in vshape() (frames T, width X,
height Y, color channels C).
I = f.encode() # encode fringe patterns
1.2.1.3. Record
Now display each frame of the fringe pattern sequence on a screen and capture the scene with a camera according to the following pseudocode (a minimal working example is given in the example below):
# allocate image stack
Irec = []
for t in range(f.T):
# display frame on screen
frame = I[t]
...
# capture scene with camera
image = ...
# append to image stack
Irec.append(image)
1.2.1.4. Decode
For analyzing (recorded) fringe patterns Irec, use the method decode().
It returns the Numpy arrays brightness a, modulation b and (screen) coordinate x.
a, b, x = f.decode(Irec) # decode fringe patterns
Note
For the computationally expensive decode()-function
we make use of the just-in-time compiler Numba.
During the first execution, an initial compilation is executed.
This can take several tens of seconds up to single digit minutes, depending on your CPU and energy settings.
However, for any subsequent execution, the compiled code is cached and the code of the function runs much faster,
approaching the speeds of code written in C.
1.2.1.5. Example
The only hardware you need is a screen and a camera. The setup can be as simple as only using your notebook’s screen and integrated camera, cf. Fig. 1.1:
Fig. 1.1 Measurement setup.
Make sure the reflected fringe pattern is visible by the camera. Also, make sure to focus onto the test object and adjust the exposure settings of the camera. Then you can use the following code snipped to record and decode your own dataset:
1"""Use the `Fringes` package to encode, record and decode data."""
2
3import cv2
4from fringes import Fringes
5import numpy as np
6
7# prepare window in which the fringe pattern sequence will be shown in fullscreen mode
8cv2.namedWindow("Fringes", cv2.WND_PROP_FULLSCREEN)
9cv2.setWindowProperty("Fringes", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
10left, top, width, height = cv2.getWindowImageRect("Fringes")
11
12# prepare camera
13camera = cv2.VideoCapture(0)
14
15camera.set(cv2.CAP_PROP_AUTOFOCUS, 1) # turn on autofocus
16camera.set(cv2.CAP_PROP_AUTO_WB, 1) # turn on whitebalance
17camera.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1) # turn on autoexposure
18
19white = np.full((height, width), 255, np.uint8) # white image
20cv2.imshow("Fringes", white) # display white image
21key = cv2.waitKey(250) # delay time of the screen for displaying the image
22
23for _ in range(10):
24 # let camera automatically set focus, whitebalance and exposure
25 ret, image = camera.read()
26
27camera.set(cv2.CAP_PROP_AUTOFOCUS, 0) # turn off autofocus
28camera.set(cv2.CAP_PROP_AUTO_WB, 0) # turn off whitebalance
29camera.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0) # turn off autoexposure
30
31# configure and create fringe pattern sequence
32f = Fringes()
33f.X = width
34f.Y = height
35I = f.encode()
36
37# allocate empty image stack
38Irec = np.empty((f.T,) + image.shape, image.dtype)
39
40# record
41try:
42 # record fringe patterns in a loop
43 for t in range(f.T):
44 # display fringe pattern with index 't' in fullscreen mode
45 cv2.imshow("Fringes", I[t])
46 key = cv2.waitKey(250) # delay time of the screen for displaying the image
47
48 # capture reflected fringe pattern; ensure the fringe pattern is not overexposed!
49 ret, image = camera.read() # note: OpenCV has color order 'BGR' (instead of 'RGB') for color images
50
51 if ret:
52 # save captured fringe pattern to image stack
53 Irec[t] = image
54finally:
55 # close window
56 cv2.destroyWindow("Fringes")
57
58 # release camera resources
59 camera.release()
If the results look strange or wrong, please check out the troubleshooting. More complete code examples can be found in the examples directory.
1.2.2. CLI
You can run Fringes directly from the command-line interface with option flags.
If infile -i is not specified, Fringes encodes the fringe pattern sequence.
(If outfile -o is not specified, the result is saved to outfile.npy respective outfile.npz per default.)
fringes
fringes -o pattern.npy
If infile -i is specified, Fringes decodes the given data
and saves it to .
fringes -i pattern.npy -o decoded.npz
To list all options, call Fringes with the help flag -h:
fringes -h