Skip to content

Commit f2dffd9

Browse files
committed
Added video recording
1 parent 562d3f6 commit f2dffd9

29 files changed

+383
-285
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ __pycache__/
99
# IDE files
1010
.vscode/
1111
.spyproject/
12+
*.code-workspace
1213

1314
# Distribution / packaging
1415
.Python

frheed/__init__.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
__author__ = "Elliot Young"
42
__email__ = "elliot.young1996@gmail.com"
53
# __version__ = "3.0.0"

frheed/calcs.py

+39-19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""
32
Functions for computing values from plots.
43
"""
@@ -16,8 +15,7 @@
1615

1716

1817
def calc_fft(x: list, y: list) -> tuple:
19-
"""
20-
Calculate the FFT of a 1D series.
18+
"""Calculate the FFT of a 1D series.
2119
2220
Parameters
2321
----------
@@ -89,24 +87,46 @@ def apply_cutoffs(
8987
y: list,
9088
minval: Optional[float] = None,
9189
maxval: Optional[float] = None
92-
) -> tuple:
93-
""" Return data that falls between a certain range. Pass None to use min or max. """
90+
) -> tuple:
91+
"""Return data that falls between a certain range. Pass None to use min or max of the array.
92+
93+
Args:
94+
x (list): x values; data is filtered based on these values
95+
y (list): y values
96+
minval (Optional[float], optional): Cutoff minimum (inclusive). Defaults to None if no lower bound.
97+
maxval (Optional[float], optional): Cutoff maximum (inclusive). Defaults to None if no upper bound.
98+
99+
Returns:
100+
tuple: the filtered x and y arrays
101+
"""
94102

95-
# Return if x or y is empty
96-
if len(x) + len(y) == 0:
103+
# Return if x or y is empty or if min or max not provided
104+
if (len(x) + len(y) == 0) or (minval is None and maxval is None):
97105
return (x, y)
106+
107+
# Convert x and y to numpy arrays
98108
x, y = map(np.array, (x, y))
99-
minval = minval or min(x)
100-
maxval = maxval or max(x)
101-
orig_x = x.copy()
102-
mask = (orig_x >= minval) & (orig_x <= maxval)
109+
110+
# Create mask if there's a minimum cutoff but not maximum
111+
if minval is not None and maxval is None:
112+
mask = (x >= minval)
113+
114+
# Create mask if there's a maximum cutoff but not minimum
115+
elif maxval is not None and minval is None:
116+
mask = (x <= maxval)
117+
118+
# Mask both
119+
else:
120+
mask = (x >= minval) & (x <= maxval)
121+
122+
# Return masked elements
103123
return (x[mask], y[mask])
104124

105125
def detect_peaks(
106126
x: Union[list, tuple, np.ndarray],
107127
y: Union[list, tuple, np.ndarray],
108128
min_freq: Optional[float] = 0.0
109-
) -> list:
129+
) -> list:
110130

111131
# Catch numpy RuntimeWarning as exceptions
112132
import warnings
@@ -130,13 +150,13 @@ def detect_peaks(
130150
prominence = None
131151

132152
# Find peaks
133-
peak_indices, props = find_peaks(
134-
y,
135-
height = height,
136-
threshold = threshold,
137-
distance = distance,
138-
prominence = prominence
139-
)
153+
peak_indices, _ = find_peaks(
154+
y,
155+
height = height,
156+
threshold = threshold,
157+
distance = distance,
158+
prominence = prominence
159+
)
140160

141161
# Get corresponding x-coordinates
142162
return [x[idx] for idx in peak_indices]

frheed/cameras/__init__.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
# -*- coding: utf-8 -*-
2-
31
class CameraError(Exception):
42
pass

frheed/cameras/flir/__init__.py

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""
32
Connecting to FLIR cameras.
43
Adapted from simple_pyspin: https://github.com/klecknerlab/simple_pyspin
@@ -7,6 +6,7 @@
76
from typing import Tuple, Union
87
import time
98
import numpy as np
9+
from collections import deque
1010

1111
from frheed.cameras import CameraError
1212

@@ -219,7 +219,7 @@ def __init__(self, src: Union[int, str] = 0, lock: bool = False):
219219

220220
# Other attributes which may be accessed later
221221
self._running = False
222-
self._frame_times = []
222+
self._frame_times = deque()
223223
self._incomplete_image_count = 0
224224

225225
def __getattr__(self, attr: str) -> object:
@@ -362,15 +362,11 @@ def real_fps(self) -> float:
362362
if len(self._frame_times) <= 1:
363363
return 0.
364364

365-
# When fewer than 60 frames have been captured in this acquisition
366-
elif len(self._frame_times) < 60:
365+
# Calculate average of all frames
366+
else:
367367
dt = (self._frame_times[-1] - self._frame_times[0])
368368
return len(self._frame_times) / max(dt, 1)
369369

370-
# Return the average frame time of the last 60 frames
371-
else:
372-
return 60 / (self._frame_times[-1] - self._frame_times[-60])
373-
374370
@property
375371
def width(self) -> int:
376372
if not self.initialized:
@@ -464,7 +460,7 @@ def stop(self) -> None:
464460

465461
if self.running:
466462
self.cam.EndAcquisition()
467-
self._frame_times = []
463+
self._frame_times = deque()
468464
self._incomplete_image_count = 0
469465
self._running = False
470466

@@ -554,10 +550,13 @@ def get_array(
554550
# Store frame time for real FPS calculation
555551
self._frame_times.append(time.time())
556552

553+
# Remove the oldest frame if there are more than 60
554+
if len(self._frame_times) > 3600:
555+
self._frame_times.popleft()
556+
557557
if get_chunk:
558558
return img.GetNDArray(), img.GetChunkData()
559559
else:
560-
self._frame_times.append(time.time())
561560
return img.GetNDArray()
562561

563562
def get_info(self, name: str) -> dict:
@@ -592,11 +591,9 @@ def get_info(self, name: str) -> dict:
592591
if hasattr(node, "GetAccessMode"):
593592
access = node.GetAccessMode()
594593
info["access"] = self._rw_modes.get(access, access)
595-
# print(info["access"])
596594
if isinstance(info["access"], str) and "read" in info["access"]:
597595
info["value"] = getattr(self, name)
598596

599-
# print(info)
600597
if info.get("access") != 0:
601598
for attr in ("description", "unit", "min", "max"):
602599
fname = "Get" + attr.capitalize()

frheed/cameras/flir/install_pyspin.py

+23-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# -*- coding: utf-8 -*-
2-
31
"""
42
Install the spinnaker .whl file located in /spinnaker/...
3+
Spinnaker can be downloaded from the Teledyne FLIR website:
4+
https://flir.app.boxcn.net/v/SpinnakerSDK
55
"""
66

77
import os
@@ -14,15 +14,26 @@
1414
logger = get_logger()
1515

1616

17-
def install_pyspin() -> None:
18-
""" Install PySpin from the appropriate .whl file """
17+
def install_pyspin(reinstall: bool=False) -> None:
18+
"""Install PySpin from the downloaded .whl file located in a ./spinnaker folder.
19+
20+
Args:
21+
reinstall (bool, optional): Whether or not to install even if PySpin is already installed. Defaults to False.
22+
23+
Raises:
24+
ValueError: If the current platform is unsupported (only 32 and 64-bit windows are supported).
25+
ValueError: If an appropriate .whl file is not found for the current platform.
26+
"""
1927

2028
# Check if PySpin is already installed
2129
try:
2230
import PySpin
2331
if __name__ == "__main__":
2432
logger.info("PySpin is already installed")
25-
return
33+
34+
# Return if not reinstalling
35+
if not reinstall:
36+
return
2637

2738
except ImportError:
2839
pass
@@ -70,9 +81,11 @@ def install_pyspin() -> None:
7081
except ImportError:
7182
logger.info(f"PySpin failed to install from {whl_filepath}")
7283

84+
7385
if __name__ == "__main__":
74-
def test():
75-
os.chdir(str(Path(__file__).parents[3]))
76-
install_pyspin()
77-
78-
test()
86+
#install_pyspin(reinstall=True)
87+
import PySpin
88+
system = PySpin.System#.GetInstance()
89+
print(system)
90+
import os
91+
print(os.environ["FLIR_GENTL64_CTI_VS140"])

frheed/cameras/flir/spinnaker_win32/README.txt

+29-3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ TABLE OF CONTENTS
3838
1.3 INSTALLATION ON MACOS
3939
2. API DIFFERENCES
4040
3. REMOVE PYSPIN
41+
4. TROUBLESHOOT
42+
4.1 TROUBLESHOOT LINUX ISSUES
4143

4244
=============================================================================
4345
1. INSTALLATION
@@ -201,12 +203,12 @@ using the following:
201203
-----------------------------------------------------------------------------
202204

203205
1. Check that Python is installed. MacOS comes with Python 2.7 installed,
204-
but it may be an older build of Python.
206+
but it may be an older build of Python.
205207
There are several ways to install Up-to-date Python packages,
206-
but the recommended way is to use pyenv - the python package manager,
208+
but the recommended way is to use pyenv - the python package manager,
207209
which manages multiple versions of Python effectively.
208210
(installing python using a method that does not use pyenv, can result in run-time errors due to mixed running Python versions)
209-
211+
210212
- For example: to install the specific python version python 3.7.7 do the following steps:
211213
# Update brew
212214
brew update
@@ -379,3 +381,27 @@ For Linux or MacOS, if you need to remove PySpin from a site-wide install the
379381
following command needs to be run as sudo to remove your associated Python version:
380382

381383
sudo <python version> -m pip uninstall spinnaker-python
384+
385+
386+
=============================================================================
387+
4. TROUBLESHOOT
388+
=============================================================================
389+
390+
-----------------------------------------------------------------------------
391+
4.1 LINUX ISSUES
392+
-----------------------------------------------------------------------------
393+
394+
There is an existing issue with numpy 1.19.5 on Linux ARM64 architecture where
395+
importing PySpin could result in an 'Illegal instruction' error. The issue
396+
originates from a numpy bug that is fixed in 1.20 but the new version will not
397+
be available for older versions of python (<= 3.6).
398+
399+
More details for the numpy issue can be found here:
400+
https://github.com/numpy/numpy/issues/18131#issuecomment-794200556
401+
402+
You can workaround the issue by:
403+
- Downgrading numpy to version 1.19.4
404+
- Upgrading numpy to version 1.20.x (if you are using python > 3.6)
405+
- Setting the environment variable OPENBLAS_CORETYPE=ARMV8
406+
- Compiling from source on the failing ARM hardware
407+
pip install --no-binary :all: numpy==1.19.5

frheed/cameras/flir/spinnaker_win64/README.txt

+29-3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ TABLE OF CONTENTS
3838
1.3 INSTALLATION ON MACOS
3939
2. API DIFFERENCES
4040
3. REMOVE PYSPIN
41+
4. TROUBLESHOOT
42+
4.1 TROUBLESHOOT LINUX ISSUES
4143

4244
=============================================================================
4345
1. INSTALLATION
@@ -201,12 +203,12 @@ using the following:
201203
-----------------------------------------------------------------------------
202204

203205
1. Check that Python is installed. MacOS comes with Python 2.7 installed,
204-
but it may be an older build of Python.
206+
but it may be an older build of Python.
205207
There are several ways to install Up-to-date Python packages,
206-
but the recommended way is to use pyenv - the python package manager,
208+
but the recommended way is to use pyenv - the python package manager,
207209
which manages multiple versions of Python effectively.
208210
(installing python using a method that does not use pyenv, can result in run-time errors due to mixed running Python versions)
209-
211+
210212
- For example: to install the specific python version python 3.7.7 do the following steps:
211213
# Update brew
212214
brew update
@@ -379,3 +381,27 @@ For Linux or MacOS, if you need to remove PySpin from a site-wide install the
379381
following command needs to be run as sudo to remove your associated Python version:
380382

381383
sudo <python version> -m pip uninstall spinnaker-python
384+
385+
386+
=============================================================================
387+
4. TROUBLESHOOT
388+
=============================================================================
389+
390+
-----------------------------------------------------------------------------
391+
4.1 LINUX ISSUES
392+
-----------------------------------------------------------------------------
393+
394+
There is an existing issue with numpy 1.19.5 on Linux ARM64 architecture where
395+
importing PySpin could result in an 'Illegal instruction' error. The issue
396+
originates from a numpy bug that is fixed in 1.20 but the new version will not
397+
be available for older versions of python (<= 3.6).
398+
399+
More details for the numpy issue can be found here:
400+
https://github.com/numpy/numpy/issues/18131#issuecomment-794200556
401+
402+
You can workaround the issue by:
403+
- Downgrading numpy to version 1.19.4
404+
- Upgrading numpy to version 1.20.x (if you are using python > 3.6)
405+
- Setting the environment variable OPENBLAS_CORETYPE=ARMV8
406+
- Compiling from source on the failing ARM hardware
407+
pip install --no-binary :all: numpy==1.19.5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<meta http-equiv="Refresh" content="0; url='https://www.flir.ca/support-center/iis/machine-vision/knowledge-base/mv-getting-started/'" />
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)