machinevision-toolbox-python 2.0.1__tar.gz → 2.2.0__tar.gz

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.
Files changed (117) hide show
  1. machinevision_toolbox_python-2.2.0/.release-please-manifest.json +3 -0
  2. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/CHANGELOG.md +69 -1
  3. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/Makefile +0 -12
  4. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/PKG-INFO +13 -5
  5. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/README.md +1 -0
  6. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/pyproject.toml +11 -6
  7. machinevision_toolbox_python-2.2.0/release-please-config.json +64 -0
  8. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/BundleAdjust.py +1 -1
  9. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/Camera.py +95 -80
  10. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageBlobs.py +10 -4
  11. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageCore.py +105 -97
  12. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageFiducials.py +62 -10
  13. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageIO.py +5 -1
  14. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageLineFeatures.py +9 -1
  15. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImagePointFeatures.py +29 -8
  16. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageProcessing.py +1 -1
  17. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageRegionFeatures.py +25 -6
  18. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageWholeFeatures.py +113 -72
  19. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/Sources.py +1 -1
  20. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/__init__.py +1 -1
  21. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/base/imageio.py +68 -33
  22. machinevision_toolbox_python-2.2.0/src/machinevisiontoolbox/bin/_iminteractive.py +461 -0
  23. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/bin/bagtool.py +120 -6
  24. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/bin/imtool.py +34 -5
  25. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/bin/mvtbtool.py +93 -18
  26. machinevision_toolbox_python-2.0.1/CODEAUTOLINK_FORK_PLAN.md +0 -186
  27. machinevision_toolbox_python-2.0.1/MIGRATION.md +0 -91
  28. machinevision_toolbox_python-2.0.1/NOTES +0 -57
  29. machinevision_toolbox_python-2.0.1/OPENCV_FUNCTIONS-original.md +0 -107
  30. machinevision_toolbox_python-2.0.1/OPENCV_FUNCTIONS.md +0 -184
  31. machinevision_toolbox_python-2.0.1/audit_typing.py +0 -108
  32. machinevision_toolbox_python-2.0.1/bags/RenderOption_2026-03-29-12-09-23.json +0 -41
  33. machinevision_toolbox_python-2.0.1/deprecation_warnings.csv +0 -22
  34. machinevision_toolbox_python-2.0.1/examples/bus.jpg +0 -0
  35. machinevision_toolbox_python-2.0.1/examples/street_scene.jpg +0 -11
  36. machinevision_toolbox_python-2.0.1/examples/yolo26n.pt +0 -0
  37. machinevision_toolbox_python-2.0.1/findimages.py +0 -16
  38. machinevision_toolbox_python-2.0.1/flowers.jpg +0 -0
  39. machinevision_toolbox_python-2.0.1/fmtparser.py +0 -78
  40. machinevision_toolbox_python-2.0.1/ilabel.c +0 -15230
  41. machinevision_toolbox_python-2.0.1/ilabel.py-unopt +0 -271
  42. machinevision_toolbox_python-2.0.1/inspect_bag.py +0 -9
  43. machinevision_toolbox_python-2.0.1/machinevision-toolbox-python.pdf +0 -0
  44. machinevision_toolbox_python-2.0.1/machinevision-toolbox-python.svg +0 -13
  45. machinevision_toolbox_python-2.0.1/machinevisiontoolbox.pdf +0 -0
  46. machinevision_toolbox_python-2.0.1/phone.py +0 -17
  47. machinevision_toolbox_python-2.0.1/plot_call_inventory.md +0 -29
  48. machinevision_toolbox_python-2.0.1/readbag.py +0 -347
  49. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/ImageCore.docstring +0 -2877
  50. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/aruco0.pdf +0 -0
  51. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/aruco50.pdf +0 -0
  52. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/bin/labeltool.py +0 -147
  53. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/blocks/Icons/icons.sh +0 -4
  54. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/cvfuncs.py +0 -40
  55. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/docbugs.py +0 -47
  56. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/newcameras.py +0 -55
  57. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/test_skimage.py +0 -12
  58. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/testblobplots.py +0 -17
  59. machinevision_toolbox_python-2.0.1/src/machinevisiontoolbox/x.json +0 -296
  60. machinevision_toolbox_python-2.0.1/ss +0 -1
  61. machinevision_toolbox_python-2.0.1/sunday.py +0 -71
  62. machinevision_toolbox_python-2.0.1/x.json +0 -254
  63. machinevision_toolbox_python-2.0.1/xx.mp4 +0 -0
  64. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/.gitignore +0 -0
  65. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/LICENSE +0 -0
  66. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/README.md +0 -0
  67. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/blobs1.py +0 -0
  68. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/blobs2.py +0 -0
  69. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/bunny.py +0 -0
  70. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/color.py +0 -0
  71. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/corners.py +0 -0
  72. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/matching.py +0 -0
  73. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/monalisa.py +0 -0
  74. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/morphdemo.py +0 -0
  75. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/randomdots.py +0 -0
  76. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/ransac_line.py +0 -0
  77. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/ros_stream.py +0 -0
  78. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/showzip.py +0 -0
  79. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/torch-yolo.py +0 -0
  80. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/examples/torch_seg.py +0 -0
  81. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/BagOfWords.py +0 -0
  82. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageColor.py +0 -0
  83. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageConstants.py +0 -0
  84. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageMorph.py +0 -0
  85. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageMultiview.py +0 -0
  86. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageReshape.py +0 -0
  87. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageSpatial.py +0 -0
  88. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/ImageTensor.py +0 -0
  89. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/Kernel.py +0 -0
  90. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/PointCloud.py +0 -0
  91. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/VisualServo.py +0 -0
  92. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/_image_typing.py +0 -0
  93. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/base/__init__.py +0 -0
  94. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/base/color.py +0 -0
  95. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/base/data.py +0 -0
  96. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/base/findpeaks.py +0 -0
  97. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/base/graphics.py +0 -0
  98. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/base/meshgrid.py +0 -0
  99. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/base/shapes.py +0 -0
  100. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/base/types.py +0 -0
  101. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/base/version.py +0 -0
  102. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/bin/_bintools.py +0 -0
  103. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/bin/ocrtool.py +0 -0
  104. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/bin/tagtool.py +0 -0
  105. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/blocks/Icons/camera.png +0 -0
  106. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/blocks/Icons/estpose_p.png +0 -0
  107. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/blocks/Icons/imageplane.png +0 -0
  108. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/blocks/Icons/visjac_p.png +0 -0
  109. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/blocks/__init__.py +0 -0
  110. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/blocks/camera.py +0 -0
  111. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/blocks/test_blocks.py +0 -0
  112. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/camera_derivatives.py +0 -0
  113. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/decorators.py +0 -0
  114. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/fiducial.py +0 -0
  115. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/src/machinevisiontoolbox/mvtb_types.py +0 -0
  116. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/symbolic/README.md +0 -0
  117. {machinevision_toolbox_python-2.0.1 → machinevision_toolbox_python-2.2.0}/symbolic/bundle-adjust.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "2.2.0"
3
+ }
@@ -1,3 +1,71 @@
1
+ # Changelog
2
+
3
+ ## [2.2.0](https://github.com/petercorke/machinevision-toolbox-python/compare/v2.1.0...v2.2.0) (2026-08-10)
4
+
5
+ **Highlight: OpenCV 5 compatibility.** MVTB now works correctly under both OpenCV 4 and the
6
+ newly-released OpenCV 5 — aruco/fiducial pose estimation, HoughLinesP line features,
7
+ BRISK/AKAZE point features, and MSER region features have all been fixed for OpenCV 5's API
8
+ and shape changes, verified against real OpenCV 4.13.0 and 5.0.0 installs. See #44 for the
9
+ full compatibility audit.
10
+
11
+ ### Features
12
+
13
+ * add mvtbtool --test smoke test, fix silent Open3D banner skip ([6a0bf2c](https://github.com/petercorke/machinevision-toolbox-python/commit/6a0bf2c090b8be4aa2d378495545ca71a55e89b1))
14
+
15
+ ### Bug Fixes
16
+
17
+ * handle HoughLinesP's (N,4) return shape on OpenCV 5 ([b54f755](https://github.com/petercorke/machinevision-toolbox-python/commit/b54f7552a8c08530173e159d70a84fa5e8f6d486))
18
+ * handle MSER's empty-tuple bboxes on OpenCV 5, resolve MSER discrepancy ([aabaf88](https://github.com/petercorke/machinevision-toolbox-python/commit/aabaf885e660c59c4949a5f5706b276ad7c50202))
19
+ * normalize aruco ids/matchImagePoints shapes for OpenCV 5 ([6ac5ec0](https://github.com/petercorke/machinevision-toolbox-python/commit/6ac5ec0cc795ad7016f491dbb464e91c4ad34aae))
20
+ * replace removed cv2.aruco.estimatePoseSingleMarkers with solvePnP ([635225d](https://github.com/petercorke/machinevision-toolbox-python/commit/635225de657a1484ad526480605d9d234f202ffa))
21
+ * resolve BRISK/AKAZE via cv2.xfeatures2d on OpenCV 5 ([fad7247](https://github.com/petercorke/machinevision-toolbox-python/commit/fad7247cf6cfc07f7e8511ffa37ce4ccc928f451))
22
+
23
+ ## [2.1.0](https://github.com/petercorke/machinevision-toolbox-python/compare/v2.0.1...v2.1.0) (2026-08-03)
24
+
25
+
26
+ ### Features
27
+
28
+ * add interactive tools to imtool and bagtool ([b16ab7d](https://github.com/petercorke/machinevision-toolbox-python/commit/b16ab7dbd1f2fe26869a7fcacc710e549735e431))
29
+ * **mvtbtool:** add 'tool' extra for IPython/pygments, fail with clear message when missing ([a31655b](https://github.com/petercorke/machinevision-toolbox-python/commit/a31655be13d07acb14548e79c618d62d5bf5589c))
30
+
31
+
32
+ ### Bug Fixes
33
+
34
+ * add missing type annotations, warn on ncdf deprecation ([7e8cabe](https://github.com/petercorke/machinevision-toolbox-python/commit/7e8cabe4ceee1f517b1a9161ab28e9d87137475e))
35
+ * add socket timeout to iread() URL fetches ([6ff62b1](https://github.com/petercorke/machinevision-toolbox-python/commit/6ff62b17aa1b556a1823e69ae4950f2786e0ebc1))
36
+ * bring 3 mixins in line with the TYPE_CHECKING _ImageBase pattern ([0d31fc5](https://github.com/petercorke/machinevision-toolbox-python/commit/0d31fc52f881df6cfda35c5ab11e4f9753e65aa0))
37
+ * colorplane handling in image i/o ([6882967](https://github.com/petercorke/machinevision-toolbox-python/commit/68829677c0f42d4b6e83b61b981f5027efe61ee3))
38
+ * gridify() IndexError from numpy float // int staying float64 ([e57597a](https://github.com/petercorke/machinevision-toolbox-python/commit/e57597aa527ab1741ff19066070ecd6968056da5))
39
+ * keep single-blob filter() matches ([7b0ab8d](https://github.com/petercorke/machinevision-toolbox-python/commit/7b0ab8d67c67251e12753df198447fdc9255f48a)), closes [#17](https://github.com/petercorke/machinevision-toolbox-python/issues/17)
40
+ * replace 6 bare except: clauses with specific exception types ([5a11306](https://github.com/petercorke/machinevision-toolbox-python/commit/5a11306eb838b2c47535389f482ab872b7a22d24))
41
+ * un-hide bot-comment notes from HTML comment block ([4a4e943](https://github.com/petercorke/machinevision-toolbox-python/commit/4a4e943fab8e00af404713efb1f3501d1c94f1a3))
42
+ * use eigh instead of eig for blob orientation/ellipse moments ([3a74fdf](https://github.com/petercorke/machinevision-toolbox-python/commit/3a74fdf6b558967ae797d19bbb4369275eaf690c))
43
+
44
+
45
+ ### Documentation
46
+
47
+ * add build date to footer copyright notice ([e7de5bf](https://github.com/petercorke/machinevision-toolbox-python/commit/e7de5bf8e68d6251cbc23465befdd4070d7fbc6c))
48
+ * add example placeholder to Alternatives considered ([879f086](https://github.com/petercorke/machinevision-toolbox-python/commit/879f086dc0bcde61496c6f227d275dd19c47e53a))
49
+ * add PR and issue templates ([d081f7e](https://github.com/petercorke/machinevision-toolbox-python/commit/d081f7e49ae1e1673b00c92e4bd174e3c2629efb))
50
+ * ask for a concrete function signature in feature requests ([b25cd12](https://github.com/petercorke/machinevision-toolbox-python/commit/b25cd12efa6eae61a9ef2a6b05a78dbffca82cda))
51
+ * fix docstring convention note, add Codacy heads-up ([d68f605](https://github.com/petercorke/machinevision-toolbox-python/commit/d68f605301aaa71795c5cab75acadb910ce6d398))
52
+ * fix Image class sidebar, cut over to sphinx-pyrunblock ([20c219d](https://github.com/petercorke/machinevision-toolbox-python/commit/20c219d65fdb68ca14d58777a08f0c29333303dd))
53
+ * fix stale rank() reference in card-algorithms.rst ([1e3f6bd](https://github.com/petercorke/machinevision-toolbox-python/commit/1e3f6bdf3cbaa3307985f616af2c178c3d6a5029))
54
+ * fix stale/broken references and add footer build date ([c51955b](https://github.com/petercorke/machinevision-toolbox-python/commit/c51955bf14b55ed8dd9a19bf6b9c9d6b97952e6d))
55
+ * flesh out PR template with a proper checklist ([f4db44b](https://github.com/petercorke/machinevision-toolbox-python/commit/f4db44b4b21a16514ea0f1de2bceb54d22b6d39c))
56
+ * forewarn contributors about Dependabot vulnerability comments ([acfedab](https://github.com/petercorke/machinevision-toolbox-python/commit/acfedabfc285e11e4a505eb06b81c3bec74c0762))
57
+ * log ci.yml's conda/micromamba setup as tech debt ([af09d07](https://github.com/petercorke/machinevision-toolbox-python/commit/af09d07cae1df3129df4853d3a672db333f42465))
58
+ * log Codacy backlog real numbers to tech-debt ([65b3c5e](https://github.com/petercorke/machinevision-toolbox-python/commit/65b3c5ed3b2a2cbd20ee41a29b9c2b8234db126e))
59
+ * log gridify() IndexError bug found while testing bare-except fix ([889d45c](https://github.com/petercorke/machinevision-toolbox-python/commit/889d45c4957f93ec9910ccb960f91a432d1d06a3))
60
+ * log Histogram.plot type= docstring/behavior mismatch ([e693eef](https://github.com/petercorke/machinevision-toolbox-python/commit/e693eefa033c5d7a7e95c2787ac3f4dbbce0d2c3))
61
+ * log mypy-not-in-CI as high-priority tech debt, with fresh audit ([1b74ae8](https://github.com/petercorke/machinevision-toolbox-python/commit/1b74ae8efc240e43c338dec8415f7198de2a0d3a))
62
+ * log pgraph-python CI gap and conda-migration decision to tech-debt ([c5b6aeb](https://github.com/petercorke/machinevision-toolbox-python/commit/c5b6aebdaa42003bc48d0428d3381599f325d1df))
63
+ * log PR [#32](https://github.com/petercorke/machinevision-toolbox-python/issues/32)/[#33](https://github.com/petercorke/machinevision-toolbox-python/issues/33) Codacy findings (type shadowing, F405, max param) ([e0ed8db](https://github.com/petercorke/machinevision-toolbox-python/commit/e0ed8db736f1032c2a4fdb78c308c16f1b7e300b))
64
+ * migrate tech-debt.md to GitHub Issues (tech-debt label) ([36aae6a](https://github.com/petercorke/machinevision-toolbox-python/commit/36aae6aa9855ac79a4de19fb49fbaf30827b423a))
65
+ * remove reference to nonexistent CentralCamera.decomposeF ([c7f1400](https://github.com/petercorke/machinevision-toolbox-python/commit/c7f1400700f2ff5364d2fafe19367cfa49628e8e))
66
+ * switch sphinx-codeautolink to released 0.19.0, drop branch pin ([594a9a1](https://github.com/petercorke/machinevision-toolbox-python/commit/594a9a13580cf58868d836adee3a5bbaebc42d12))
67
+ * use %pip magic in notebooks, add tagline to README ([843db36](https://github.com/petercorke/machinevision-toolbox-python/commit/843db36441d43ec74e573d9b201f93635213c7ad))
68
+
1
69
  2.0.0 May 2026
2
70
 
3
71
  * Added
@@ -238,4 +306,4 @@ and is `None` if the blob has no parent (its parent is the background).
238
306
 
239
307
  * Additional unit tests
240
308
 
241
- * Myriad minor bug fixes, see commit history.
309
+ * Myriad minor bug fixes, see commit history.
@@ -14,7 +14,6 @@ help:
14
14
  @echo " make docs-strict - nitpicky Sphinx build with warnings treated as errors"
15
15
  @echo " make view - open Sphinx doco build (uses open for MacOS)"
16
16
  @echo " make dist - preview dist build"
17
- @echo " make pypi - build the dist, upload to PyPI, tag the release and push the tag to origin"
18
17
  @echo " make clean - remove dist and docs build files"
19
18
  @echo " make help - this message$(BLACK)"
20
19
 
@@ -59,17 +58,6 @@ dist: .FORCE
59
58
  python -m build
60
59
  ls -lh dist/*
61
60
 
62
- pypi: .FORCE
63
- @if ! git diff --quiet || ! git diff --cached --quiet; then \
64
- echo "Error: uncommitted changes present, aborting upload"; exit 1; \
65
- fi
66
- python -m build
67
- $(eval VERSION := $(shell grep '^version' pyproject.toml | sed 's/version = "\(.*\)"/\1/'))
68
- @echo "Uploading version $(VERSION) to PyPI"
69
- twine upload dist/*
70
- git tag v$(VERSION)
71
- git push origin v$(VERSION)
72
-
73
61
  clean: .FORCE
74
62
  (cd docs; make clean)
75
63
  -rm -r *.egg-info
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: machinevision-toolbox-python
3
- Version: 2.0.1
3
+ Version: 2.2.0
4
4
  Summary: Object-oriented machine vision for Python.
5
5
  Project-URL: Homepage, https://github.com/petercorke/machinevision-toolbox-python
6
6
  Project-URL: Bug Tracker, https://github.com/pypa/sampleproject/issues
@@ -23,8 +23,8 @@ Requires-Dist: ansitable
23
23
  Requires-Dist: matplotlib
24
24
  Requires-Dist: mvtb-data
25
25
  Requires-Dist: numpy
26
- Requires-Dist: opencv-contrib-python
27
- Requires-Dist: opencv-python
26
+ Requires-Dist: opencv-contrib-python<5.0.0
27
+ Requires-Dist: opencv-python<5.0.0
28
28
  Requires-Dist: pgraph-python
29
29
  Requires-Dist: pillow
30
30
  Requires-Dist: requests
@@ -33,8 +33,10 @@ Requires-Dist: spatialmath-python
33
33
  Requires-Dist: tqdm
34
34
  Provides-Extra: all
35
35
  Requires-Dist: ipympl; extra == 'all'
36
+ Requires-Dist: ipython; extra == 'all'
36
37
  Requires-Dist: ipywidgets; extra == 'all'
37
38
  Requires-Dist: open3d-python; extra == 'all'
39
+ Requires-Dist: pygments; extra == 'all'
38
40
  Requires-Dist: pytesseract; extra == 'all'
39
41
  Requires-Dist: rosbags; extra == 'all'
40
42
  Requires-Dist: roslibpy; extra == 'all'
@@ -44,15 +46,17 @@ Provides-Extra: dev
44
46
  Requires-Dist: coverage; extra == 'dev'
45
47
  Requires-Dist: nbmake; extra == 'dev'
46
48
  Requires-Dist: pytest; extra == 'dev'
49
+ Requires-Dist: pytest-timeout; extra == 'dev'
50
+ Requires-Dist: pytest-xvfb; extra == 'dev'
47
51
  Requires-Dist: ruff; extra == 'dev'
48
52
  Provides-Extra: docs
49
53
  Requires-Dist: pydata-sphinx-theme; extra == 'docs'
50
54
  Requires-Dist: sphinx; extra == 'docs'
51
- Requires-Dist: sphinx-autorun; extra == 'docs'
52
- Requires-Dist: sphinx-codeautolink; extra == 'docs'
55
+ Requires-Dist: sphinx-codeautolink>=0.19.0; extra == 'docs'
53
56
  Requires-Dist: sphinx-copybutton; extra == 'docs'
54
57
  Requires-Dist: sphinx-design; extra == 'docs'
55
58
  Requires-Dist: sphinx-favicon; extra == 'docs'
59
+ Requires-Dist: sphinx-pyrunblock; extra == 'docs'
56
60
  Requires-Dist: sphinxcontrib-programoutput; extra == 'docs'
57
61
  Provides-Extra: jupyter
58
62
  Requires-Dist: ipympl; extra == 'jupyter'
@@ -65,6 +69,9 @@ Provides-Extra: ros
65
69
  Requires-Dist: rosbags; extra == 'ros'
66
70
  Requires-Dist: roslibpy; extra == 'ros'
67
71
  Requires-Dist: websockets; extra == 'ros'
72
+ Provides-Extra: tool
73
+ Requires-Dist: ipython; extra == 'tool'
74
+ Requires-Dist: pygments; extra == 'tool'
68
75
  Provides-Extra: torch
69
76
  Requires-Dist: torch; extra == 'torch'
70
77
  Description-Content-Type: text/markdown
@@ -74,6 +81,7 @@ Description-Content-Type: text/markdown
74
81
  <div align="center">
75
82
  <img src="https://github.com/petercorke/machinevision-toolbox-python/raw/main/docs/figs/VisionToolboxLogo_NoBackgnd@2x.png" width="350">
76
83
  <br>
84
+ <em>OpenCV for humans</em><br>
77
85
  <strong>A high-productivity framework for computer vision research and education.</strong>
78
86
  <br><br>
79
87
 
@@ -3,6 +3,7 @@
3
3
  <div align="center">
4
4
  <img src="https://github.com/petercorke/machinevision-toolbox-python/raw/main/docs/figs/VisionToolboxLogo_NoBackgnd@2x.png" width="350">
5
5
  <br>
6
+ <em>OpenCV for humans</em><br>
6
7
  <strong>A high-productivity framework for computer vision research and education.</strong>
7
8
  <br><br>
8
9
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "machinevision-toolbox-python"
3
- version = "2.0.1"
3
+ version = "2.2.0"
4
4
  authors = [{ name = "Peter Corke", email = "rvc@petercorke.com" }]
5
5
  description = "Object-oriented machine vision for Python."
6
6
  readme = "README.md"
@@ -39,8 +39,8 @@ dependencies = [
39
39
  "scipy",
40
40
  "matplotlib",
41
41
  "pillow",
42
- "opencv-python",
43
- "opencv-contrib-python",
42
+ "opencv-python<5.0.0",
43
+ "opencv-contrib-python<5.0.0",
44
44
  "spatialmath-python",
45
45
  "pgraph-python",
46
46
  "ansitable",
@@ -65,19 +65,22 @@ dependencies = [
65
65
  # open3d - open3d support (open3d generally won't work with latest Python)
66
66
  # all - all runtime optional features below
67
67
  # ocr - OCR support via pytesseract
68
+ # tool - dependencies for the mvtbtool interactive shell
68
69
 
69
- dev = ["pytest", "coverage", "ruff", "nbmake"]
70
+ dev = ["pytest", "pytest-timeout", "pytest-xvfb", "coverage", "ruff", "nbmake"]
70
71
 
71
72
  ros = ["rosbags", "roslibpy", "websockets"]
72
73
 
74
+ tool = ["ipython", "pygments"]
75
+
73
76
  docs = [
74
77
  "sphinx",
75
78
  "pydata-sphinx-theme",
76
- "sphinx-codeautolink",
79
+ "sphinx-codeautolink>=0.19.0",
77
80
  "sphinx-favicon",
78
81
  "sphinx-copybutton",
79
82
  "sphinxcontrib-programoutput",
80
- "sphinx-autorun",
83
+ "sphinx-pyrunblock",
81
84
  "sphinx-design",
82
85
  ]
83
86
 
@@ -98,6 +101,8 @@ all = [
98
101
  "rosbags",
99
102
  "roslibpy",
100
103
  "websockets",
104
+ "ipython",
105
+ "pygments",
101
106
  ]
102
107
 
103
108
  [tool.pytest.ini_options]
@@ -0,0 +1,64 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
3
+ "release-type": "python",
4
+ "packages": {
5
+ ".": {
6
+ "release-type": "python",
7
+ "package-name": "machinevision-toolbox-python",
8
+ "version-file": "pyproject.toml",
9
+ "changelog-path": "CHANGELOG.md",
10
+ "include-component-in-tag": false
11
+ }
12
+ },
13
+ "pull-request-title-pattern": "chore: release ${version}",
14
+ "changelog-sections": [
15
+ {
16
+ "type": "feat",
17
+ "section": "Features"
18
+ },
19
+ {
20
+ "type": "fix",
21
+ "section": "Bug Fixes"
22
+ },
23
+ {
24
+ "type": "perf",
25
+ "section": "Performance Improvements"
26
+ },
27
+ {
28
+ "type": "deps",
29
+ "section": "Dependencies"
30
+ },
31
+ {
32
+ "type": "revert",
33
+ "section": "Reverts"
34
+ },
35
+ {
36
+ "type": "docs",
37
+ "section": "Documentation"
38
+ },
39
+ {
40
+ "type": "build",
41
+ "section": "Build System"
42
+ },
43
+ {
44
+ "type": "test",
45
+ "section": "Tests",
46
+ "hidden": true
47
+ },
48
+ {
49
+ "type": "refactor",
50
+ "section": "Code Refactoring",
51
+ "hidden": true
52
+ },
53
+ {
54
+ "type": "chore",
55
+ "section": "Miscellaneous",
56
+ "hidden": true
57
+ },
58
+ {
59
+ "type": "ci",
60
+ "section": "CI",
61
+ "hidden": true
62
+ }
63
+ ]
64
+ }
@@ -12,7 +12,7 @@ try:
12
12
  import pgraph
13
13
 
14
14
  pgraph_installed = True
15
- except:
15
+ except ImportError:
16
16
  print("pgraph not installed")
17
17
  pgraph_installed = False
18
18
  import matplotlib.pyplot as plt
@@ -827,7 +827,7 @@ class CameraBase(ABC):
827
827
  for artist in self._ax.get_children():
828
828
  try:
829
829
  artist.remove()
830
- except:
830
+ except Exception:
831
831
  pass
832
832
 
833
833
  def plot_point(
@@ -1216,86 +1216,10 @@ class CameraBase(ABC):
1216
1216
  try:
1217
1217
  # draw camera-like object:
1218
1218
  if shape == "frustum":
1219
- # TODO make this kwargs or optional inputs
1220
- # side colors:
1221
- # +x red
1222
- # -y red
1223
- # +y green
1224
- # -y yellow
1225
- length = scale
1226
- widthb = scale / 10
1227
- widtht = scale
1228
- widthb /= 2
1229
- widtht /= 2
1230
- b0 = np.array([-widthb, -widthb, 0, 1])
1231
- b1 = np.array([-widthb, widthb, 0, 1])
1232
- b2 = np.array([widthb, widthb, 0, 1])
1233
- b3 = np.array([widthb, -widthb, 0, 1])
1234
- t0 = np.array([-widtht, -widtht, length, 1])
1235
- t1 = np.array([-widtht, widtht, length, 1])
1236
- t2 = np.array([widtht, widtht, length, 1])
1237
- t3 = np.array([widtht, -widtht, length, 1])
1238
-
1239
- # bottom/narrow end
1240
- T = pose.A
1241
- b0 = (T @ b0)[:-1]
1242
- b1 = (T @ b1)[:-1]
1243
- b2 = (T @ b2)[:-1]
1244
- b3 = (T @ b3)[:-1]
1245
-
1246
- # wide/top end
1247
- t0 = (T @ t0)[:-1]
1248
- t1 = (T @ t1)[:-1]
1249
- t2 = (T @ t2)[:-1]
1250
- t3 = (T @ t3)[:-1]
1251
-
1252
- points = [
1253
- np.array([b0, b1, t1, t0]), # -x face
1254
- np.array([b1, b2, t2, t1]), # +y face
1255
- np.array([b2, b3, t3, t2]), # +x face
1256
- np.array([b3, b0, t0, t3]), # -y face
1257
- ]
1258
- poly = Poly3DCollection(
1259
- points, facecolors=["r", "g", "r", "y"], alpha=alpha
1260
- )
1261
- ax.add_collection3d(poly)
1219
+ self._plot_frustum(ax, pose, scale, alpha)
1262
1220
 
1263
1221
  elif shape == "camera":
1264
- # the box is centred at the origin and its centerline parallel to the
1265
- # z-axis. Its z-extent is -bh/2 to bh/2.
1266
- W = 0.5 # width & height of the box
1267
- L = 1.2 # length of the box
1268
- cr = 0.2 # cylinder radius
1269
- ch = 0.4 # cylinder height
1270
- cn = 12 # number of facets of cylinder
1271
- a = 3 # length of axis line segments
1272
-
1273
- # draw the box part of the camera
1274
- smb.plot_cuboid(
1275
- sides=np.r_[W, W, L] * scale,
1276
- pose=pose,
1277
- filled=solid,
1278
- color=color,
1279
- alpha=0.5 * alpha if solid else alpha,
1280
- ax=ax,
1281
- )
1282
-
1283
- # draw the lens
1284
- smb.plot_cylinder(
1285
- radius=cr * scale,
1286
- height=np.r_[L / 2, L / 2 + ch] * scale,
1287
- resolution=cn,
1288
- pose=pose,
1289
- filled=solid,
1290
- color=color,
1291
- alpha=0.5 * alpha,
1292
- ax=ax,
1293
- )
1294
-
1295
- if label:
1296
- ax.set_xlabel("X")
1297
- ax.set_ylabel("Y")
1298
- ax.set_zlabel("Z")
1222
+ self._plot_camera_icon(ax, pose, scale, solid, color, alpha, label)
1299
1223
 
1300
1224
  if frame is True:
1301
1225
  self.pose.plot(
@@ -1311,6 +1235,97 @@ class CameraBase(ABC):
1311
1235
 
1312
1236
  return ax
1313
1237
 
1238
+ def _plot_frustum(self, ax: Axes, pose: SE3, scale: float, alpha: float) -> None:
1239
+ """Draw the ``shape="frustum"`` camera icon into ``ax``."""
1240
+ # TODO make this kwargs or optional inputs
1241
+ # side colors:
1242
+ # +x red
1243
+ # -y red
1244
+ # +y green
1245
+ # -y yellow
1246
+ length = scale
1247
+ widthb = scale / 10
1248
+ widtht = scale
1249
+ widthb /= 2
1250
+ widtht /= 2
1251
+ b0 = np.array([-widthb, -widthb, 0, 1])
1252
+ b1 = np.array([-widthb, widthb, 0, 1])
1253
+ b2 = np.array([widthb, widthb, 0, 1])
1254
+ b3 = np.array([widthb, -widthb, 0, 1])
1255
+ t0 = np.array([-widtht, -widtht, length, 1])
1256
+ t1 = np.array([-widtht, widtht, length, 1])
1257
+ t2 = np.array([widtht, widtht, length, 1])
1258
+ t3 = np.array([widtht, -widtht, length, 1])
1259
+
1260
+ # bottom/narrow end
1261
+ T = pose.A
1262
+ b0 = (T @ b0)[:-1]
1263
+ b1 = (T @ b1)[:-1]
1264
+ b2 = (T @ b2)[:-1]
1265
+ b3 = (T @ b3)[:-1]
1266
+
1267
+ # wide/top end
1268
+ t0 = (T @ t0)[:-1]
1269
+ t1 = (T @ t1)[:-1]
1270
+ t2 = (T @ t2)[:-1]
1271
+ t3 = (T @ t3)[:-1]
1272
+
1273
+ points = [
1274
+ np.array([b0, b1, t1, t0]), # -x face
1275
+ np.array([b1, b2, t2, t1]), # +y face
1276
+ np.array([b2, b3, t3, t2]), # +x face
1277
+ np.array([b3, b0, t0, t3]), # -y face
1278
+ ]
1279
+ poly = Poly3DCollection(points, facecolors=["r", "g", "r", "y"], alpha=alpha)
1280
+ ax.add_collection3d(poly)
1281
+
1282
+ def _plot_camera_icon(
1283
+ self,
1284
+ ax: Axes,
1285
+ pose: SE3,
1286
+ scale: float,
1287
+ solid: bool,
1288
+ color: str,
1289
+ alpha: float,
1290
+ label: bool,
1291
+ ) -> None:
1292
+ """Draw the ``shape="camera"`` box+cylinder icon into ``ax``."""
1293
+ # the box is centred at the origin and its centerline parallel to the
1294
+ # z-axis. Its z-extent is -bh/2 to bh/2.
1295
+ W = 0.5 # width & height of the box
1296
+ L = 1.2 # length of the box
1297
+ cr = 0.2 # cylinder radius
1298
+ ch = 0.4 # cylinder height
1299
+ cn = 12 # number of facets of cylinder
1300
+ a = 3 # length of axis line segments
1301
+
1302
+ # draw the box part of the camera
1303
+ smb.plot_cuboid(
1304
+ sides=np.r_[W, W, L] * scale,
1305
+ pose=pose,
1306
+ filled=solid,
1307
+ color=color,
1308
+ alpha=0.5 * alpha if solid else alpha,
1309
+ ax=ax,
1310
+ )
1311
+
1312
+ # draw the lens
1313
+ smb.plot_cylinder(
1314
+ radius=cr * scale,
1315
+ height=np.r_[L / 2, L / 2 + ch] * scale,
1316
+ resolution=cn,
1317
+ pose=pose,
1318
+ filled=solid,
1319
+ color=color,
1320
+ alpha=0.5 * alpha,
1321
+ ax=ax,
1322
+ )
1323
+
1324
+ if label:
1325
+ ax.set_xlabel("X")
1326
+ ax.set_ylabel("Y")
1327
+ ax.set_zlabel("Z")
1328
+
1314
1329
  def _add_noise_distortion(self, uv: np.ndarray) -> np.ndarray:
1315
1330
  """
1316
1331
  Add noise to pixel coordinates
@@ -1862,7 +1877,7 @@ class CentralCamera(CameraBase):
1862
1877
  """
1863
1878
  try:
1864
1879
  return 2 * np.arctan(np.r_[self.imagesize] / 2 * np.r_[self.rho] / self.f)
1865
- except:
1880
+ except (TypeError, AttributeError):
1866
1881
  raise ValueError("imagesize or rho properties not set")
1867
1882
 
1868
1883
  def distort(self, points: np.ndarray) -> np.ndarray:
@@ -11,7 +11,7 @@ import tempfile
11
11
  import webbrowser
12
12
  from collections import UserList, namedtuple
13
13
  from dataclasses import dataclass
14
- from typing import Any, cast
14
+ from typing import TYPE_CHECKING, Any, cast
15
15
 
16
16
  import cv2
17
17
  import matplotlib.pyplot as plt
@@ -24,6 +24,9 @@ import spatialmath.base as smb
24
24
  from machinevisiontoolbox.base import plot_labelbox, mpl_styling
25
25
  from machinevisiontoolbox.decorators import array_result, scalar_result
26
26
 
27
+ if TYPE_CHECKING:
28
+ from machinevisiontoolbox._image_typing import _ImageBase
29
+
27
30
  """
28
31
  NOTES
29
32
 
@@ -458,7 +461,10 @@ class Blobs(UserList): # lgtm[py/missing-equals]
458
461
 
459
462
  ## Equivalent ellipse
460
463
  J = np.array([[M["mu20"], M["mu11"]], [M["mu11"], M["mu02"]]])
461
- e, X = np.linalg.eig(J)
464
+ # J is real-symmetric, so use eigh (not eig): eig can return
465
+ # complex128 for a symmetric matrix due to floating-point
466
+ # noise even though the eigenvalues are mathematically real.
467
+ e, X = np.linalg.eigh(J)
462
468
  blob_params["a"] = 2.0 * np.sqrt(e.max() / M["m00"])
463
469
  blob_params["b"] = 2.0 * np.sqrt(e.min() / M["m00"])
464
470
 
@@ -631,7 +637,7 @@ class Blobs(UserList): # lgtm[py/missing-equals]
631
637
  return self[:]
632
638
  m: np.ndarray = np.array(mask).all(axis=0) # type: ignore[assignment]
633
639
 
634
- return self[m]
640
+ return self[m.flatten()]
635
641
 
636
642
  def sort(self, by: str = "area", reverse: bool = False) -> "Blobs": # type: ignore[override]
637
643
  """
@@ -2620,7 +2626,7 @@ class Blobs(UserList): # lgtm[py/missing-equals]
2620
2626
  dot_stream.close()
2621
2627
 
2622
2628
 
2623
- class ImageBlobsMixin:
2629
+ class ImageBlobsMixin(_ImageBase if TYPE_CHECKING else object):
2624
2630
  def blobs(self, **kwargs) -> Blobs:
2625
2631
  """
2626
2632
  Find and describe blobs in image