Repository navigation
v0.27.0
What changed and why
Cropping is its own tool now — CvCropOpt with CvImageOps.Crop. CvImageProcessOpt / Preprocess only
resample and denoise. This is a breaking change on purpose; the old call sites stop compiling.
A consumer inspects parts that are small in the field of view and sit off-centre, and wants to cut them out
before inspecting and to show the result on the cut-out. Cropping and image cleanup are different jobs, so
they are separate tools even though a chain gets one tool longer.
CvCropOpt—UseCrop,CropX/CropY/CropW/CropHin original-image coordinates, with its edit shape.
The property names are the onesCvImageProcessOptused to carry, so an old image-process file read as a
CvCropOptgives the crop back, and handlers keyed by property name keep working on the new tool.CvImageOps.Crop(Mat src, CvCropOpt opt, out Rect used)— returns a copy and the rect it used (the whole
image when the crop is off or falls back). A view would share memory with aCamFramewrapped byAsMat():
writing into it rewrites pixels that history and display still hold (a regression checks exactly this).
The copy is one pass over the region, or over the whole frame when the crop is off.CvImageOps.CropRectOf(Mat src, CvCropOpt opt)— the rect alone; same fallback as before (outside the image or
under 8 px → whole image plus a warning).CvImageOps.MapOf(Rect used, Mat pre)— the stage → original map, carrying both the crop origin and the scale.- Removed:
CvImageOps.CropRectOf(Mat, CvImageProcessOpt)andCvImageOps.MapOf(Mat, Mat, CvImageProcessOpt).
Keeping them as obsolete would have let a call compile against an image that was never cropped and add the
old offset to it.CvImageProcessOptno longer implementsICvShapeSource— it has no geometry left.
Migrating a call site:
// before
using var pre = CvImageOps.Preprocess(gray, ip);
var map = CvImageOps.MapOf(gray, pre, ip);
// after
using var cut = CvImageOps.Crop(gray, crop, out var used);
using var pre = CvImageOps.Preprocess(cut, ip);
var map = CvImageOps.MapOf(used, pre);
// no crop in this chain: pass the whole image rect
var map = CvImageOps.MapOf(new Rect(0, 0, gray.Cols, gray.Rows), pre);There is deliberately no MapOf(Mat, Mat): a cut image does not know where it was cut from, so such an overload
would get the scale right and silently drop the offset — every result drawn off by the crop origin, with nothing
looking wrong. Only Preprocess takes cut: the result overlay stays in original-frame coordinates, so arguments
that bound drawing to the image (ViDraw clipping sizes, the corner ViHud branches) keep the original frame size.
The first parameter of Preprocess and CropRectOf is now named src (was gray) — calls with named arguments
need the new name.
Recipes saved before 0.27. An image-process file with the crop on still loads — the old fields stay on
CvImageProcessOpt as hidden, obsolete properties, and they are written back on save until the crop is moved, so
a host that saves before migrating does not lose it. But Preprocess throws InvalidOperationException while an
unmoved crop is on. The tools after it were taught on the cut-out; running them on the whole image would put each
of them off by the crop origin and still produce verdicts that look normal. Move it when the recipe loads:
if (CvCropOpt.FromLegacy(ip) is { } moved) { /* use `moved` as the crop tool, then save the image-process file */ }FromLegacy returns the crop, turns it off on ip and logs one Info line. A crop saved without its size keys moves
at the old default size, 640×480, as 0.26 cut it. Save the image-process file again afterwards, or the crop is
moved again on the next load. With System.Text.Json that save also drops the old keys. Json.NET keeps writing
them as false/0, which reads back as a crop that is off. A file whose crop was off loads as before. The old
properties are [Obsolete]: code that sets them gets CS0618.
Migration is one-way. Once a migrated recipe is saved, a host on 0.26.x or earlier finds no crop in the
image-process file and does not know the crop tool. It runs uncropped, with no error. Roll recipes back together
with the host, and keep a copy from before the first 0.27 save.
Teaching screens: the image-process tool no longer shows the crop checkbox or rectangle. Add a CvCropOpt tool
in front of it.
Showing a result on the cropped region
ViOverlayLabel.IsHud— everyViHud.AddSummarybranch sets it. Renderers ignore it. Use it to find the summary
HUD instead of guessing from the alignment and text: corner alignment is also used for labels above detection boxes.ViOverlay.CropTo(x, y, width, height)— a new overlay for the cut-out. Items move by (−x, −y). The HUD goes back
to the same corner of the cut-out, whereAddSummarywould have put it on that image. A HUD given a start height
keeps that height. The source overlay is not touched, and items outside the region are kept — clipping is the
renderer's job. A label copied by hand withoutIsHudmoves like any other label.CamFrame.Crop(x, y, width, height)— a new frame with a tight stride. It keeps the format,DeviceTimestampand
TimestampUtc(it is the same shot). It throws if the region is not inside the frame, because the overlay moved
with the same rect would no longer match. Pass theusedrect fromCvImageOps.Crop.
Also
CvInspect.WpfREADME,Framerow: hiding and showing the control (a tab switch, a collapsed parent) is not a
resize. The zoom is kept unless the size changed while the control was hidden. A regression covers both cases.- Demo: a Crop tool. Loading a recipe folder saved before 0.27 inserts a Crop tool just above the Preprocess that
carried the crop.
Version
0.27.0 — minor. Added: CvCropOpt (+ FromLegacy), CvImageProcessOpt.HasLegacyCrop, CvImageOps.Crop,
CvImageOps.CropRectOf(Mat, CvCropOpt), CvImageOps.MapOf(Rect, Mat), ViOverlayLabel.IsHud, ViOverlay.CropTo,
CamFrame.Crop. Removed: CvImageOps.CropRectOf(Mat, CvImageProcessOpt),
CvImageOps.MapOf(Mat, Mat, CvImageProcessOpt), ICvShapeSource on CvImageProcessOpt. Obsolete:
CvImageProcessOpt.UseCrop/CropX/CropY/CropW/CropH. Changed: CvImageOps.Preprocess no longer crops and
throws on an unmoved crop; its first parameter is named src. CvInspect.Imaging.Gev has no change of its own.
Checks
-
dotnet build CvInspect.sln -c Release --no-incrementalreports 0 warnings -
mainis an ancestor of this branch (the release-pr-guard job verifies it) - the tag will be created on the merge commit,
mainmerged back intodevafterwards, anddevbumped to the next-devversion