Skip to content

Commit 2ce32dc

Browse files
committed
make improvements
1 parent a2b8541 commit 2ce32dc

File tree

1 file changed

+46
-33
lines changed

1 file changed

+46
-33
lines changed

Data_science/Mathematica/SignalProcessing/MachineVision/RANSAC/RANSACPointAlignment.vb

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,7 @@ Imports std = System.Math
6969
''' A static utility class for aligning two 2D polygons using the RANSAC algorithm.
7070
''' This version is optimized for correctness and includes a proper least-squares refinement step.
7171
''' </summary>
72-
Public NotInheritable Class RANSACPointAlignment
73-
74-
Private Sub New()
75-
' Prevent instantiation of this static class
76-
End Sub
72+
Public Module RANSACPointAlignment
7773

7874
''' <summary>
7975
''' Aligns a source polygon to a target polygon using RANSAC.
@@ -83,10 +79,10 @@ Public NotInheritable Class RANSACPointAlignment
8379
''' <param name="iterations">The number of RANSAC iterations.</param>
8480
''' <param name="distanceThreshold">The distance threshold to consider a point an inlier.</param>
8581
''' <returns>The best-fit Transform object.</returns>
86-
Public Shared Function AlignPolygons(sourcePoly As Polygon2D,
87-
targetPoly As Polygon2D,
88-
Optional iterations As Integer = 1000,
89-
Optional distanceThreshold As Double = 0.1) As AffineTransform
82+
Public Function AlignPolygons(sourcePoly As Polygon2D,
83+
targetPoly As Polygon2D,
84+
Optional iterations As Integer = 1000,
85+
Optional distanceThreshold As Double = 0.1) As AffineTransform
9086

9187
' Pre-check: need at least 3 points
9288
If sourcePoly.length < 2 OrElse targetPoly.length < 2 Then
@@ -156,7 +152,7 @@ Public NotInheritable Class RANSACPointAlignment
156152
''' <summary>
157153
''' Generates a list of candidate matches by finding the nearest neighbor in descriptor space.
158154
''' </summary>
159-
Private Shared Function GenerateCandidateMatches(ByRef sourceDesc As PointWithDescriptor(), ByRef targetDesc As PointWithDescriptor()) As List(Of (source As PointF, target As PointF))
155+
Private Function GenerateCandidateMatches(ByRef sourceDesc As PointWithDescriptor(), ByRef targetDesc As PointWithDescriptor()) As List(Of (source As PointF, target As PointF))
160156
Dim matches As New List(Of (source As PointF, target As PointF))()
161157

162158
Call $"Generates a list of candidate matches by finding the nearest neighbor in descriptor space.".debug
@@ -195,8 +191,8 @@ Public NotInheritable Class RANSACPointAlignment
195191
''' <summary>
196192
''' Computes an affine transform from exactly three point pairs.
197193
''' </summary>
198-
Private Shared Function ComputeAffineFrom3Pairs(p1 As PointF, p2 As PointF, p3 As PointF,
199-
q1 As PointF, q2 As PointF, q3 As PointF) As AffineTransform
194+
Private Function ComputeAffineFrom3Pairs(p1 As PointF, p2 As PointF, p3 As PointF,
195+
q1 As PointF, q2 As PointF, q3 As PointF) As AffineTransform
200196
' Solve the linear system for 6 parameters (a,b,c,d,e,f)
201197
' |x1 y1 1 0 0 0| |a| |x'1|
202198
' |x2 y2 1 0 0 0| |b| |x'2|
@@ -205,25 +201,31 @@ Public NotInheritable Class RANSACPointAlignment
205201
' |0 0 0 x2 y2 1| |e| |y'2|
206202
' |0 0 0 x3 y3 1| |f| |y'3|
207203
' We can solve this by splitting it into two 3x3 systems.
208-
Dim sourceX = {p1.X, p2.X, p3.X}
209-
Dim sourceY = {p1.Y, p2.Y, p3.Y}
210-
Dim targetX = {q1.X, q2.X, q3.X}
211-
Dim targetY = {q1.Y, q2.Y, q3.Y}
204+
' Dim sourceX = {p1.X, p2.X, p3.X}
205+
' Dim sourceY = {p1.Y, p2.Y, p3.Y}
206+
' Dim targetX = {q1.X, q2.X, q3.X}
207+
' Dim targetY = {q1.Y, q2.Y, q3.Y}
212208

213209
' Using the same least squares solver for the exact case
214-
Dim pairs As New List(Of (source As PointF, target As PointF)) From {
215-
(p1, q1), (p2, q2), (p3, q3)
216-
}
210+
Dim pairs As (source As PointF, target As PointF)() = {(p1, q1), (p2, q2), (p3, q3)}
217211
Dim a, b, c, d, e, f As Double
218-
SolveLeastSquaresAffine(pairs, a, b, c, d, e, f)
219212

220-
Return New AffineTransform With {.a = a, .b = b, .c = c, .d = d, .e = e, .f = f}
213+
Call SolveLeastSquaresAffine(pairs, a, b, c, d, e, f)
214+
215+
Return New AffineTransform With {
216+
.a = a,
217+
.b = b,
218+
.c = c,
219+
.d = d,
220+
.e = e,
221+
.f = f
222+
}
221223
End Function
222224

223225
''' <summary>
224226
''' Refines the transformation using all inliers with a least-squares fit for an affine transform.
225227
''' </summary>
226-
Private Shared Function RefineTransformWithLeastSquares(candidateMatches As List(Of (source As PointF, target As PointF)), initialTransform As AffineTransform, threshold As Double) As AffineTransform
228+
Private Function RefineTransformWithLeastSquares(candidateMatches As List(Of (source As PointF, target As PointF)), initialTransform As AffineTransform, threshold As Double) As AffineTransform
227229
Dim inlierPairs As New List(Of (source As PointF, target As PointF))
228230
Dim thresholdSq = threshold * threshold
229231
Dim errors As New List(Of Double)
@@ -248,23 +250,32 @@ Public NotInheritable Class RANSACPointAlignment
248250
End If
249251

250252
Dim a, b, c, d, e, f As Double
251-
SolveLeastSquaresAffine(inlierPairs, a, b, c, d, e, f)
252-
Return New AffineTransform With {.a = a, .b = b, .c = c, .d = d, .e = e, .f = f}
253+
254+
Call SolveLeastSquaresAffine(inlierPairs.ToArray, a, b, c, d, e, f)
255+
256+
Return New AffineTransform With {
257+
.a = a,
258+
.b = b,
259+
.c = c,
260+
.d = d,
261+
.e = e,
262+
.f = f
263+
}
253264
End Function
254265

255266
''' <summary>
256267
''' Solves the least-squares problem for affine transformation parameters.
257268
''' This function is unchanged from your original, as it was mathematically correct.
258269
''' </summary>
259-
Private Shared Sub SolveLeastSquaresAffine(points As List(Of (source As PointF, target As PointF)), ByRef a As Double, ByRef b As Double, ByRef c As Double, ByRef d As Double, ByRef e As Double, ByRef f As Double)
260-
Dim n = points.Count
270+
Private Sub SolveLeastSquaresAffine(ByRef points As (source As PointF, target As PointF)(), ByRef a As Double, ByRef b As Double, ByRef c As Double, ByRef d As Double, ByRef e As Double, ByRef f As Double)
271+
Dim n As Integer = points.Length
261272
Dim sumX, sumY, sumX2, sumY2, sumXY, sumXp, sumYp, sumXpX, sumXpY, sumYpX, sumYpY As Double
262273

263274
For Each pair In points
264-
Dim x = pair.source.X
265-
Dim y = pair.source.Y
266-
Dim xp = pair.target.X
267-
Dim yp = pair.target.Y
275+
Dim x As Double = pair.source.X
276+
Dim y As Double = pair.source.Y
277+
Dim xp As Double = pair.target.X
278+
Dim yp As Double = pair.target.Y
268279

269280
sumX += x : sumY += y
270281
sumX2 += x * x : sumY2 += y * y : sumXY += x * y
@@ -283,15 +294,17 @@ Public NotInheritable Class RANSACPointAlignment
283294

284295
' Solve two 3x3 systems (one for x', one for y')
285296
Dim det = ata_00 * (ata_11 * ata_22 - ata_12 * ata_21) -
286-
ata_01 * (ata_10 * ata_22 - ata_12 * ata_20) +
287-
ata_02 * (ata_10 * ata_21 - ata_11 * ata_20)
297+
ata_01 * (ata_10 * ata_22 - ata_12 * ata_20) +
298+
ata_02 * (ata_10 * ata_21 - ata_11 * ata_20)
288299

289300
If std.Abs(det) < 0.000000001 Then
290301
' Matrix is singular, cannot solve, return identity
291302
a = 1 : b = 0 : c = 0
292303
d = 0 : e = 1 : f = 0
304+
293305
Return
294306
End If
307+
295308
Dim invDet = 1.0 / det
296309

297310
Dim inv_00 = (ata_11 * ata_22 - ata_12 * ata_21) * invDet
@@ -313,4 +326,4 @@ Public NotInheritable Class RANSACPointAlignment
313326
e = inv_10 * atb_3 + inv_11 * atb_4 + inv_12 * atb_5
314327
f = inv_20 * atb_3 + inv_21 * atb_4 + inv_22 * atb_5
315328
End Sub
316-
End Class
329+
End Module

0 commit comments

Comments
 (0)