Permalink
Browse files

algorithm works poorly, adding a new prototype

  • Loading branch information...
1 parent f4475b9 commit 008c35eb847bc44afe3c02b87bb575c4313dfe59 @twolfe18 committed Dec 26, 2011
Showing with 124 additions and 26 deletions.
  1. +39 −24 edge_detctors.go
  2. +25 −0 line.go
  3. +49 −0 shortlines.go
  4. +11 −2 util.go
View
@@ -68,7 +68,7 @@ func (ed EdgeDetector) AlignTo(img image.Image) {
fmt.Printf("]\n")
// test this on images to see how fast this should be decreased
- cur_ed.proposal_variance *= 0.9
+ //cur_ed.proposal_variance *= 0.9
// print out ED for debugging
outf := fmt.Sprintf("/Users/travis/Dropbox/code/sudoku/img/debug.%d.png", iter)
@@ -78,15 +78,15 @@ func (ed EdgeDetector) AlignTo(img image.Image) {
func NewEdgeDetector(b Float64Rectangle) EdgeDetector {
ed := new(EdgeDetector)
- ed.default_line_radius = 10.0
+ ed.default_line_radius = 1.0
ed.orientation_sensitivity = 3.0
- ed.num_proposals = 80
+ ed.num_proposals = 75
ed.greedyness = 2.5
- ed.proposal_variance = 1.0 // in degrees
+ ed.proposal_variance = 4.0 // in degrees
// place some lines
- padding := 2.0
- num_lines := SudokuGridDimension + 1
+ padding := 60.0 //2.0
+ num_lines := 4 //SudokuGridDimension + 1
dx := (b.Dx() - 2.0*padding) / float64(num_lines - 1)
dy := (b.Dx() - 2.0*padding) / float64(num_lines - 1)
x0 := b.Min.X + padding; xmax := b.Max.X - padding; x := x0
@@ -103,7 +103,7 @@ func NewEdgeDetector(b Float64Rectangle) EdgeDetector {
//fmt.Printf("[ned] ed.lines = %s\n", ed.lines)
// random perturbation of "perfect"
- crappyness := 2.0
+ crappyness := 6.0
ed.proposal_variance *= crappyness
n := ed.Proposal(b)
n.proposal_variance /= crappyness
@@ -148,6 +148,8 @@ func (ed EdgeDetector) Proposal(bounds Float64Rectangle) EdgeDetector {
nl.right = PointPlus(Midpoint(l.left, l.right), z)
// now apply left-right and up-down shifts
+ // TODO the indepented scale for dx dy shifts should be higher to allow for when
+ // the original distance between lines is too great or small
dx := mean_dx + independent_scale * (rand.Float64() * 2.0 - 1.0) * ed.proposal_variance // left-right movement
dy := mean_dy + independent_scale * (rand.Float64() * 2.0 - 1.0) * ed.proposal_variance // up-down movement
nl.left.X += dx
@@ -156,18 +158,26 @@ func (ed EdgeDetector) Proposal(bounds Float64Rectangle) EdgeDetector {
nl.right.Y += dy
// now make sure it's in the bounds
- nl.left.X = math.Fmax(bounds.Min.X, nl.left.X)
- nl.left.X = math.Fmin(bounds.Max.X, nl.left.X)
- nl.left.Y = math.Fmax(bounds.Min.Y, nl.left.Y)
- nl.left.Y = math.Fmin(bounds.Max.Y, nl.left.Y)
-
- nl.right.X = math.Fmax(bounds.Min.X, nl.right.X)
- nl.right.X = math.Fmin(bounds.Max.X, nl.right.X)
- nl.right.Y = math.Fmax(bounds.Min.Y, nl.right.Y)
- nl.right.Y = math.Fmin(bounds.Max.Y, nl.right.Y)
-
+ nl.ProjectInto(bounds)
new_ed.lines[i] = nl
}
+
+ // scalings (shrinks and stretches) in x and y directions
+ // TODO write variance struct that includes L/R, U/D shift amounts in (0,1)
+ stretch := (rand.Float64() * 2.0 - 1.0) * ed.proposal_variance
+ center := Float64Point{0.0, 0.0} // find center of all lines, stretch to/from this point
+ for _,l := range new_ed.lines {
+ center := PointPlus(center, Midpoint(l))
+ }
+ center.Scale(1.0 / len(new_ed.lines))
+ amount := 0.0 // TODO
+ for _,l := range new_ed.lines {
+ nmp := ShiftedMidpoint(l, center, amount)
+ half := PointMinus(l.right, Midpoint(l))
+ l.right = PointPlus(half, nmp)
+ l.left = PointMinus(nmp, half)
+ }
+
return new_ed
}
@@ -201,34 +211,39 @@ func (ed EdgeDetector) Potential(img image.Image) (p float64) {
// probably not...
// activation for each line and pixel
+ var delta, dist float64
add := 0.0
b := img.Bounds()
for x := b.Min.X; x < b.Max.X; x++ {
for y := b.Min.Y; y < b.Max.Y; y++ {
for _, line := range ed.lines {
// TODO may need to play with this formula
- d := DarknessAt(img, x, y) * line.SquaredDistance(float64(x), float64(y))
- //fmt.Printf("[poten] d = %.2f\tsq_d = %.2f\tdarkness = %.2f \t line.radius = %.2f\n", d, line.SquaredDistance(float64(x), float64(y)), DarknessAt(img, x, y), line.radius)
- p += math.Exp(-1.0 * d / line.radius)
- add += math.Exp(-1.0 * d / line.radius)
+ dist = line.SquaredDistance(float64(x), float64(y))
+ delta = DarknessAt(img, x, y) * math.Exp(-dist / line.radius)
+ p += delta; add += delta
if math.IsInf(add, 1) {
fmt.Printf("[Potential] hit inf!\n")
os.Exit(1)
}
}
}
}
+ p /= float64(len(ed.lines)); add /= float64(len(ed.lines))
// orientation of the lines
remove := 0.0
+ num_pairs := 0 // man up: N * (N-1) / 2
N := len(ed.lines)
for i := 1; i < N; i++ {
for j := 0; j < i; j++ {
- a := ed.lines[i].Angle(ed.lines[j])
- p -= math.Exp(-1.0 * math.Fmod(a, 90.0)) * ed.orientation_sensitivity
- remove += math.Exp(-1.0 * math.Fmod(a, 90.0)) * ed.orientation_sensitivity
+ num_pairs += 1
+ dist = ed.lines[i].Angle(ed.lines[j])
+ delta = math.Exp(-math.Fmod(dist, 90.0)) * ed.orientation_sensitivity
+ /*p -= delta;*/ remove += delta
}
}
+ remove /= float64(num_pairs)
+ p -= remove
fmt.Printf("[EdgeDetector.Potential] potential = %.2f\t(+%.2f, -%.2f)\n", p, add, remove)
return p
View
25 line.go
@@ -25,6 +25,31 @@ type Line struct {
/******************************************************************************************/
+func ShiftedMidpoint(l Line, towards Float64Point, amount float64) {
+ if amount <= 0.0 || amount >= 1.0 {
+ fmt.Printf("[ShiftLine] illegal amount: %.2f\n", amount)
+ os.Exit(1)
+ }
+ mp := MidPoint(l).Scale(amount)
+ towards.Scale(1.0 - amount)
+ return PointPlus(mp, towards)
+}
+
+func (l Line) ScaleLength(scale float64) {
+ m := Midpoint(l)
+ v := PointMinus(l.right, m)
+ v.Scale(scale)
+ l.right = PointPlus(m, v)
+ l.left = PointMinus(m, v)
+}
+
+func (l Line) ProjectInto(bounds Float64Rectangle) {
+ l.left.ProjectInto(bounds)
+ l.right.ProjectInto(bounds)
+}
+
+/******************************************************************************************/
+
func (l Line) String() string {
return fmt.Sprintf("[%s -> %s]", l.left.String(), l.right.String())
}
View
@@ -0,0 +1,49 @@
+
+package main
+
+import (
+ "fmt"
+)
+
+const ( // TODO find a unified way to write this with stuff in edge_detectors
+ LINE_EXPANSION = 1.3
+ PROPORTION_KEEP = 0.7
+ NUM_LINES = 20 // 9 cells in each dim, 10 lines in each dim X 2 dims
+ MAX_ITER = 10
+)
+
+func main() {
+
+ // read the image
+ img := nil
+
+ // initialize a whole bunch of lines randomly
+ bounds := NewFloat64Rectangle(img.Bounds())
+ lines := [NUM_LINES]Line
+ for i,_ := range lines {
+ lines[i] = RandomPointBetween(bounds.Min(), bounds.Max())
+ }
+
+ for iter := 0; iter < MAX_ITER; iter++ {
+
+ // optimize positions of lines
+
+ // take top 80% of the lines (by potential)
+
+ // for remaining 20% randomly place lines on the grid
+ // - maybe utilize infomation about location of top 80%
+ // - maybe give these lines one round of optimization so they can compete
+
+ // increase each line length
+ for _,l := range lines {
+ l.ScaleLength(LINE_EXPANSION)
+ l.ProjectInto(bounds)
+ }
+
+}
+
+func OptimizePotential(lines []Lines, img image.Image) {
+ // TODO maybe pass in a potential function
+ // TODO this should be merged with Proposal() and Potenital() code in edge_detectors
+}
+
View
13 util.go
@@ -10,6 +10,8 @@ import (
"math"
)
+// TODO refactor all intstances of Float64Point in the file to two Float64Points
+
type Float64Point struct {
X, Y float64
}
@@ -23,6 +25,13 @@ func (p *Float64Point) Scale(s float64) {
p.Y *= s
}
+func (p Float64Point) ProjectInto(bounds Float64Rectangle) {
+ p.X = math.Fmax(bounds.Min.X, p.X)
+ p.X = math.Fmin(bounds.Max.X, p.X)
+ p.Y = math.Fmax(bounds.Min.Y, p.Y)
+ p.Y = math.Fmin(bounds.Max.Y, p.Y)
+}
+
func (v Float64Point) Rotate(theta float64) Float64Point {
// http://en.wikipedia.org/wiki/Rotation_(mathematics)#Matrix_algebra
st := math.Sin(theta)
@@ -119,8 +128,8 @@ func DarknessAt(img image.Image, x, y int) float64 {
r, g, b, _ := img.At(x, y).RGBA()
lum := 0.21 * float64(r) + 0.71 * float64(g) + 0.07 * float64(b)
// TODO make this more flexible
- //return 255.0 - lum // 8 bit
- return 65535.0 - lum // 16 bit
+ //return (255.0 - lum) / 255.0 // 8 bit
+ return (65535.0 - lum) / 65535.0 // 16 bit
}
// converts an image to a mutable grayscale image

0 comments on commit 008c35e

Please sign in to comment.