forked from makiuchi-d/gozxing
-
Notifications
You must be signed in to change notification settings - Fork 0
/
perspective_transform.go
95 lines (86 loc) · 3.04 KB
/
perspective_transform.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package common
type PerspectiveTransform struct {
a11, a21, a31 float64
a12, a22, a32 float64
a13, a23, a33 float64
}
func PerspectiveTransform_QuadrilateralToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3,
x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p float64) *PerspectiveTransform {
qToS := PerspectiveTransform_QuadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3)
sToQ := PerspectiveTransform_SquareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p)
return sToQ.times(qToS)
}
func (p *PerspectiveTransform) TransformPoints(points []float64) {
maxI := len(points) - 1 // points.length must be even
for i := 0; i < maxI; i += 2 {
x := points[i]
y := points[i+1]
denominator := p.a13*x + p.a23*y + p.a33
points[i] = (p.a11*x + p.a21*y + p.a31) / denominator
points[i+1] = (p.a12*x + p.a22*y + p.a32) / denominator
}
}
func (p *PerspectiveTransform) TransformPointsXY(xValues, yValues []float64) {
n := len(xValues)
for i := 0; i < n; i++ {
x := xValues[i]
y := yValues[i]
denominator := p.a13*x + p.a23*y + p.a33
xValues[i] = (p.a11*x + p.a21*y + p.a31) / denominator
yValues[i] = (p.a12*x + p.a22*y + p.a32) / denominator
}
}
func PerspectiveTransform_SquareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3 float64) *PerspectiveTransform {
dx3 := x0 - x1 + x2 - x3
dy3 := y0 - y1 + y2 - y3
if dx3 == 0.0 && dy3 == 0.0 {
// Affine
return &PerspectiveTransform{
x1 - x0, x2 - x1, x0,
y1 - y0, y2 - y1, y0,
0.0, 0.0, 1.0}
} else {
dx1 := x1 - x2
dx2 := x3 - x2
dy1 := y1 - y2
dy2 := y3 - y2
denominator := dx1*dy2 - dx2*dy1
a13 := (dx3*dy2 - dx2*dy3) / denominator
a23 := (dx1*dy3 - dx3*dy1) / denominator
return &PerspectiveTransform{
x1 - x0 + a13*x1, x3 - x0 + a23*x3, x0,
y1 - y0 + a13*y1, y3 - y0 + a23*y3, y0,
a13, a23, 1.0}
}
}
func PerspectiveTransform_QuadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3 float64) *PerspectiveTransform {
// Here, the adjoint serves as the inverse:
return PerspectiveTransform_SquareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint()
}
func (p *PerspectiveTransform) buildAdjoint() *PerspectiveTransform {
// Adjoint is the transpose of the cofactor matrix:
return &PerspectiveTransform{
p.a22*p.a33 - p.a23*p.a32,
p.a23*p.a31 - p.a21*p.a33,
p.a21*p.a32 - p.a22*p.a31,
p.a13*p.a32 - p.a12*p.a33,
p.a11*p.a33 - p.a13*p.a31,
p.a12*p.a31 - p.a11*p.a32,
p.a12*p.a23 - p.a13*p.a22,
p.a13*p.a21 - p.a11*p.a23,
p.a11*p.a22 - p.a12*p.a21,
}
}
func (p *PerspectiveTransform) times(other *PerspectiveTransform) *PerspectiveTransform {
return &PerspectiveTransform{
p.a11*other.a11 + p.a21*other.a12 + p.a31*other.a13,
p.a11*other.a21 + p.a21*other.a22 + p.a31*other.a23,
p.a11*other.a31 + p.a21*other.a32 + p.a31*other.a33,
p.a12*other.a11 + p.a22*other.a12 + p.a32*other.a13,
p.a12*other.a21 + p.a22*other.a22 + p.a32*other.a23,
p.a12*other.a31 + p.a22*other.a32 + p.a32*other.a33,
p.a13*other.a11 + p.a23*other.a12 + p.a33*other.a13,
p.a13*other.a21 + p.a23*other.a22 + p.a33*other.a23,
p.a13*other.a31 + p.a23*other.a32 + p.a33*other.a33,
}
}