func TestCosCorr(t *testing.T) { const eps = 1e-9 f := rimg64.FromRows([][]float64{ {1, 2, 3, 4, 5}, {2, 5, 4, 1, 3}, {5, 4, 3, 2, 1}, }) g := rimg64.FromRows([][]float64{ {3, 1, 5}, {2, 4, 1}, }) gnorm := math.Sqrt(sqr(3) + sqr(1) + sqr(5) + sqr(2) + sqr(4) + sqr(1)) cases := []struct { I, J int Want float64 }{ // <g, [1 2 3; 2 5 4]> {0, 0, (3*1 + 1*2 + 5*3 + 2*2 + 4*5 + 1*4) / math.Sqrt(sqr(1)+sqr(2)+sqr(3)+sqr(2)+sqr(5)+sqr(4)) / gnorm}, // <g, [2 3 4; 5 4 1]> {1, 0, (3*2 + 1*3 + 5*4 + 2*5 + 4*4 + 1*1) / math.Sqrt(sqr(2)+sqr(3)+sqr(4)+sqr(5)+sqr(4)+sqr(1)) / gnorm}, // <g, ([3 4 5; 4 1 3]> {2, 0, (3*3 + 1*4 + 5*5 + 2*4 + 4*1 + 1*3) / math.Sqrt(sqr(3)+sqr(4)+sqr(5)+sqr(4)+sqr(1)+sqr(3)) / gnorm}, // <g, ([2 5 4; 5 4 3]> {0, 1, (3*2 + 1*5 + 5*4 + 2*5 + 4*4 + 1*3) / math.Sqrt(sqr(2)+sqr(5)+sqr(4)+sqr(5)+sqr(4)+sqr(3)) / gnorm}, // <g, ([5 4 1; 4 3 2]> {1, 1, (3*5 + 1*4 + 5*1 + 2*4 + 4*3 + 1*2) / math.Sqrt(sqr(5)+sqr(4)+sqr(1)+sqr(4)+sqr(3)+sqr(2)) / gnorm}, // <g, ([4 1 3; 3 2 1]> {2, 1, (3*4 + 1*1 + 5*3 + 2*3 + 4*2 + 1*1) / math.Sqrt(sqr(4)+sqr(1)+sqr(3)+sqr(3)+sqr(2)+sqr(1)) / gnorm}, } h, err := slide.CosCorr(f, g, slide.Auto) if err != nil { t.Fatal(err) } if h.Width != 3 || h.Height != 2 { t.Fatalf("wrong size: want %dx%d, got %dx%d", 3, 2, h.Width, h.Height) } for _, c := range cases { if got := h.At(c.I, c.J); math.Abs(got-c.Want) > eps { t.Errorf( "not equal: (i, j) = (%d, %d): want %.5g, got %.5g", c.I, c.J, c.Want, got, ) } } }
func TestCorrStrideNaive(t *testing.T) { const eps = 1e-9 const X = 10 cases := []struct { F, G, H *rimg64.Image K int }{ { F: rimg64.FromRows([][]float64{ {1, 2, 3, 4, 5}, {2, 5, 4, 1, 3}, {5, 4, 3, 2, 1}, }), G: rimg64.FromRows([][]float64{ {1, -1}, }), K: 2, H: rimg64.FromRows([][]float64{ {1 - 2, 3 - 4}, {5 - 4, 3 - 2}, }), }, { F: rimg64.FromRows([][]float64{ {1, 2, 3, 4, 5}, {2, 5, 4, 1, 3}, {5, 4, 3, 2, 1}, }), G: rimg64.FromRows([][]float64{ {1}, {-1}, }), K: 2, H: rimg64.FromRows([][]float64{ {1 - 2, 3 - 4, 5 - 3}, }), }, { F: rimg64.FromRows([][]float64{ {1, 2, 3, 4, 5}, {2, 5, 4, 1, 3}, {5, 4, 3, 2, 1}, {2, 2, 2, 2, 2}, }), G: rimg64.FromRows([][]float64{ {1, 2, 3}, {-3, -2, -1}, }), K: 2, H: rimg64.FromRows([][]float64{ {(1*1 + 2*2 + 3*3) + ((-3)*2 + (-2)*5 + (-1)*4), (1*3 + 2*4 + 3*5) + ((-3)*4 + (-2)*1 + (-1)*3)}, {(1*5 + 2*4 + 3*3) + ((-3)*2 + (-2)*2 + (-1)*2), (1*3 + 2*2 + 3*1) + ((-3)*2 + (-2)*2 + (-1)*2)}, }), }, { F: rimg64.FromRows([][]float64{ {1, 2, 3, 4, 5}, {2, 5, 4, 1, 3}, {5, 4, 3, 2, 1}, {2, 2, 2, 2, 2}, }), G: rimg64.FromRows([][]float64{ {1, 2, 3}, {-3, -2, -1}, }), K: 3, H: rimg64.FromRows([][]float64{ {(1*1 + 2*2 + 3*3) + ((-3)*2 + (-2)*5 + (-1)*4)}, }), }, { F: rimg64.FromRows([][]float64{ {1, 2, 3, 4, 5}, {2, 5, 4, 1, 3}, {5, 4, 3, 2, 1}, {2, 2, 2, 2, 2}, }), G: rimg64.FromRows([][]float64{ {1, 2}, {-3, -2}, }), K: 3, H: rimg64.FromRows([][]float64{ {(1*1 + 2*2) + ((-3)*2 + (-2)*5), (1*4 + 2*5) + ((-3)*1 + (-2)*3)}, }), }, { F: rimg64.FromRows([][]float64{ {1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 1}, }), G: rimg64.FromRows([][]float64{ {1, 2}, {3, 4}, }), K: 2, H: rimg64.FromRows([][]float64{ {1, 0, 3, 0}, {0, 0, 0, 0}, {0, 1, 0, 4}, }), }, { F: rimg64.FromRows([][]float64{ {1, 0, X, 0, 1, X, 0, 0}, {0, 0, X, 0, 0, X, 1, 0}, {X, X, X, X, X, X, X, X}, {0, 0, X, 1, 0, X, 0, 1}, {0, 1, X, 0, 1, X, 0, 1}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, }), G: rimg64.FromRows([][]float64{ {1, 2}, {3, 4}, }), K: 3, H: rimg64.FromRows([][]float64{ {1, 2, 3}, {4, 5, 6}, }), }, { F: rimg64.FromRows([][]float64{ {0, 0, X, X, 0, 1, X, X}, {0, 1, X, X, 0, 0, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {0, 0, X, X, 1, 0, X, X}, {1, 0, X, X, 0, 1, X, X}, {X, X, X, X, X, X, X, X}, }), G: rimg64.FromRows([][]float64{ {1, 2}, {3, 4}, }), K: 4, H: rimg64.FromRows([][]float64{ {4, 2}, {3, 5}, }), }, { F: rimg64.FromRows([][]float64{ {0, 1, X, X, X, 0, 0, X}, {0, 0, X, X, X, 0, 1, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {0, 1, X, X, X, 1, 0, X}, {0, 1, X, X, X, 0, 0, X}, }), G: rimg64.FromRows([][]float64{ {1, 2}, {3, 4}, }), K: 5, H: rimg64.FromRows([][]float64{ {2, 4}, {6, 1}, }), }, { F: rimg64.FromRows([][]float64{ {1, 1, X, X, X, X, 0, 0}, {0, 0, X, X, X, X, 1, 1}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, }), G: rimg64.FromRows([][]float64{ {1, 2}, {3, 4}, }), K: 6, H: rimg64.FromRows([][]float64{ {3, 7}, }), }, { F: rimg64.FromRows([][]float64{ {1, 1, X, X, X, X, X, X}, {1, 1, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, }), G: rimg64.FromRows([][]float64{ {1, 2}, {3, 4}, }), K: 7, H: rimg64.FromRows([][]float64{ {10}, }), }, { F: rimg64.FromRows([][]float64{ {1, 1, X, X, X, X, X, X}, {0, 1, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, {X, X, X, X, X, X, X, X}, }), G: rimg64.FromRows([][]float64{ {1, 2}, {3, 4}, }), K: 10000, H: rimg64.FromRows([][]float64{ {7}, }), }, { F: rimg64.FromRows([][]float64{ {1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, }), G: rimg64.FromRows([][]float64{ {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, }), K: 2, H: rimg64.FromRows([][]float64{ {1, 6, 4}, {9, 7, 0}, {3, 1, 5}, }), }, } for _, q := range cases { h, err := slide.CorrStrideNaive(q.F, q.G, q.K) if err != nil { t.Errorf("im %v, tmpl %v, stride %d: %v", q.F.Size(), q.G.Size(), q.K, err) continue } if err := errIfNotEqImage(q.H, h, eps); err != nil { t.Errorf("im %v, tmpl %v, stride %d: %v", q.F.Size(), q.G.Size(), q.K, err) continue } } }