v2.4.0

v2.4.0 rewrites find_lines() as a Hough-transform detector, adds find_line_segments(), find_datamatrices() data-matrix decoding, sensor.set_vsync_output(), image-slice read/write, and many new scaled framesizes for higher FPS. find_lines(), match_descriptor(), and skip_frames() changed — read the breaking changes below.

Highlights

  • find_lines() — rewritten as a Hough-transform line detector returning line objects (now works on RGB565, not just grayscale).

  • find_line_segments() — detect finite line segments.

  • find_datamatrices() — data-matrix decoding.

  • sensor.set_vsync_output() — drive VSYNC on an I/O pin for camera synchronization.

  • More framesizes — many additional scaled resolutions for higher FPS.

  • Breaking: find_lines(), match_descriptor(), and skip_frames() changed — see the breaking changes.

New features

  • image.find_line_segments() — find non-infinite line segments; line objects gained a .length() accessor.

  • image.find_datamatrices() — data-matrix decoding, with example scripts.

  • sensor.set_vsync_output(pin) — output the VSYNC signal on a GPIO pin for camera synchronization (OpenMV 2 / OpenMV 3).

  • Image slices — image subscript / buffer protocol now supports reading and writing slices of the image data.

  • Added many additional scaled resolution / framesize combinations to support higher frame rates; clock.fps() now resets its accumulators every 2 s so the reported FPS tracks the recent rate.

Other changes and improvements

  • The OV7725 is windowed to QVGA when the resolution is ≤ VGA (fewer dropped frames at high capture rates) and its PLL was set to 6× with a reduced external clock (OpenMV 2 48 MHz, OpenMV 3 54 MHz), altering sensor frame timing.

Bug fixes

Imaging:

  • Fixed the compress_for_ide() buffer-size error (start/end marker), QR decoding (plus upstream quirc cell-bitmap indexing and alignment-pattern bounds fixes).

Sensor and connectivity:

  • Lowered the OpenMV 2 sensor clock to work with the higher sensor PLL (camera init/sync) and made WINC socket.recvfrom() return the actual received size (erroring on a non-positive size instead of returning a stale value).

Hardware and board support

  • VSYNC output on a GPIO pin (OpenMV 2 / OpenMV 3) backing sensor.set_vsync_output().

  • OpenMV 3 — enabled pyb.UART UART1.

Breaking API changes

User-visible API breaks between v2.3.0 and v2.4.0. Scope: Python C-modules in modules/ and Python libraries in scripts/libraries/.

Each change is tagged with its impact:

  • major — affects most scripts that used the feature; you will need to port code.

  • minor — narrow API; only affects scripts that used it.

  • behavior — same API, different results; re-check tuned scripts.

Changes are grouped by impact in that order. If you just want to port your code, jump to the migration checklist at the end. Each commit hash links to its diff on GitHub.

find_lines() rewritten as a Hough detector (major)

image.find_lines() was rewritten as a Hough-transform detector. It no longer returns a list of (x1, y1, x2, y2) tuples — it returns line objects (.line() / .x1() / .y1() / .x2() / .y2() / .theta() / .rho() / .magnitude()) — and now also works on RGB565 (not just grayscale). The threshold argument changed from a 0.0–1.0 float to an integer edge-magnitude sum, line.magnitude is now an integer, and new theta_margin / rho_margin keywords were added. Port tuple-unpacking code to the line objects and re-tune threshold.

Commits: 31b7b5bf3, f4a9c6154

match_descriptor() returns a match object (minor)

image.match_descriptor() (ORB) now returns a kptmatch object with .cx() / .cy() / .x() / .y() / .w() / .h() / .count() / .theta() / .rect() accessors instead of a plain 8-tuple. The object is still subscriptable/sliceable so positional indexing keeps working, but code that did isinstance(result, tuple) (or used tuple methods) must use the new accessors.

Commits: e960546b6

sensor.skip_frames() is now time-based (behavior)

sensor.skip_frames() was reworked to accept a time= keyword (default ~300 ms) and is now time-based by default rather than running a fixed frame count, stopping early once the time elapses. Scripts that relied on an exact frame count should pass an explicit count and/or set time= accordingly.

Commits: a039b5d1c

Migration checklist

For a clean port to v2.4.0 the typical work is:

  1. Port find_lines() tuple unpacking to the line objects and re-tune the integer threshold (the find_lines rewrite).

  2. Use the kptmatch accessors instead of treating match_descriptor() results as a tuple (the match_descriptor change).

  3. Pass an explicit count and/or time= to sensor.skip_frames() if you relied on a fixed frame count (the skip_frames change).

All other scripts run unchanged.