diff options
-rw-r--r-- | cmd/wipe/main.go | 31 | ||||
-rw-r--r-- | testdata/pg2_integralwipesides_t0.02_w5.png | bin | 33595 -> 33622 bytes | |||
-rw-r--r-- | testdata/pg2_integralwipesides_t0.05_w25.png | bin | 33432 -> 33622 bytes | |||
-rw-r--r-- | testdata/pg2_integralwipesides_t0.05_w5.png | bin | 21695 -> 21735 bytes | |||
-rw-r--r-- | wipesides.go | 61 | ||||
-rw-r--r-- | wipesides_test.go | 4 |
6 files changed, 54 insertions, 42 deletions
diff --git a/cmd/wipe/main.go b/cmd/wipe/main.go index 30b0061..c69836d 100644 --- a/cmd/wipe/main.go +++ b/cmd/wipe/main.go @@ -9,10 +9,6 @@ package main import ( "flag" "fmt" - "image" - "image/draw" - _ "image/jpeg" - "image/png" "log" "os" @@ -25,7 +21,7 @@ func main() { fmt.Fprintf(os.Stderr, "Wipes the sections of an image which are outside the content area.\n") flag.PrintDefaults() } - min := flag.Int("hm", 30, "Minimum percentage of the image width for the content width calculation to be considered valid.") + hmin := flag.Int("hm", 30, "Minimum percentage of the image width for the content width calculation to be considered valid.") thresh := flag.Float64("ht", 0.05, "Threshold for the proportion of black pixels below which a window is determined to be the edge. Higher means more aggressive wiping.") wsize := flag.Int("hw", 5, "Window size for mask finding algorithm.") vmin := flag.Int("vm", 30, "Minimum percentage of the image height for the content width calculation to be considered valid.") @@ -37,29 +33,8 @@ func main() { os.Exit(1) } - f, err := os.Open(flag.Arg(0)) - defer f.Close() + err := preproc.WipeFile(flag.Arg(0), flag.Arg(1), *wsize, *thresh, *hmin, *vwsize, *vthresh, *vmin) if err != nil { - log.Fatalf("Could not open file %s: %v\n", flag.Arg(0), err) - } - img, _, err := image.Decode(f) - if err != nil { - log.Fatalf("Could not decode image: %v\n", err) - } - b := img.Bounds() - gray := image.NewGray(image.Rect(0, 0, b.Dx(), b.Dy())) - draw.Draw(gray, b, img, b.Min, draw.Src) - - sidesdone := preproc.Wipe(gray, *wsize, *thresh, *min) - clean := preproc.VWipe(sidesdone, *vwsize, *vthresh, *vmin) - - f, err = os.Create(flag.Arg(1)) - if err != nil { - log.Fatalf("Could not create file %s: %v\n", flag.Arg(1), err) - } - defer f.Close() - err = png.Encode(f, clean) - if err != nil { - log.Fatalf("Could not encode image: %v\n", err) + log.Fatalf("Failed to wipe image: %v\n", err) } } diff --git a/testdata/pg2_integralwipesides_t0.02_w5.png b/testdata/pg2_integralwipesides_t0.02_w5.png Binary files differindex 6b4ccb2..4e8850c 100644 --- a/testdata/pg2_integralwipesides_t0.02_w5.png +++ b/testdata/pg2_integralwipesides_t0.02_w5.png diff --git a/testdata/pg2_integralwipesides_t0.05_w25.png b/testdata/pg2_integralwipesides_t0.05_w25.png Binary files differindex 39dc88d..4e8850c 100644 --- a/testdata/pg2_integralwipesides_t0.05_w25.png +++ b/testdata/pg2_integralwipesides_t0.05_w25.png diff --git a/testdata/pg2_integralwipesides_t0.05_w5.png b/testdata/pg2_integralwipesides_t0.05_w5.png Binary files differindex 3a0452f..da09eba 100644 --- a/testdata/pg2_integralwipesides_t0.05_w5.png +++ b/testdata/pg2_integralwipesides_t0.05_w5.png diff --git a/wipesides.go b/wipesides.go index e4b9ad5..4af3204 100644 --- a/wipesides.go +++ b/wipesides.go @@ -4,8 +4,8 @@ package preproc -// TODO: add minimum size variable (default ~30%?) // TODO: switch to an interface rather than integralimg.I +// TODO: optionally return the edges chosen import ( "errors" @@ -28,24 +28,32 @@ func proportion(i integralimg.I, x int, size int) float64 { // findbestedge goes through every vertical line from x to x+w to // find the one with the lowest proportion of black pixels. +// if there are multiple lines with the same proportion (e.g. zero), +// choose the middle one. func findbestedge(img integralimg.I, x int, w int) int { - var bestx int var best float64 + var bestxs []int if w == 1 { return x } + best = 100 + right := x + w for ; x < right; x++ { prop := proportion(img, x, 1) - if prop > best { + if prop < best { + bestxs = make([]int, 0) best = prop - bestx = x + } + if prop == best { + bestxs = append(bestxs, x) } } + middlex := bestxs[len(bestxs)/2] - return bestx + return middlex } // findedges finds the edges of the main content, by moving a window of wsize @@ -76,6 +84,31 @@ func findedges(img integralimg.I, wsize int, thresh float64) (int, int) { return lowedge, highedge } +// findedgesOutin finds the edges of the main content as findedges does, +// but working from the outside of the image inwards, rather than from the +// middle outwards. +// TODO: test what difference this makes +func findedgesOutin(img integralimg.I, wsize int, thresh float64) (int, int) { + maxx := len(img[0]) - 1 + var lowedge, highedge int = 0, maxx + + for x := maxx-wsize; x > 0; x-- { + if proportion(img, x, wsize) > thresh { + highedge = findbestedge(img, x, wsize) + break + } + } + + for x := 0; x < maxx-wsize; x++ { + if proportion(img, x, wsize) > thresh { + lowedge = findbestedge(img, x, wsize) + break + } + } + + return lowedge, highedge +} + // wipesides fills the sections of image not within the boundaries // of lowedge and highedge with white func wipesides(img *image.Gray, lowedge int, highedge int) *image.Gray { @@ -145,7 +178,8 @@ func Wipe(img *image.Gray, wsize int, thresh float64, min int) *image.Gray { func VWipe(img *image.Gray, wsize int, thresh float64, min int) *image.Gray { rotimg := sideways(img) integral := integralimg.ToIntegralImg(rotimg) - lowedge, highedge := findedges(integral, wsize, thresh) + // TODO: test whether there are any places where Outin makes a real difference + lowedge, highedge:= findedgesOutin(integral, wsize, thresh) if toonarrow(img, lowedge, highedge, min) { return img } @@ -158,10 +192,13 @@ func VWipe(img *image.Gray, wsize int, thresh float64, min int) *image.Gray { // content area is above min %. // inPath: path of the input image. // outPath: path to save the output image. -// wsize: window size for wipe algorithm. -// thresh: threshold for wipe algorithm. -// min: minimum % of content area width to consider valid. -func WipeFile(inPath string, outPath string, wsize int, thresh float64, min int) error { +// hwsize: window size for horizontal wipe algorithm. +// hthresh: threshold for horizontal wipe algorithm. +// hmin: minimum % of content area width to consider valid. +// vwsize: window size for vertical wipe algorithm. +// vthresh: threshold for vertical wipe algorithm. +// vmin: minimum % of content area height to consider valid. +func WipeFile(inPath string, outPath string, hwsize int, hthresh float64, hmin int, vwsize int, vthresh float64, vmin int) error { f, err := os.Open(inPath) defer f.Close() if err != nil { @@ -175,8 +212,8 @@ func WipeFile(inPath string, outPath string, wsize int, thresh float64, min int) gray := image.NewGray(image.Rect(0, 0, b.Dx(), b.Dy())) draw.Draw(gray, b, img, b.Min, draw.Src) - hclean := Wipe(gray, wsize, thresh, min) - clean := VWipe(hclean, wsize, thresh, min) + hclean := Wipe(gray, hwsize, hthresh, hmin) + clean := VWipe(hclean, vwsize, vthresh, vmin) f, err = os.Create(outPath) if err != nil { diff --git a/wipesides_test.go b/wipesides_test.go index 7ce3472..d6a9af3 100644 --- a/wipesides_test.go +++ b/wipesides_test.go @@ -103,8 +103,8 @@ func TestWipeSides(t *testing.T) { thresh float64 wsize int }{ - {"testdata/1727_GREENE_0048.png", 172, 237, 2204, 2244, 0.005, 120}, - {"testdata/1687_SCHWEITZER_0030.png", 142, 231, 2595, 2656, 0.005, 90}, + {"testdata/1727_GREENE_0048.png", 70, 237, 2204, 2450, 0.005, 120}, + {"testdata/1687_SCHWEITZER_0030.png", 70, 231, 2595, 2770, 0.005, 90}, } for _, c := range topbottomedgecases { |