Skip to content
Andre Ambrosio Boechat edited this page Mar 25, 2017 · 4 revisions

Image segmentation is tipically used to locate objects and boundaries (lines, curves, etc.) in images. The simplest technique to achieve image segmentation is called thresholding, where pixel intensities are set to 0 or 1 depending if their original value is above or below a threshold.

Global Thresholding

As an example, let's load an image in gray scale and then apply a threshold:

(require '[eye-boof.core :refer :all]
         '[eye-boof.visualization :refer [show-image render-binary]])

(def gray-img (-> "http://png-3.vector.me/files/images/8/0/807142/realistic_vector_eye_thumb.jpg"
                  (java.net.URL.)
                  load-image->gray-u8))

(-> (threshold gray-img 100 true)
    (render-binary true)
    show-image)

Note that threshold makes intensities below 100 to become 1 and the rest to become 0. render-binary usually makes 0 to become white and 1 to become black, but we are telling it to invert the procedure, e.i., zeros (original intensities above 100) become black and ones (intensities below 100) become white.

black-white eye

Another interesting way of calculating a global threshold for an image is using Otsu's method. The algorithm assumes the intensities follow a bi-modal histogram representing the background and the foreground, calculating the optimal threshold so that their intra-class variance is minimal.

(let [otsu-f #(otsu-threshold % 0 255)]
  (-> (threshold-f gray-img otsu-f true)
      (render-binary true)
      show-image))

otsu eye

Local Thresholding

In the previous examples, a global threshold value was calculated for the whole image. However, due to noise and nonuniform illumination, there are many cases where a global value is ineffective and we end up either losing important information or keeping a high level of noise, or both.

Let's use a picture of a text as an example1 and apply a global threshold to it:

(def sonnet-lena (load-image->gray-u8 "sonnet_for_lena.gif"))

(let [otsu-f #(otsu-threshold % 0 255)]
  (show-grid 2
             sonnet-lena
             (render-binary
              (threshold-f sonnet-lena otsu-f true) true)))
sonnet original sonnet otsu

As we can see, a global threshold is completely ineffective due to the poor and nonuniform illumination. An alternative solution is the calculation of local or adaptive threshold values, where a value is calculated at every point (x, y) of the image based on properties of its neighborhood.

An implementation of this strategy is local-square-threshold, which basically works like a moving average along the image.

(-> (local-square-threshold sonnet-lena 15 true 0.93)
    (render-binary true)
    show-image)
sonnet original sonnet local

1: Picture taken from the URL http://homepages.inf.ed.ac.uk/rbf/HIPR2/images/son1.gif.

Clone this wiki locally