From fe0fdfeea6fb34ee766b5c6131c884e285968d2d Mon Sep 17 00:00:00 2001 From: Ashwani Rathee Date: Fri, 2 Jul 2021 21:14:37 +0530 Subject: [PATCH 1/5] Image Binarization --- .../imagebinarization/image_binarization.jl | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 docs/examples/imagebinarization/image_binarization.jl diff --git a/docs/examples/imagebinarization/image_binarization.jl b/docs/examples/imagebinarization/image_binarization.jl new file mode 100644 index 00000000..29101439 --- /dev/null +++ b/docs/examples/imagebinarization/image_binarization.jl @@ -0,0 +1,71 @@ +# --- +# cover: assets/binarize.gif +# title: Image Binarization +# author: Ashwani Rathee +# date: 2021-7-2 +# --- + +# ImageBinarization.jl provides number of algorithms for binarizing images +# into background and foreground(bi-level image). In this demonstration , +# we'll be exploring where these algorithms could be useful and learn how +# different algorithms are suited for different types of tasks. + +# Suppose a person wants to make a automatic Sudoku solver using Computer +# Vision . Before anything else that person needs to import the image, +# preprocess it to optimize it for cell content extraction which can then +# be used for solving the sudoku. + +# Let's first import our sudoku + +using Images, ImageBinarization, TestImages, MosaicViews + +function get_image(url) + img = mktemp() do fn, f + download(url, fn) + load(fn) + end + img_resized = imresize(img, ratio = 1 / 2) +end + +img = get_image("https://i.imgur.com/DDLL6tp.png"); +img_gray = Gray.(img); + +# Now let's binarize a image using Otsu algorithm + +alg = Otsu() +img_otsu = binarize(img, alg) +[img img_gray img_otsu] + +# Now the differences between the binarized and non-binarized images +# become apparent. Let's now implement a function to see how different algorithms +# perform for this particular problem. + +algs = [ + "AdaptiveThreshold", + "Balanced", + "Entropy", + "Intermodes", + "MinimumError", + "Moments", + "Niblack", + "Otsu", + "Polysegment", + "Sauvola", + "UnimodalRosin", + "Yen", +] +function binarize_methods(img, algs) + imgs_binarized = Array[] + for i in algs + alg = getfield(ImageBinarization, Symbol(i))() + img = binarize(img, alg) + push!(imgs_binarized, img) + end + return imgs_binarized +end + +output = binarize_methods(img, algs) +mosaicview(output, nrow = 3, npad = 1) + + + From 3b25c65a6f6d4a81b199818b19cf731f51f1fbce Mon Sep 17 00:00:00 2001 From: Ashwani Rathee Date: Sun, 4 Jul 2021 20:57:05 +0530 Subject: [PATCH 2/5] removal of download,addition of content --- .../image_binarization.jl | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) rename docs/examples/{imagebinarization => image_binarization}/image_binarization.jl (63%) diff --git a/docs/examples/imagebinarization/image_binarization.jl b/docs/examples/image_binarization/image_binarization.jl similarity index 63% rename from docs/examples/imagebinarization/image_binarization.jl rename to docs/examples/image_binarization/image_binarization.jl index 29101439..7a1dea67 100644 --- a/docs/examples/imagebinarization/image_binarization.jl +++ b/docs/examples/image_binarization/image_binarization.jl @@ -1,5 +1,4 @@ # --- -# cover: assets/binarize.gif # title: Image Binarization # author: Ashwani Rathee # date: 2021-7-2 @@ -17,24 +16,30 @@ # Let's first import our sudoku -using Images, ImageBinarization, TestImages, MosaicViews +using ImageBinarization, TestImages, MosaicViews, Colors +using ImageTransformations, CoordinateTransformations, Rotations, ImageMorphology -function get_image(url) - img = mktemp() do fn, f - download(url, fn) - load(fn) - end - img_resized = imresize(img, ratio = 1 / 2) -end +# Original Image + +img = testimage("sudoku") + +# Grayscale version as binarize! only accepts Grayscale images + +img = Gray.(img) + +# Let's first rotate our image +trfm = recenter(RotMatrix(pi/30), center(img)); +imgw = warp(img, trfm) + +# Now lets zoom in a bit -img = get_image("https://i.imgur.com/DDLL6tp.png"); -img_gray = Gray.(img); +imgw = parent(imgw)[65:490,65:490] -# Now let's binarize a image using Otsu algorithm +# Now let's binarize a image using Sauvola algorithm -alg = Otsu() -img_otsu = binarize(img, alg) -[img img_gray img_otsu] +alg = Sauvola(); +img_otsu = binarize(imgw, alg) +[imgw img_otsu] # Now the differences between the binarized and non-binarized images # become apparent. Let's now implement a function to see how different algorithms @@ -54,17 +59,17 @@ algs = [ "UnimodalRosin", "Yen", ] -function binarize_methods(img, algs) +function binarize_methods(img_input, algs) imgs_binarized = Array[] for i in algs alg = getfield(ImageBinarization, Symbol(i))() - img = binarize(img, alg) - push!(imgs_binarized, img) + img_input1 = binarize(img_input, alg) + push!(imgs_binarized, img_input1) end return imgs_binarized end -output = binarize_methods(img, algs) +output = binarize_methods(imgw, algs) mosaicview(output, nrow = 3, npad = 1) From 369915bb3f818dacf44cb9555861dabd52a3a5e6 Mon Sep 17 00:00:00 2001 From: Ashwani Rathee Date: Thu, 8 Jul 2021 14:45:57 +0530 Subject: [PATCH 3/5] addition of extra example --- .../image_binarization/image_binarization.jl | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/docs/examples/image_binarization/image_binarization.jl b/docs/examples/image_binarization/image_binarization.jl index 7a1dea67..98f1f672 100644 --- a/docs/examples/image_binarization/image_binarization.jl +++ b/docs/examples/image_binarization/image_binarization.jl @@ -16,7 +16,7 @@ # Let's first import our sudoku -using ImageBinarization, TestImages, MosaicViews, Colors +using ImageBinarization, TestImages, MosaicViews, Colors, FileIO, ImageShow using ImageTransformations, CoordinateTransformations, Rotations, ImageMorphology # Original Image @@ -28,18 +28,19 @@ img = testimage("sudoku") img = Gray.(img) # Let's first rotate our image -trfm = recenter(RotMatrix(pi/30), center(img)); + +trfm = recenter(RotMatrix(pi / 30), center(img)); imgw = warp(img, trfm) # Now lets zoom in a bit -imgw = parent(imgw)[65:490,65:490] +imgw = parent(imgw)[65:490, 65:490] # Now let's binarize a image using Sauvola algorithm alg = Sauvola(); img_otsu = binarize(imgw, alg) -[imgw img_otsu] +mosaicview(imgw, img_otsu; ncol = 2) # Now the differences between the binarized and non-binarized images # become apparent. Let's now implement a function to see how different algorithms @@ -69,8 +70,41 @@ function binarize_methods(img_input, algs) return imgs_binarized end -output = binarize_methods(imgw, algs) -mosaicview(output, nrow = 3, npad = 1) +output = binarize_methods(imgw, algs); + + +for i = 1:12 #src + save("assets/test$(i).png", RGB.(output[i])) #src +end #src + +# | Algorithm | Algorithm | Algorithm | +# | :------: | :------: | :------: | +# | AdaptiveThreshold | Balanced | Entropy | +# | ![](assets/test1.png) | ![](assets/test2.png) | ![](assets/test3.png) | +# | MinimumError | Moments | Niblack | +# | ![](assets/test5.png) | ![](assets/test6.png) | ![](assets/test7.png) | +# | Polysegment | Sauvola | UnimodalRosin | +# | ![](assets/test9.png) | ![](assets/test10.png) | ![](assets/test11.png) | +# | Intermodes | Otsu | Yen | +# | ![](assets/test4.png) | ![](assets/test8.png) | ![](assets/test12.png) | + + +# Now let's take a simple example to understand behavior of these algorithms +img = Array(reshape(range(0, stop = 1, length = 4 * 10^4), 200, 200)); +output = binarize_methods(Gray.(img), algs); +for i = 1:12 #src + save("assets/test$(i+12).png", RGB.(output[i])) #src +end #src +# | Algorithm | Algorithm | Algorithm | +# | :------: | :------: | :------: | +# | AdaptiveThreshold | Balanced | Entropy | +# | ![](assets/test113.png) | ![](assets/test14.png) | ![](assets/test15.png) | +# | MinimumError | Moments | Niblack | +# | ![](assets/test16.png) | ![](assets/test17.png) | ![](assets/test18.png) | +# | Polysegment | Sauvola | UnimodalRosin | +# | ![](assets/test19.png) | ![](assets/test20.png) | ![](assets/test21.png) | +# | Intermodes | Otsu | Yen | +# | ![](assets/test22.png) | ![](assets/test23.png) | ![](assets/test24.png) | From 9d54d367a29d64fc51b316aa091c5be411a174a9 Mon Sep 17 00:00:00 2001 From: Ashwani Rathee Date: Sun, 11 Jul 2021 09:43:00 +0530 Subject: [PATCH 4/5] addition of content --- .../image_binarization/image_binarization.jl | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/docs/examples/image_binarization/image_binarization.jl b/docs/examples/image_binarization/image_binarization.jl index 98f1f672..6e492843 100644 --- a/docs/examples/image_binarization/image_binarization.jl +++ b/docs/examples/image_binarization/image_binarization.jl @@ -4,12 +4,12 @@ # date: 2021-7-2 # --- -# ImageBinarization.jl provides number of algorithms for binarizing images -# into background and foreground(bi-level image). In this demonstration , +# ImageBinarization.jl provides several algorithms for binarizing images +# into background and foreground(bi-level image). In this demonstration, # we'll be exploring where these algorithms could be useful and learn how # different algorithms are suited for different types of tasks. -# Suppose a person wants to make a automatic Sudoku solver using Computer +# Suppose a person wants to make an automatic Sudoku solver using Computer # Vision . Before anything else that person needs to import the image, # preprocess it to optimize it for cell content extraction which can then # be used for solving the sudoku. @@ -32,11 +32,11 @@ img = Gray.(img) trfm = recenter(RotMatrix(pi / 30), center(img)); imgw = warp(img, trfm) -# Now lets zoom in a bit +# Now let's zoom in a bit imgw = parent(imgw)[65:490, 65:490] -# Now let's binarize a image using Sauvola algorithm +# Now let's binarize an image using the Sauvola algorithm alg = Sauvola(); img_otsu = binarize(imgw, alg) @@ -89,10 +89,15 @@ end #src # | ![](assets/test4.png) | ![](assets/test8.png) | ![](assets/test12.png) | -# Now let's take a simple example to understand behavior of these algorithms +# Now let's take a simple example to understand the behavior of these algorithms +# -img = Array(reshape(range(0, stop = 1, length = 4 * 10^4), 200, 200)); -output = binarize_methods(Gray.(img), algs); +img = Array(reshape(range(0, stop = 1, length = 4 * 10^4), 200, 200)) +img = Gray.(img) + +# Implementation of algorithms on this example + +output = binarize_methods(img, algs); for i = 1:12 #src save("assets/test$(i+12).png", RGB.(output[i])) #src @@ -108,3 +113,13 @@ end #src # | ![](assets/test19.png) | ![](assets/test20.png) | ![](assets/test21.png) | # | Intermodes | Otsu | Yen | # | ![](assets/test22.png) | ![](assets/test23.png) | ![](assets/test24.png) | + +# For every pixel, the same threshold value is applied. In some cases, if the pixel value is smaller +# than the threshold, it is set to 0, otherwise it is set to a maximum value. In other algorithms, +# a complete opposite approach is used. + +# Every algorithm has its own way of selecting that threshold and in some methods +# it can be defined. + +# binarize_methods() could be particularly useful when you are not aware of the +# underlying assumptions made in algorithms and see all results and choose between them. \ No newline at end of file From 7e3291435c26cfa614940e0397db02244407a70f Mon Sep 17 00:00:00 2001 From: Ashwani Rathee Date: Sun, 11 Jul 2021 09:51:52 +0530 Subject: [PATCH 5/5] Fixes --- .../image_binarization/image_binarization.jl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/examples/image_binarization/image_binarization.jl b/docs/examples/image_binarization/image_binarization.jl index 6e492843..583a1a40 100644 --- a/docs/examples/image_binarization/image_binarization.jl +++ b/docs/examples/image_binarization/image_binarization.jl @@ -14,10 +14,10 @@ # preprocess it to optimize it for cell content extraction which can then # be used for solving the sudoku. -# Let's first import our sudoku +# Let's first import packages and then testimage sudoku -using ImageBinarization, TestImages, MosaicViews, Colors, FileIO, ImageShow -using ImageTransformations, CoordinateTransformations, Rotations, ImageMorphology +using Images, ImageBinarization, TestImages +using CoordinateTransformations, Rotations, ImageTransformations # Original Image @@ -36,7 +36,7 @@ imgw = warp(img, trfm) imgw = parent(imgw)[65:490, 65:490] -# Now let's binarize an image using the Sauvola algorithm +# Now let's binarize an image using the `Sauvola` algorithm alg = Sauvola(); img_otsu = binarize(imgw, alg) @@ -88,6 +88,9 @@ end #src # | Intermodes | Otsu | Yen | # | ![](assets/test4.png) | ![](assets/test8.png) | ![](assets/test12.png) | +# We can choose one of methods based on the results here, and use `OCReact.jl` +# which is based on Tesseract OCR to find the content in the sudoku and then +# solve the sudoku. # Now let's take a simple example to understand the behavior of these algorithms # @@ -106,7 +109,7 @@ end #src # | Algorithm | Algorithm | Algorithm | # | :------: | :------: | :------: | # | AdaptiveThreshold | Balanced | Entropy | -# | ![](assets/test113.png) | ![](assets/test14.png) | ![](assets/test15.png) | +# | ![](assets/test13.png) | ![](assets/test14.png) | ![](assets/test15.png) | # | MinimumError | Moments | Niblack | # | ![](assets/test16.png) | ![](assets/test17.png) | ![](assets/test18.png) | # | Polysegment | Sauvola | UnimodalRosin | @@ -121,5 +124,5 @@ end #src # Every algorithm has its own way of selecting that threshold and in some methods # it can be defined. -# binarize_methods() could be particularly useful when you are not aware of the +# `binarize_methods()`` could be particularly useful when you are not aware of the # underlying assumptions made in algorithms and see all results and choose between them. \ No newline at end of file