|
26 | 26 | micropy_all_versions = (os.getenv("MICROPY_ALL_VERSIONS") or "latest").split(",") |
27 | 27 | url_pattern = "%s/en/%%s" % (os.getenv("MICROPY_URL_PREFIX") or "/",) |
28 | 28 |
|
29 | | -# The OpenMV firmware version this documentation describes. |
| 29 | +# ============================================================================= |
| 30 | +# Documentation versions and build date — bump these for each release. |
| 31 | +# ============================================================================= |
| 32 | +import datetime as _dt |
| 33 | + |
| 34 | +# OpenMV firmware version this documentation covers. |
30 | 35 | openmv_version = "5.0.0" |
31 | 36 |
|
| 37 | +# MicroPython version that the firmware is built on top of. |
| 38 | +# (Also used as the Sphinx ``version`` / ``release`` variables below.) |
| 39 | +micropython_version = "1.28" |
| 40 | + |
| 41 | +# Build date is computed automatically each time Sphinx runs. |
| 42 | +build_date = _dt.date.today().strftime("%d %b %Y") |
| 43 | + |
32 | 44 | # The members of the html_context dict are available inside topindex.html |
33 | 45 | html_context = { |
34 | 46 | "cur_version": micropy_version, |
|
38 | 50 | ], |
39 | 51 | "is_release": micropy_version != "latest", |
40 | 52 | "openmv_version": openmv_version, |
| 53 | + "micropython_version": micropython_version, |
| 54 | + "build_date": build_date, |
| 55 | +} |
| 56 | + |
| 57 | +# -- Landing page code examples (rendered via Pygments to match site code style) -- |
| 58 | +from pygments import highlight as _pygments_highlight |
| 59 | +from pygments.lexers import PythonLexer as _PythonLexer |
| 60 | +from pygments.formatters import HtmlFormatter as _HtmlFormatter |
| 61 | + |
| 62 | +_landing_examples_src = { |
| 63 | + "yolo": ''' |
| 64 | +import csi |
| 65 | +import time |
| 66 | +import ml |
| 67 | +from ml.postprocessing.ultralytics import YoloV8 |
| 68 | +
|
| 69 | +csi0 = csi.CSI() |
| 70 | +csi0.reset() |
| 71 | +csi0.pixformat(csi.RGB565) |
| 72 | +csi0.framesize(csi.VGA) |
| 73 | +
|
| 74 | +# Built-in single-class person detector model. |
| 75 | +model = ml.Model("/rom/yolov8n_192.tflite", |
| 76 | + postprocess=YoloV8(threshold=0.4)) |
| 77 | +clock = time.clock() |
| 78 | +
|
| 79 | +while True: |
| 80 | + clock.tick() |
| 81 | + img = csi0.snapshot() |
| 82 | + # predict returns a list per class of ((x, y, w, h), score) tuples. |
| 83 | + for class_dets in model.predict([img]): |
| 84 | + for rect, score in class_dets: |
| 85 | + img.draw_rectangle(rect, color=(0, 255, 0)) |
| 86 | + print(clock.fps(), "fps") |
| 87 | +''', |
| 88 | + "apriltag": ''' |
| 89 | +import csi |
| 90 | +import math |
| 91 | +import time |
| 92 | +
|
| 93 | +csi0 = csi.CSI() |
| 94 | +csi0.reset() |
| 95 | +csi0.pixformat(csi.RGB565) |
| 96 | +csi0.framesize(csi.QVGA) |
| 97 | +csi0.auto_gain(False) |
| 98 | +csi0.auto_whitebal(False) |
| 99 | +
|
| 100 | +clock = time.clock() |
| 101 | +
|
| 102 | +while True: |
| 103 | + clock.tick() |
| 104 | + img = csi0.snapshot() |
| 105 | + for tag in img.find_apriltags(): |
| 106 | + img.draw_detection(tag, color1=(255, 0, 0), color2=(0, 255, 0)) |
| 107 | + deg = math.degrees(tag.rotation) |
| 108 | + print("ID %d rotation %.1f deg" % (tag.id, deg)) |
| 109 | + print(clock.fps(), "fps") |
| 110 | +''', |
| 111 | + "blazeface": ''' |
| 112 | +import csi |
| 113 | +import time |
| 114 | +import ml |
| 115 | +from ml.postprocessing.mediapipe import BlazeFace |
| 116 | +
|
| 117 | +csi0 = csi.CSI() |
| 118 | +csi0.reset() |
| 119 | +csi0.pixformat(csi.RGB565) |
| 120 | +csi0.framesize(csi.VGA) |
| 121 | +csi0.window((400, 400)) # square window for best results |
| 122 | +
|
| 123 | +model = ml.Model("/rom/blazeface_front_128.tflite", |
| 124 | + postprocess=BlazeFace(threshold=0.4)) |
| 125 | +clock = time.clock() |
| 126 | +
|
| 127 | +while True: |
| 128 | + clock.tick() |
| 129 | + img = csi0.snapshot() |
| 130 | + for rect, score, keypoints in model.predict([img]): |
| 131 | + img.draw_rectangle(rect, color=(0, 0, 255)) |
| 132 | + ml.utils.draw_keypoints(img, keypoints, color=(255, 0, 0)) |
| 133 | + print(clock.fps(), "fps") |
| 134 | +''', |
| 135 | + "qrcode": ''' |
| 136 | +import csi |
| 137 | +import time |
| 138 | +
|
| 139 | +csi0 = csi.CSI() |
| 140 | +csi0.reset() |
| 141 | +csi0.pixformat(csi.RGB565) |
| 142 | +csi0.framesize(csi.QVGA) |
| 143 | +csi0.auto_gain(False) |
| 144 | +
|
| 145 | +clock = time.clock() |
| 146 | +
|
| 147 | +while True: |
| 148 | + clock.tick() |
| 149 | + img = csi0.snapshot() |
| 150 | + for code in img.find_qrcodes(): |
| 151 | + img.draw_rectangle(code.rect, color=(255, 0, 0)) |
| 152 | + print(code.payload) |
| 153 | + print(clock.fps(), "fps") |
| 154 | +''', |
| 155 | + "color": ''' |
| 156 | +import csi |
| 157 | +import time |
| 158 | +
|
| 159 | +csi0 = csi.CSI() |
| 160 | +csi0.reset() |
| 161 | +csi0.pixformat(csi.RGB565) |
| 162 | +csi0.framesize(csi.QVGA) |
| 163 | +csi0.auto_gain(False) |
| 164 | +csi0.auto_whitebal(False) |
| 165 | +
|
| 166 | +# LAB thresholds: (L_min, L_max, A_min, A_max, B_min, B_max) |
| 167 | +thresholds = [ |
| 168 | + (30, 100, 15, 127, 15, 127), # red |
| 169 | + (30, 100, -64, -8, -32, 32), # green |
| 170 | +] |
| 171 | +
|
| 172 | +clock = time.clock() |
| 173 | +
|
| 174 | +while True: |
| 175 | + clock.tick() |
| 176 | + img = csi0.snapshot() |
| 177 | + for blob in img.find_blobs(thresholds, pixels_threshold=200): |
| 178 | + img.draw_rectangle(blob.rect, color=(255, 0, 0)) |
| 179 | + img.draw_cross((blob.cx, blob.cy)) |
| 180 | + print(clock.fps(), "fps") |
| 181 | +''', |
| 182 | + "barcode": ''' |
| 183 | +import csi |
| 184 | +import time |
| 185 | +
|
| 186 | +csi0 = csi.CSI() |
| 187 | +csi0.reset() |
| 188 | +csi0.pixformat(csi.GRAYSCALE) |
| 189 | +csi0.framesize(csi.VGA) |
| 190 | +csi0.window((640, 80)) # narrow strip for fast linear scanning |
| 191 | +csi0.auto_gain(False) |
| 192 | +csi0.auto_whitebal(False) |
| 193 | +
|
| 194 | +clock = time.clock() |
| 195 | +
|
| 196 | +while True: |
| 197 | + clock.tick() |
| 198 | + img = csi0.snapshot() |
| 199 | + for code in img.find_barcodes(): |
| 200 | + img.draw_rectangle(code.rect, color=(0, 255, 0)) |
| 201 | + print(code.payload, "(quality %d)" % code.quality) |
| 202 | + print(clock.fps(), "fps") |
| 203 | +''', |
| 204 | + "hand": ''' |
| 205 | +import csi |
| 206 | +import time |
| 207 | +import ml |
| 208 | +from ml.postprocessing.mediapipe import HandLandmarks |
| 209 | +
|
| 210 | +csi0 = csi.CSI() |
| 211 | +csi0.reset() |
| 212 | +csi0.pixformat(csi.RGB565) |
| 213 | +csi0.framesize(csi.VGA) |
| 214 | +csi0.window((400, 400)) # square window for the model |
| 215 | +
|
| 216 | +# Connections between the 21 keypoints — palm + 5 fingers. |
| 217 | +hand_lines = ((0, 1), (1, 2), (2, 3), (3, 4), (0, 5), (5, 6), |
| 218 | + (6, 7), (7, 8), (5, 9), (9, 10), (10, 11), (11, 12), |
| 219 | + (9, 13), (13, 14), (14, 15), (15, 16), (13, 17), (17, 18), |
| 220 | + (18, 19), (19, 20), (0, 17)) |
| 221 | +
|
| 222 | +model = ml.Model("/rom/hand_landmarks_full_224.tflite", |
| 223 | + postprocess=HandLandmarks(threshold=0.4)) |
| 224 | +clock = time.clock() |
| 225 | +
|
| 226 | +while True: |
| 227 | + clock.tick() |
| 228 | + img = csi0.snapshot() |
| 229 | + # predict returns a list per hand: index 0 = left, index 1 = right. |
| 230 | + for detections in model.predict([img]): |
| 231 | + for rect, score, keypoints in detections: |
| 232 | + ml.utils.draw_skeleton(img, keypoints, hand_lines, |
| 233 | + kp_color=(255, 0, 0), |
| 234 | + line_color=(0, 255, 0)) |
| 235 | + print(clock.fps(), "fps") |
| 236 | +''', |
| 237 | +} |
| 238 | + |
| 239 | +def _render_landing_code(src): |
| 240 | + return _pygments_highlight( |
| 241 | + src.strip(), _PythonLexer(), |
| 242 | + _HtmlFormatter(nowrap=False, cssclass="highlight"), |
| 243 | + ) |
| 244 | + |
| 245 | +html_context["landing_examples"] = { |
| 246 | + k: _render_landing_code(v) for k, v in _landing_examples_src.items() |
41 | 247 | } |
42 | 248 |
|
43 | 249 | # Authors used in various parts of the documentation. |
|
58 | 264 | "sphinx.ext.intersphinx", |
59 | 265 | "sphinx.ext.todo", |
60 | 266 | "sphinx.ext.coverage", |
61 | | - "sphinxcontrib.jquery", |
62 | | - "sphinx_rtd_theme", |
63 | 267 | ] |
64 | 268 |
|
65 | 269 | # Add any paths that contain templates here, relative to this directory. |
|
76 | 280 |
|
77 | 281 | # General information about the project. |
78 | 282 | project = "MicroPython" |
79 | | -copyright = "- The MicroPython Documentation is Copyright © 2014-2026, Damien P. George, Paul Sokolovsky, OpenMV LLC, and contributors" |
| 283 | +copyright = "The OpenMV MicroPython Documentation is Copyright © 2014-2026 by OpenMV, Damien P. George, and others." |
80 | 284 |
|
81 | 285 | # The version info for the project you're documenting, acts as replacement for |
82 | 286 | # |version| and |release|, also used in various other places throughout the |
83 | 287 | # built documents. |
84 | 288 | # |
85 | 289 | # We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags" |
86 | 290 | # breakdown, so use the same version identifier for both to avoid confusion. |
87 | | -version = release = "1.28" |
| 291 | +version = release = micropython_version |
88 | 292 |
|
89 | 293 | # The language for content autogenerated by Sphinx. Refer to documentation |
90 | 294 | # for a list of supported languages. |
|
207 | 411 |
|
208 | 412 | # -- Options for HTML output ---------------------------------------------- |
209 | 413 |
|
210 | | -import sphinx_rtd_theme |
211 | | - |
212 | | -on_rtd = os.environ.get("READTHEDOCS", None) == "True" |
213 | | - |
214 | | -if not on_rtd: # only import and set the theme if we're building docs locally |
215 | | - try: |
216 | | - import sphinx_rtd_theme |
217 | | - |
218 | | - html_theme = "sphinx_rtd_theme" |
219 | | - except: |
220 | | - html_theme = "default" |
221 | | - html_theme_path = ["."] |
222 | | -else: |
223 | | - html_theme_path = ["."] |
| 414 | +html_theme = "shibuya" |
224 | 415 |
|
225 | 416 | # Theme options are theme-specific and customize the look and feel of a theme |
226 | 417 | # further. For a list of options available for each theme, see the |
227 | 418 | # documentation. |
228 | | -# html_theme_options = {} |
| 419 | +html_theme_options = { |
| 420 | + "light_logo": "_static/openmv-logo-light.png", |
| 421 | + "dark_logo": "_static/openmv-logo-dark.png", |
| 422 | + "accent_color": "blue", |
| 423 | + "color_mode": "auto", |
| 424 | + "github_url": "https://github.com/openmv/openmv", |
| 425 | + "discussion_url": "https://forums.openmv.io/", |
| 426 | + "globaltoc_expand_depth": 1, |
| 427 | + "toctree_collapse": True, |
| 428 | + "show_ai_links": False, |
| 429 | + "nav_links": [ |
| 430 | + {"title": "Home", "url": "index"}, |
| 431 | + {"title": "Quick start", "url": "openmvcam/tutorial/software_setup"}, |
| 432 | + {"title": "Tutorial", "url": "openmvcam/tutorial/index"}, |
| 433 | + {"title": "Library", "url": "library/index"}, |
| 434 | + {"title": "Boards", "url": "openmvcam/quickref"}, |
| 435 | + ], |
| 436 | +} |
229 | 437 |
|
230 | 438 | # Add any paths that contain custom themes here, relative to this directory. |
231 | 439 | # html_theme_path = ['.'] |
|
326 | 534 | master_doc, |
327 | 535 | "MicroPython.tex", |
328 | 536 | "MicroPython Documentation", |
329 | | - "Damien P. George, Paul Sokolovsky, OpenMV LLC, and contributors", |
| 537 | + "OpenMV, Damien P. George, and others", |
330 | 538 | "manual", |
331 | 539 | ), |
332 | 540 | ] |
|
363 | 571 | "index", |
364 | 572 | "micropython", |
365 | 573 | "MicroPython Documentation", |
366 | | - ["Damien P. George, Paul Sokolovsky, OpenMV LLC, and contributors"], |
| 574 | + ["OpenMV, Damien P. George, and others"], |
367 | 575 | 1, |
368 | 576 | ), |
369 | 577 | ] |
|
382 | 590 | master_doc, |
383 | 591 | "MicroPython", |
384 | 592 | "MicroPython Documentation", |
385 | | - "Damien P. George, Paul Sokolovsky, OpenMV LLC, and contributors", |
| 593 | + "OpenMV, Damien P. George, and others", |
386 | 594 | "MicroPython", |
387 | 595 | "One line description of project.", |
388 | 596 | "Miscellaneous", |
|
0 commit comments