threshold.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // Copyright 2012 Harry de Boer. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ocr
  5. import (
  6. "image"
  7. )
  8. // Threshold performs thresholding on a grayscale image.
  9. //
  10. // All color values greater than threshold are set to fgColor, the other to bgColor.
  11. func Threshold(m *image.Gray, threshold, bgColor, fgColor uint8) {
  12. count := len(m.Pix)
  13. for i := 0; i < count; i++ {
  14. if m.Pix[i] > threshold {
  15. m.Pix[i] = fgColor
  16. } else {
  17. m.Pix[i] = bgColor
  18. }
  19. }
  20. }
  21. // Otsu determines a threshold value using Otsu's method on grayscale images.
  22. //
  23. // "A threshold selection method from gray-level histograms" (Otsu, 1979).
  24. func Otsu(m *image.Gray) uint8 {
  25. hist := Histogram(m)
  26. sum := 0
  27. for i, v := range hist {
  28. sum += i * v
  29. }
  30. wB, wF := 0, len(m.Pix)
  31. sumB, sumF := 0, sum
  32. maxVariance := 0.0
  33. threshold := uint8(0)
  34. for t := 0; t < 256; t++ {
  35. wB += hist[t]
  36. wF -= hist[t]
  37. if wB == 0 {
  38. continue
  39. }
  40. if wF == 0 {
  41. return threshold
  42. }
  43. sumB += t * hist[t]
  44. sumF = sum - sumB
  45. mB := float64(sumB) / float64(wB)
  46. mF := float64(sumF) / float64(wF)
  47. betweenVariance := float64(wB*wF) * (mB - mF) * (mB - mF)
  48. if betweenVariance > maxVariance {
  49. maxVariance = betweenVariance
  50. threshold = uint8(t)
  51. }
  52. }
  53. return threshold
  54. }
  55. // Histogram creates a histogram of a grayscale image.
  56. func Histogram(m *image.Gray) []int {
  57. hist := make([]int, 256)
  58. count := len(m.Pix)
  59. for i := 0; i < count; i++ {
  60. hist[m.Pix[i]]++
  61. }
  62. return hist
  63. }