summaryrefslogtreecommitdiff
path: root/binarize
diff options
context:
space:
mode:
authorNick White <git@njw.name>2019-03-26 17:23:33 +0000
committerNick White <git@njw.name>2019-03-26 17:23:33 +0000
commit8af4c7e56e0336f1e70a0e079c79ee7459d92519 (patch)
tree4547e6c029a7063c3fddd6349bc4bbb80364fab3 /binarize
parentf20982f465ee4735caf5b0ebc3c57af31ee90e75 (diff)
Add zeroinv option for binarize command
Diffstat (limited to 'binarize')
-rw-r--r--binarize/cmd/binarize/main.go13
-rw-r--r--binarize/sauvola.go2
-rw-r--r--binarize/util.go20
3 files changed, 32 insertions, 3 deletions
diff --git a/binarize/cmd/binarize/main.go b/binarize/cmd/binarize/main.go
index c4b9562..bda3d93 100644
--- a/binarize/cmd/binarize/main.go
+++ b/binarize/cmd/binarize/main.go
@@ -20,11 +20,12 @@ func autowsize(bounds image.Rectangle) int {
func main() {
flag.Usage = func() {
- fmt.Fprintf(os.Stderr, "Usage: sauvola [-w num] [-k num] inimg outimg\n")
+ fmt.Fprintf(os.Stderr, "Usage: binarize [-k num] [-t type] [-w num] inimg outimg\n")
flag.PrintDefaults()
}
wsize := flag.Int("w", 0, "Window size for sauvola algorithm. Set automatically based on resolution if not set.")
ksize := flag.Float64("k", 0.5, "K for sauvola algorithm. This controls the overall threshold level. Set it lower for very light text (try 0.1 or 0.2).")
+ btype := flag.String("t", "binary", "Type of threshold. binary or zeroinv are currently implemented.")
flag.Parse()
if flag.NArg() < 2 {
flag.Usage()
@@ -55,7 +56,15 @@ func main() {
// TODO: come up with a way to set a good ksize automatically
- thresh := binarize.IntegralSauvola(gray, *ksize, *wsize)
+ var thresh image.Image
+ thresh = binarize.IntegralSauvola(gray, *ksize, *wsize)
+
+ if *btype == "zeroinv" {
+ thresh, err = binarize.BinToZeroInv(thresh.(*image.Gray), img.(*image.RGBA))
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
f, err = os.Create(flag.Arg(1))
if err != nil {
diff --git a/binarize/sauvola.go b/binarize/sauvola.go
index ca0acf0..ee773ba 100644
--- a/binarize/sauvola.go
+++ b/binarize/sauvola.go
@@ -28,7 +28,7 @@ func Sauvola(img *image.Gray, ksize float64, windowsize int) *image.Gray {
}
// Implements Sauvola's algorithm using Integral Images, see paper
-// "Effcient Implementation of Local Adaptive Thresholding Techniques Using Integral Images"
+// "Efficient Implementation of Local Adaptive Thresholding Techniques Using Integral Images"
// and
// https://stackoverflow.com/questions/13110733/computing-image-integral
func IntegralSauvola(img *image.Gray, ksize float64, windowsize int) *image.Gray {
diff --git a/binarize/util.go b/binarize/util.go
index e7fcfe4..ad641c9 100644
--- a/binarize/util.go
+++ b/binarize/util.go
@@ -1,6 +1,7 @@
package binarize
import (
+ "errors"
"image"
"math"
)
@@ -65,3 +66,22 @@ func surrounding(img *image.Gray, x int, y int, size int) []int {
}
return s
}
+
+func BinToZeroInv(bin *image.Gray, orig *image.RGBA) (*image.RGBA, error) {
+ b := bin.Bounds()
+ if ! b.Eq(orig.Bounds()) {
+ return orig, errors.New("bin and orig images need to be the same dimensions")
+ }
+ newimg := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ if bin.GrayAt(x, y).Y == 255 {
+ newimg.Set(x, y, bin.GrayAt(x, y))
+ } else {
+ newimg.Set(x, y, orig.At(x, y))
+ }
+ }
+ }
+
+ return newimg, nil
+}