Beispiel #1
0
// Flip mirrors an image in x and y.
func Flip(f *rimg64.Image) *rimg64.Image {
	g := rimg64.New(f.Width, f.Height)
	for i := 0; i < f.Width; i++ {
		for j := 0; j < f.Height; j++ {
			g.Set(f.Width-1-i, f.Height-1-j, f.At(i, j))
		}
	}
	return g
}
Beispiel #2
0
func square(f *rimg64.Image) *rimg64.Image {
	g := rimg64.New(f.Width, f.Height)
	for i := 0; i < f.Width; i++ {
		for j := 0; j < f.Height; j++ {
			g.Set(i, j, sqr(f.At(i, j)))
		}
	}
	return g
}
Beispiel #3
0
// CorrBankBLAS computes the correlation of an image with a bank of filters.
// 	h_p[u, v] = (f corr g_p)[u, v]
func CorrBankBLAS(f *rimg64.Image, g *Bank) (*rimg64.Multi, error) {
	out := ValidSize(f.Size(), g.Size())
	if out.X <= 0 || out.Y <= 0 {
		return nil, nil
	}
	// Express as dense matrix multiplication.
	//   h_p[u, v] = (f corr g_q)[u, v]
	//   Y(h) = A(f) X(g)
	// If the number of output channels is k, then
	//   A is (M-m+1)(N-n+1) x mn and
	//   X is mn x k, so that
	//   Y is (M-m+1)(N-n+1) x k.

	h := rimg64.NewMulti(out.X, out.Y, len(g.Filters))
	m, n, k := g.Width, g.Height, len(g.Filters)
	a := blas.NewMat(out.X*out.Y, m*n)
	{
		var r int
		for u := 0; u < h.Width; u++ {
			for v := 0; v < h.Height; v++ {
				var s int
				for i := 0; i < g.Width; i++ {
					for j := 0; j < g.Height; j++ {
						a.Set(r, s, f.At(i+u, j+v))
						s++
					}
				}
				r++
			}
		}
	}
	x := blas.NewMat(m*n, k)
	{
		var r int
		for i := 0; i < g.Width; i++ {
			for j := 0; j < g.Height; j++ {
				for p := 0; p < h.Channels; p++ {
					x.Set(r, p, g.Filters[p].At(i, j))
				}
				r++
			}
		}
	}
	y := blas.MatMul(1, a, x)
	{
		var r int
		for u := 0; u < h.Width; u++ {
			for v := 0; v < h.Height; v++ {
				for p := 0; p < h.Channels; p++ {
					h.Set(u, v, p, y.At(r, p))
				}
				r++
			}
		}
	}
	return h, nil
}
Beispiel #4
0
// CorrBankStrideBLAS computes the strided correlation of
// an image with a bank of filters.
// 	h_p[u, v] = (f corr g_p)[stride*u, stride*v]
func CorrBankStrideBLAS(f *rimg64.Image, g *Bank, stride int) (*rimg64.Multi, error) {
	out := ValidSizeStride(f.Size(), g.Size(), stride)
	if out.X <= 0 || out.Y <= 0 {
		return nil, nil
	}
	h := rimg64.NewMulti(out.X, out.Y, len(g.Filters))
	// Size of filters.
	m, n := g.Width, g.Height
	// Express as dense matrix multiplication.
	//   h_p[u, v] = sum_q (f_q corr g_pq)[u, v]
	//   h = A(f) X(g)
	// where A is whk by mnk
	// with w = ceil[(M-m+1)/stride],
	//      h = ceil[(N-n+1)/stride].
	a := blas.NewMat(h.Width*h.Height, m*n)
	{
		var r int
		for u := 0; u < h.Width; u++ {
			for v := 0; v < h.Height; v++ {
				var s int
				for i := 0; i < g.Width; i++ {
					for j := 0; j < g.Height; j++ {
						a.Set(r, s, f.At(stride*u+i, stride*v+j))
						s++
					}
				}
				r++
			}
		}
	}
	x := blas.NewMat(m*n, h.Channels)
	{
		var r int
		for i := 0; i < g.Width; i++ {
			for j := 0; j < g.Height; j++ {
				for p := 0; p < h.Channels; p++ {
					x.Set(r, p, g.Filters[p].At(i, j))
				}
				r++
			}
		}
	}
	y := blas.MatMul(1, a, x)
	{
		var r int
		for u := 0; u < h.Width; u++ {
			for v := 0; v < h.Height; v++ {
				for p := 0; p < h.Channels; p++ {
					h.Set(u, v, p, y.At(r, p))
				}
				r++
			}
		}
	}
	return h, nil
}
Beispiel #5
0
// Decimate takes every r-th sample starting at (0, 0).
func Decimate(f *rimg64.Image, r int) *rimg64.Image {
	out := ceilDivPt(f.Size(), r)
	g := rimg64.New(out.X, out.Y)
	for i := 0; i < g.Width; i++ {
		for j := 0; j < g.Height; j++ {
			g.Set(i, j, f.At(r*i, r*j))
		}
	}
	return g
}
Beispiel #6
0
func copyImageTo(x *fftw.Array2, f *rimg64.Image) {
	w, h := x.Dims()
	for u := 0; u < w; u++ {
		for v := 0; v < h; v++ {
			if u < f.Width && v < f.Height {
				x.Set(u, v, complex(f.At(u, v), 0))
			} else {
				x.Set(u, v, 0)
			}
		}
	}
}
Beispiel #7
0
// CorrStrideBLAS computes the strided correlation of an image with a filter.
// 	h[u, v] = (f corr g)[stride*u, stride*v]
func CorrStrideBLAS(f, g *rimg64.Image, stride int) (*rimg64.Image, error) {
	out := ValidSizeStride(f.Size(), g.Size(), stride)
	if out.X <= 0 || out.Y <= 0 {
		return nil, nil
	}
	h := rimg64.New(out.X, out.Y)
	// Size of filters.
	m, n := g.Width, g.Height
	// Express as dense matrix multiplication.
	//   h[u, v] = (f corr g)[stride*u, stride*v]
	//   y(h) = A(f) x(g)
	// where A is wh by mn
	// with w = ceil[(M-m+1)/stride],
	//      h = ceil[(N-n+1)/stride].
	a := blas.NewMat(h.Width*h.Height, m*n)
	{
		var r int
		for u := 0; u < h.Width; u++ {
			for v := 0; v < h.Height; v++ {
				var s int
				for i := 0; i < g.Width; i++ {
					for j := 0; j < g.Height; j++ {
						a.Set(r, s, f.At(stride*u+i, stride*v+j))
						s++
					}
				}
				r++
			}
		}
	}
	x := blas.NewMat(m*n, 1)
	{
		var r int
		for i := 0; i < g.Width; i++ {
			for j := 0; j < g.Height; j++ {
				x.Set(r, 0, g.At(i, j))
				r++
			}
		}
	}
	y := blas.MatMul(1, a, x)
	{
		var r int
		for u := 0; u < h.Width; u++ {
			for v := 0; v < h.Height; v++ {
				h.Set(u, v, y.At(r, 0))
				r++
			}
		}
	}
	return h, nil
}
Beispiel #8
0
func invNorm(f *rimg64.Image) float64 {
	var norm float64
	for i := 0; i < f.Width; i++ {
		for j := 0; j < f.Height; j++ {
			norm += sqr(f.At(i, j))
		}
	}
	norm = math.Sqrt(norm) // This will never be negative.
	if norm == 0 {
		return 0
	}
	return 1 / norm
}
Beispiel #9
0
func errIfNotEqImage(f, g *rimg64.Image, eps float64) error {
	if !f.Size().Eq(g.Size()) {
		return fmt.Errorf("different size: %v, %v", f.Size(), g.Size())
	}
	for i := 0; i < f.Width; i++ {
		for j := 0; j < f.Height; j++ {
			a, b := f.At(i, j), g.At(i, j)
			if math.Abs(a-b) > eps*math.Max(math.Abs(a), math.Abs(b)) {
				return fmt.Errorf("different at x %d, y %d: %g, %g", i, j, a, b)
			}
		}
	}
	return nil
}
Beispiel #10
0
// dst[i, j] = src[i*stride + offset.X, j*stride + offset.Y],
// or zero if this is outside the boundary.
func copyStrideTo(dst *fftw.Array2, src *rimg64.Image, stride int, offset image.Point) {
	m, n := dst.Dims()
	bnds := image.Rect(0, 0, src.Width, src.Height)
	for i := 0; i < m; i++ {
		for j := 0; j < n; j++ {
			p := image.Pt(i, j).Mul(stride).Add(offset)
			var val complex128
			if p.In(bnds) {
				val = complex(src.At(p.X, p.Y), 0)
			}
			dst.Set(i, j, val)
		}
	}
}
Beispiel #11
0
// Tests whether (u, v) is a local maximum.
// Pixels at the edge can be maxima.
func notLocalMax(r *rimg64.Image, u, v int) bool {
	uv := r.At(u, v)
	if u > 0 && r.At(u-1, v) > uv {
		return true
	}
	if u < r.Width-1 && r.At(u+1, v) > uv {
		return true
	}
	if v > 0 && r.At(u, v-1) > uv {
		return true
	}
	if v < r.Height-1 && r.At(u, v+1) > uv {
		return true
	}
	return false
}
Beispiel #12
0
// CorrStrideNaive computes the strided correlation of an image with a filter.
// 	h[u, v] = (f corr g)[stride*u, stride*v]
func CorrStrideNaive(f, g *rimg64.Image, stride int) (*rimg64.Image, error) {
	out := ValidSizeStride(f.Size(), g.Size(), stride)
	h := rimg64.New(out.X, out.Y)
	for i := 0; i < h.Width; i++ {
		for j := 0; j < h.Height; j++ {
			var total float64
			for u := 0; u < g.Width; u++ {
				for v := 0; v < g.Height; v++ {
					p := image.Pt(i, j).Mul(stride).Add(image.Pt(u, v))
					total += f.At(p.X, p.Y) * g.At(u, v)
				}
			}
			h.Set(i, j, total)
		}
	}
	return h, nil
}
Beispiel #13
0
// CorrNaive computes the correlation of an image with a filter.
// 	h[u, v] = (f corr g)[u, v]
func CorrNaive(f, g *rimg64.Image) (*rimg64.Image, error) {
	out := ValidSize(f.Size(), g.Size())
	if out.X <= 0 || out.Y <= 0 {
		return nil, nil
	}
	h := rimg64.New(out.X, out.Y)
	for i := 0; i < out.X; i++ {
		for j := 0; j < out.Y; j++ {
			var total float64
			for u := 0; u < g.Width; u++ {
				for v := 0; v < g.Height; v++ {
					total += f.At(i+u, j+v) * g.At(u, v)
				}
			}
			h.Set(i, j, total)
		}
	}
	return h, nil
}
Beispiel #14
0
// CorrBankNaive computes the correlation of an image with a bank of filters.
// 	h_p[u, v] = (f corr g_p)[u, v]
func CorrBankNaive(f *rimg64.Image, g *Bank) (*rimg64.Multi, error) {
	out := ValidSize(f.Size(), g.Size())
	if out.X <= 0 || out.Y <= 0 {
		return nil, nil
	}
	h := rimg64.NewMulti(out.X, out.Y, len(g.Filters))
	for u := 0; u < h.Width; u++ {
		for v := 0; v < h.Height; v++ {
			for p := 0; p < h.Channels; p++ {
				var total float64
				for i := 0; i < g.Width; i++ {
					for j := 0; j < g.Height; j++ {
						total += f.At(i+u, j+v) * g.Filters[p].At(i, j)
					}
				}
				h.Set(u, v, p, total)
			}
		}
	}
	return h, nil
}
Beispiel #15
0
// CorrBankStrideNaive computes the strided correlation of
// an image with a bank of filters.
// 	h_p[u, v] = (f corr g_p)[stride*u, stride*v]
func CorrBankStrideNaive(f *rimg64.Image, g *Bank, stride int) (*rimg64.Multi, error) {
	out := ValidSizeStride(f.Size(), g.Size(), stride)
	if out.X <= 0 || out.Y <= 0 {
		return nil, nil
	}
	h := rimg64.NewMulti(out.X, out.Y, len(g.Filters))
	for u := 0; u < h.Width; u++ {
		for v := 0; v < h.Height; v++ {
			for p := 0; p < h.Channels; p++ {
				var sum float64
				for i := 0; i < g.Width; i++ {
					for j := 0; j < g.Height; j++ {
						sum += f.At(stride*u+i, stride*v+j) * g.Filters[p].At(i, j)
					}
				}
				h.Set(u, v, p, sum)
			}
		}
	}
	return h, nil
}
Beispiel #16
0
func adjSum(f *rimg64.Image, x1, y1, x2, y2 int) float64 {
	return f.At(x1, y1) + f.At(x1, y2) + f.At(x2, y1) + f.At(x2, y2)
}
Beispiel #17
0
// Avoids f.Set(x, y, f.Get(x, y, ...)).
func addTo(f *rimg64.Image, x, y int, v float64) {
	f.Set(x, y, f.At(x, y)+v)
}