@@ -97,6 +97,171 @@ Caffe model support was dropped; these constructors now take ONNX model paths:
9797| ` new BarcodeDetector(superResolutionPrototxtPath, superResolutionCaffeModelPath) ` | ` new BarcodeDetector(superResolutionModelPath = "") ` |
9898| ` new WeChatQRCode(detectorPrototxt, detectorCaffe, srPrototxt, srCaffe) ` | ` new WeChatQRCode(detectorModelPath = "", superResolutionModelPath = "") ` |
9999
100+ ## 3b. Additional findings from real-world migration testing (raw notes, needs editing pass)
101+
102+ The following was found by taking the ` opencvsharp_samples ` repo and actually
103+ migrating every sample project from OpenCvSharp4 to a locally-built
104+ OpenCvSharp5 beta package. Not yet cross-checked against other modules or
105+ polished into the rest of this document — treat as a raw findings dump for a
106+ future editing pass.
107+
108+ ### ` Cv2.Dnn.ReadNet(model, config) ` is NOT a working fallback for Caffe/Darknet
109+
110+ The "Removed APIs" table above says to use ONNX for Caffe/Darknet models, but
111+ it's worth being explicit: the generic dispatcher `Cv2.Dnn.ReadNet(model,
112+ config)` ( ` cv::dnn::readNet` in ` opencv/modules/dnn/src/dnn_read.cpp`)
113+ still * detects* ` .caffemodel ` /` .prototxt ` /` .weights ` /` .cfg ` extensions, but on
114+ match it unconditionally throws:
115+
116+ ```
117+ cv::Exception: Caffe importer has been removed. Please use ONNX-converted models or use an older OpenCV version.
118+ ```
119+
120+ (same for Darknet). So there is no code-level workaround at all for
121+ Caffe/Darknet models in OpenCvSharp5 — model conversion to ONNX is mandatory,
122+ not just recommended. (The ` opencvsharp_samples ` samples that loaded
123+ ` .caffemodel ` files — ` CaffeSample ` , ` FaceDetectionDNN ` , ` HandPose ` , ` Pose ` —
124+ were deleted outright rather than "fixed", since there is nothing to fix them
125+ to without a different model file.)
126+
127+ ### Minor: ` ReadNetFromOnnx ` casing is inconsistent between ` Cv2.Dnn ` and ` Net `
128+
129+ ` Cv2.Dnn.ReadNetFromOnnx ` (lowercase ` nnx ` ) forwards to ` Net.ReadNetFromONNX `
130+ (uppercase ` ONNX ` ). Pick one casing convention; right now the facade and the
131+ underlying type disagree with each other, and this migration doc's own
132+ "Removed APIs" table used the ` ONNX ` casing (inherited from the ` Net ` side) —
133+ worth double-checking every mention once one casing is chosen.
134+
135+ ### ` OutputArray.Create(List<T>) ` (write-back into a ` List<T> ` ) was removed
136+
137+ This is a genuine removed API, missing from the "Removed APIs" table above.
138+ OpenCvSharp4 let you pass a ` List<T> ` as an output sink, e.g.:
139+
140+ ``` csharp
141+ var output = new List <byte >();
142+ Cv2 .Threshold (InputArray .Create (input ), OutputArray .Create (output ), T , Max , ThresholdTypes .Binary );
143+ ```
144+
145+ ` OutputArray.Create(List<T>) ` no longer exists. Use a ` Mat ` as the output and
146+ pull the array back out with ` Mat.GetArray<T>(out T[]) ` :
147+
148+ ``` csharp
149+ using var output = new Mat ();
150+ Cv2 .Threshold (InputArray .Create (input ), output , T , Max , ThresholdTypes .Binary );
151+ output .GetArray (out byte [] outputArr );
152+ ```
153+
154+ This was removed as "dead scaffolding" (issue #1976 step 4), but real sample
155+ code in ` opencvsharp_samples ` (` NormalArrayOperations ` , ` SolveEquation ` ) was
156+ using it, so "dead" was inaccurate — flag this if the same reasoning gets
157+ applied to other APIs going forward.
158+
159+ ### ` null ` no longer works for optional ` InputArray ` /` OutputArray ` /` InputOutputArray ` parameters — use ` default `
160+
161+ ` InputArray ` / ` OutputArray ` / ` InputOutputArray ` are now `readonly ref
162+ struct`s (see the InputArray/OutputArray ref-struct redesign, issue #1976 ),
163+ so they can't be ` null ` . Any call site that used to pass a literal ` null ` for
164+ an optional mask/array parameter (e.g. `Feature2D.DetectAndCompute(image,
165+ null, out keypoints, descriptors)` , ` Cv2.CalcHist(..., null, ...)`,
166+ ` Cv2.Dilate(src, dst, null) ` ) now needs ` default ` instead:
167+
168+ ``` csharp
169+ sift .DetectAndCompute (gray , default , out var keypoints , descriptors ); // was: null
170+ ```
171+
172+ This is the same convention already used in ` test/OpenCvSharp.Tests ` (e.g.
173+ ` FlannBasedMatcherTest.cs ` , ` ORBTest.cs ` ), so it's at least consistent — but
174+ it isn't mentioned anywhere in this migration doc yet, and the compiler error
175+ you get (`CS0037: cannot convert null to 'InputArray' because it's a
176+ non-nullable value type` ) doesn't point at ` default` as the fix.
177+
178+ ### ` Mat ` 's fluent Cv2-wrapper instance methods were removed entirely (huge blast radius)
179+
180+ ` Mat_CvMethods.cs ` — the file of ` Mat ` instance methods that wrapped ` Cv2 `
181+ static methods purely for chainable call syntax (` mat.Circle(...) ` ,
182+ ` mat.Line(...) ` , ` mat.Rectangle(...) ` , ` mat.PutText(...) ` ,
183+ ` mat.Polylines(...) ` , ` mat.CvtColor(...) ` , ` mat.Threshold(...) ` ,
184+ ` mat.Resize(...) ` , ` mat.SaveImage(...) ` , ` mat.HoughCircles(...) ` ,
185+ ` mat.MinEnclosingCircle(...) ` , and many more — over 2300 lines) — was deleted
186+ outright (commit ` 446c36b8 ` , "Remove Mat_CvMethods.cs fluent Cv2 wrappers
187+ (Mat instance methods)"). Rationale from the commit message: the duplication
188+ doubled the maintenance surface of every ` Cv2 ` method, and intermediate
189+ ` Mat ` s produced mid-chain couldn't be captured with ` using ` , leaking into
190+ non-deterministic GC-driven native cleanup.
191+
192+ This is an intentional, deliberate, already-decided breaking change — not a
193+ bug — but its real-world impact is large: migrating the ~ 20 files in
194+ ` opencvsharp_samples ` that used this fluent style touched ** every single
195+ non-GUI sample that draws or converts a ` Mat ` ** . The compile error gives zero
196+ indication of what changed (`CS1061: 'Mat' does not contain a definition for
197+ 'Circle'`), so anyone hitting this needs to already know the fluent API was
198+ removed. This deserves prominent, explicit coverage in the migration guide —
199+ probably its own top-level section — since it's likely the single most common
200+ break for existing OpenCvSharp4 code, more so than any of the renames above.
201+
202+ Migration pattern is mechanical: ` mat.Xxx(args) ` → ` Cv2.Xxx(mat, args) `
203+ (insert the ` Mat ` as the first argument). Two subtleties found in practice:
204+
205+ - Methods that used to * return a new Mat* (` var gray = src.CvtColor(code); ` ,
206+ ` var t = src.Threshold(...) ` ) need an explicit destination ` Mat ` created
207+ first: ` using var gray = new Mat(); Cv2.CvtColor(src, gray, code); ` .
208+ - ` Mat.Resize(...) ` collides with an unrelated, still-existing instance
209+ method: ` Mat.Resize(int sz) ` / ` Mat.Resize(int sz, Scalar s) ` (std::vector
210+ -style row-count resize, present since OpenCvSharp4). Callers who meant
211+ "image resize" and got a "wrong number of arguments" error rather than a
212+ "no such method" error should be pointed at `Cv2.Resize(src, dst, size,
213+ fx, fy, interpolation)` explicitly, since overload resolution won't say
214+ "did you mean Cv2.Resize" for them.
215+
216+ ### ` MatExpr ` is no longer ` IDisposable ` — drop ` using ` on it
217+
218+ Consistent with the ` MatExpr ` lazy-tree rework: ` Mat.Zeros(...) ` , ` Mat.Eye(...) ` ,
219+ ` mat.T() ` , and Mat arithmetic operators (` + ` , ` * ` , ` -0.5 ` , ...) now return a
220+ ` MatExpr ` that is a lightweight managed value, not a disposable native
221+ handle. Code that did ` using var x = Mat.Zeros(...); ` or `using var t = a *
222+ b;` now fails with ` CS1674: 'MatExpr': type used in a using statement must be
223+ implicitly convertible to 'System.IDisposable'`. Fix is to just drop the
224+ ` using ` /` using var ` (` var x = Mat.Zeros(...); ` ). If the declared type is
225+ explicitly ` Mat ` rather than ` var ` (e.g. ` using (Mat img = Mat.Zeros(...)) ` ),
226+ it still compiles and still needs disposal, because ` MatExpr ` has an
227+ implicit conversion to ` Mat ` that materializes it.
228+
229+ ### Namespace churn in ` features ` /` xfeatures2d ` beyond what's listed above
230+
231+ Found while migrating ` SiftSurfSample ` , ` BRISKSample ` , ` KAZESample* ` :
232+
233+ - ` SIFT ` moved out of ` OpenCvSharp.Features2D ` and now lives directly in
234+ ` OpenCvSharp ` (the ` OpenCvSharp.Features2D ` namespace no longer exists at
235+ all).
236+ - ` BRISK ` , ` KAZE ` , ` AKAZE ` moved the * other* direction: from ` OpenCvSharp `
237+ into ` OpenCvSharp.XFeatures2D ` .
238+ - ` SURF ` was already in ` OpenCvSharp.XFeatures2D ` in OpenCvSharp4, unchanged.
239+
240+ Worth a full sweep of every ` features ` /` xfeatures2d ` type's namespace before
241+ finalizing this doc, since the above was only what surfaced through the
242+ samples actually exercised.
243+
244+ ### Aruco: ` DetectMarkers ` is a structural change, not just a ` CvAruco ` → ` Cv2.Aruco ` rename
245+
246+ Beyond the ` CvAruco.Xxx ` → ` Cv2.Aruco.Xxx ` facade rename already documented
247+ above, ` DetectMarkers ` itself moved from being a static one-shot call to an
248+ instance method on ` ArucoDetector ` (constructed once from a ` Dictionary ` +
249+ ` DetectorParameters ` + ` RefineParameters ` , then reused):
250+
251+ ``` csharp
252+ // OpenCvSharp4
253+ CvAruco .DetectMarkers (image , dictionary , out corners , out ids , detectorParameters , out rejected );
254+
255+ // OpenCvSharp5
256+ using var dictionary = Cv2 .Aruco .GetPredefinedDictionary (PredefinedDictionaryType .Dict4X4_1000 );
257+ using var detector = new ArucoDetector (dictionary , detectorParameters , new RefineParameters ());
258+ detector .DetectMarkers (image , out corners , out ids , out rejected );
259+ ```
260+
261+ This mirrors the OpenCV 5 C++ API shape (` cv::aruco::ArucoDetector ` ), so it's
262+ expected/upstream-driven, but it's a bigger call-site change than the simple
263+ prefix swap the existing table above implies.
264+
100265## 4. OpenCV 5 API changes surfaced through the wrapper
101266
102267OpenCV 5 reorganizes modules and changes some APIs. The managed surface follows
0 commit comments