kernel.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package convolution
  2. import (
  3. "fmt"
  4. "math"
  5. )
  6. // Matrix interface.
  7. // At returns the matrix value at position x, y.
  8. // Normalized returns a new matrix with normalized values.
  9. // MaxX returns the horizontal length.
  10. // MaxY returns the vertical length.
  11. type Matrix interface {
  12. At(x, y int) float64
  13. Normalized() Matrix
  14. MaxX() int
  15. MaxY() int
  16. Transposed() Matrix
  17. }
  18. // NewKernel returns a kernel of the provided length.
  19. func NewKernel(width, height int) *Kernel {
  20. return &Kernel{make([]float64, width*height), width, height}
  21. }
  22. // Kernel to be used as a convolution matrix.
  23. type Kernel struct {
  24. Matrix []float64
  25. Width int
  26. Height int
  27. }
  28. // Normalized returns a new Kernel with normalized values.
  29. func (k *Kernel) Normalized() Matrix {
  30. sum := k.Absum()
  31. w := k.Width
  32. h := k.Height
  33. nk := NewKernel(w, h)
  34. // avoid division by 0
  35. if sum == 0 {
  36. sum = 1
  37. }
  38. for i := 0; i < w*h; i++ {
  39. nk.Matrix[i] = k.Matrix[i] / sum
  40. }
  41. return nk
  42. }
  43. // MaxX returns the horizontal length.
  44. func (k *Kernel) MaxX() int {
  45. return k.Width
  46. }
  47. // MaxY returns the vertical length.
  48. func (k *Kernel) MaxY() int {
  49. return k.Height
  50. }
  51. // At returns the matrix value at position x, y.
  52. func (k *Kernel) At(x, y int) float64 {
  53. return k.Matrix[y*k.Width+x]
  54. }
  55. // Transposed returns a new Kernel that has the columns as rows and vice versa
  56. func (k *Kernel) Transposed() Matrix {
  57. w := k.Width
  58. h := k.Height
  59. nk := NewKernel(h, w)
  60. for x := 0; x < w; x++ {
  61. for y := 0; y < h; y++ {
  62. nk.Matrix[x*h+y] = k.Matrix[y*w+x]
  63. }
  64. }
  65. return nk
  66. }
  67. // String returns the string representation of the matrix.
  68. func (k *Kernel) String() string {
  69. result := ""
  70. stride := k.MaxX()
  71. height := k.MaxY()
  72. for y := 0; y < height; y++ {
  73. result += fmt.Sprintf("\n")
  74. for x := 0; x < stride; x++ {
  75. result += fmt.Sprintf("%-8.4f", k.At(x, y))
  76. }
  77. }
  78. return result
  79. }
  80. // Absum returns the absolute cumulative value of the kernel.
  81. func (k *Kernel) Absum() float64 {
  82. var sum float64
  83. for _, v := range k.Matrix {
  84. sum += math.Abs(v)
  85. }
  86. return sum
  87. }