machinevision-toolbox-python 2.3.0__py3-none-any.whl → 2.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {machinevision_toolbox_python-2.3.0.dist-info → machinevision_toolbox_python-2.4.1.dist-info}/METADATA +8 -6
- {machinevision_toolbox_python-2.3.0.dist-info → machinevision_toolbox_python-2.4.1.dist-info}/RECORD +24 -22
- {machinevision_toolbox_python-2.3.0.dist-info → machinevision_toolbox_python-2.4.1.dist-info}/WHEEL +1 -1
- {machinevision_toolbox_python-2.3.0.dist-info → machinevision_toolbox_python-2.4.1.dist-info}/entry_points.txt +0 -1
- machinevisiontoolbox/BagOfWords.py +13 -1
- machinevisiontoolbox/BundleAdjust.py +983 -980
- machinevisiontoolbox/Camera.py +101 -18
- machinevisiontoolbox/ImageConstants.py +27 -6
- machinevisiontoolbox/ImageCore.py +69 -8
- machinevisiontoolbox/ImageFiducials.py +16 -8
- machinevisiontoolbox/ImageIO.py +8 -0
- machinevisiontoolbox/ImagePointFeatures.py +13 -2
- machinevisiontoolbox/ImageWholeFeatures.py +18 -5
- machinevisiontoolbox/Kernel.py +29 -0
- machinevisiontoolbox/PointCloud.py +17 -4
- machinevisiontoolbox/Sources.py +18 -9
- machinevisiontoolbox/base/__init__.py +1 -0
- machinevisiontoolbox/base/color.py +42 -16
- machinevisiontoolbox/base/imageio.py +541 -443
- machinevisiontoolbox/base/types.py +14 -0
- machinevisiontoolbox/bin/mvtbtool.py +2 -1
- machinevisiontoolbox/blocks/Icons/README.md +28 -0
- machinevisiontoolbox/blocks/Icons/make_icons.py +111 -0
- {machinevision_toolbox_python-2.3.0.dist-info → machinevision_toolbox_python-2.4.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -8,6 +8,20 @@ import numpy as np
|
|
|
8
8
|
|
|
9
9
|
from machinevisiontoolbox.mvtb_types import Dtype
|
|
10
10
|
|
|
11
|
+
#: Short-name aliases for dtype strings accepted throughout the Toolbox
|
|
12
|
+
#: (e.g. Image(..., dtype='float'), VideoFile(..., dtype='float')).
|
|
13
|
+
#: NumPy's own np.dtype('float') resolves to float64, not float32 -- these
|
|
14
|
+
#: aliases exist specifically so 'float'/'int' mean the Toolbox's own
|
|
15
|
+
#: default single-precision/8-bit types, not NumPy's C-double/C-long
|
|
16
|
+
#: defaults. Single source of truth: resolve any dtype string through this
|
|
17
|
+
#: table (dtype_alias.get(dtype, dtype)) before passing it to np.dtype().
|
|
18
|
+
DTYPE_ALIASES: dict[str, str] = {
|
|
19
|
+
"int": "uint8",
|
|
20
|
+
"float": "float32",
|
|
21
|
+
"double": "float64",
|
|
22
|
+
"half": "float16",
|
|
23
|
+
}
|
|
24
|
+
|
|
11
25
|
|
|
12
26
|
def int_image(
|
|
13
27
|
image: np.ndarray, intclass: Dtype = "uint8", maxintval: int | None = None
|
|
@@ -391,7 +391,8 @@ def main():
|
|
|
391
391
|
code = [
|
|
392
392
|
f"%matplotlib{' '+args.backend if args.backend is not None else ''}",
|
|
393
393
|
"import matplotlib.pyplot as plt",
|
|
394
|
-
"
|
|
394
|
+
"_prec = get_ipython().run_line_magic('precision', '%.3g'); "
|
|
395
|
+
"print(f'Default numeric formatting: {_prec}')",
|
|
395
396
|
]
|
|
396
397
|
if args.base:
|
|
397
398
|
code.append("from machinevisiontoolbox.base import *")
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Block icons
|
|
2
|
+
|
|
3
|
+
Icons for the bdsim blocks in this toolbox. They follow the conventions of
|
|
4
|
+
[bdsim's `Icons` folder](https://github.com/petercorke/bdsim/blob/main/src/bdsim/blocks/Icons/README.md):
|
|
5
|
+
250x250 RGBA PNG, black "ink" on a transparent background, named as the
|
|
6
|
+
lower-case version of the block's class name.
|
|
7
|
+
|
|
8
|
+
| Icon | How it is made |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `visjac_p.png`, `estpose_p.png` | TeX math, rendered by `make_icons.py` (below). The files in git were made with `bdtex2icon` from bdsim, which needs LaTeX; `make_icons.py` makes the same glyphs, with slightly different size and placement. |
|
|
11
|
+
| `camera.png`, `imageplane.png` | not made by `make_icons.py` |
|
|
12
|
+
|
|
13
|
+
## Creating icons from TeX
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
python make_icons.py # all icons in the table at the top of the script
|
|
17
|
+
python make_icons.py visjac_p # one icon
|
|
18
|
+
python make_icons.py --outdir /tmp # write somewhere else, e.g. to compare
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This needs only matplotlib and Pillow, which this toolbox already depends on,
|
|
22
|
+
and no LaTeX installation. To add an icon, add a line to the `ICONS` table in
|
|
23
|
+
`make_icons.py`. The math is rendered by matplotlib's `mathtext`, which
|
|
24
|
+
implements a subset of TeX and does not know the custom macros of the RVC
|
|
25
|
+
notation file (`\mat`, `\pose`, ...), so write those expanded, for example
|
|
26
|
+
`\mathbf{J}_p` rather than `\mat{J}_p`.
|
|
27
|
+
|
|
28
|
+
Running the script overwrites the icons of the same name in this folder.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Create block icons from TeX math, using only matplotlib and Pillow.
|
|
4
|
+
|
|
5
|
+
Run it from anywhere to (re)create the icons listed in :data:`ICONS`::
|
|
6
|
+
|
|
7
|
+
$ python make_icons.py # all icons, written next to this script
|
|
8
|
+
$ python make_icons.py visjac_p # just one
|
|
9
|
+
$ python make_icons.py --outdir /tmp/icons # somewhere else
|
|
10
|
+
|
|
11
|
+
Each icon is a 250x250 RGBA PNG: black "ink" on a transparent background, the
|
|
12
|
+
size and style used by the bdsim block icons (see the README in this folder).
|
|
13
|
+
|
|
14
|
+
The math is rendered by matplotlib's ``mathtext`` engine with the Computer
|
|
15
|
+
Modern font set, so no LaTeX installation is needed. ``mathtext`` implements a
|
|
16
|
+
subset of TeX, and not the custom macros (``\\mat``, ``\\pose``, ...) from the
|
|
17
|
+
``rvc-notation`` file that ``bdtex2icon`` (part of bdsim) uses, so the entries
|
|
18
|
+
in :data:`ICONS` are written with those macros expanded.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import argparse
|
|
22
|
+
import io
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
import matplotlib
|
|
26
|
+
|
|
27
|
+
matplotlib.use("Agg")
|
|
28
|
+
|
|
29
|
+
import numpy as np
|
|
30
|
+
from matplotlib import mathtext, rc_context
|
|
31
|
+
from PIL import Image
|
|
32
|
+
|
|
33
|
+
IMSIZE = 250
|
|
34
|
+
|
|
35
|
+
#: icon file stem -> TeX math (without the surrounding ``$``)
|
|
36
|
+
ICONS: dict[str, str] = {
|
|
37
|
+
"visjac_p": r"\mathbf{J}_p",
|
|
38
|
+
"estpose_p": r"\xi(p, P)",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def tex_icon(
|
|
43
|
+
tex: str, path: Path, size: int = IMSIZE, margin: float = 0.08, dpi: int = 600
|
|
44
|
+
) -> None:
|
|
45
|
+
"""Render TeX math to a square, transparent, black-ink PNG icon.
|
|
46
|
+
|
|
47
|
+
:param tex: TeX math expression, without the surrounding ``$``
|
|
48
|
+
:param path: output file
|
|
49
|
+
:param size: width and height of the icon in pixels, defaults to 250
|
|
50
|
+
:param margin: blank border as a fraction of ``size``, on each side,
|
|
51
|
+
defaults to 0.08
|
|
52
|
+
:param dpi: resolution of the intermediate rendering, defaults to 600
|
|
53
|
+
|
|
54
|
+
The expression is rendered, cropped to its ink, scaled to fit inside the
|
|
55
|
+
margin, and centered on a transparent canvas.
|
|
56
|
+
"""
|
|
57
|
+
buf = io.BytesIO()
|
|
58
|
+
with rc_context({"mathtext.fontset": "cm"}): # Computer Modern, as LaTeX
|
|
59
|
+
mathtext.math_to_image(f"${tex}$", buf, dpi=dpi, format="png", color="black")
|
|
60
|
+
|
|
61
|
+
# math_to_image saves a figure, so it is black ink on an *opaque white*
|
|
62
|
+
# background. The ink is black, so how dark a pixel is gives its coverage,
|
|
63
|
+
# and that is all the icon needs: black everywhere, with this as the alpha.
|
|
64
|
+
# Working on one channel also avoids mixing colors into anti-aliased edges.
|
|
65
|
+
alpha = 255 - np.asarray(Image.open(buf).convert("L"))
|
|
66
|
+
ys, xs = np.nonzero(alpha)
|
|
67
|
+
ink = Image.fromarray(alpha[ys.min() : ys.max() + 1, xs.min() : xs.max() + 1])
|
|
68
|
+
|
|
69
|
+
scale = size * (1 - 2 * margin) / max(ink.size)
|
|
70
|
+
ink = ink.resize(
|
|
71
|
+
(max(1, round(ink.width * scale)), max(1, round(ink.height * scale))),
|
|
72
|
+
Image.LANCZOS,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
canvas = Image.new("L", (size, size), 0)
|
|
76
|
+
canvas.paste(ink, ((size - ink.width) // 2, (size - ink.height) // 2))
|
|
77
|
+
|
|
78
|
+
icon = Image.new("RGBA", (size, size), (0, 0, 0, 0))
|
|
79
|
+
icon.putalpha(canvas)
|
|
80
|
+
icon.save(path)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def main() -> None:
|
|
84
|
+
parser = argparse.ArgumentParser(description=__doc__.strip().splitlines()[0])
|
|
85
|
+
parser.add_argument(
|
|
86
|
+
"names",
|
|
87
|
+
nargs="*",
|
|
88
|
+
metavar="name",
|
|
89
|
+
help=f"icons to create, one or more of {', '.join(ICONS)}; default is all",
|
|
90
|
+
)
|
|
91
|
+
parser.add_argument(
|
|
92
|
+
"--outdir",
|
|
93
|
+
type=Path,
|
|
94
|
+
default=Path(__file__).resolve().parent,
|
|
95
|
+
help="output directory, defaults to the directory containing this script",
|
|
96
|
+
)
|
|
97
|
+
args = parser.parse_args()
|
|
98
|
+
|
|
99
|
+
unknown = [n for n in args.names if n not in ICONS]
|
|
100
|
+
if unknown:
|
|
101
|
+
parser.error(f"unknown icon(s) {unknown}, choose from {list(ICONS)}")
|
|
102
|
+
|
|
103
|
+
args.outdir.mkdir(parents=True, exist_ok=True)
|
|
104
|
+
for name in args.names or ICONS:
|
|
105
|
+
path = args.outdir / f"{name}.png"
|
|
106
|
+
tex_icon(ICONS[name], path)
|
|
107
|
+
print(f"Written: {path}")
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
if __name__ == "__main__":
|
|
111
|
+
main()
|
|
File without changes
|