Regions of interest

After this step you should know how to:

See also:

In the previous step, we used the routine data::fill in order to change the values of an image. It was convenient since we did not need to write any loop by hand. The problem was that we could not specify which region to fill with data. This point leads us to talk about the genericity in Olena. All along this example we will use the routine data::fill to illustrate the possibilities in Olena but note that every image types passed to the routine in this example could be passed to any algorithm in the library expecting an image.

One main feature of Olena is to be able to easily work on regions of interest in images. According to the way a region of interest is defined, a specific image type is associated. Therefore, each algorithm knows exactly what it is working on and can behave differently in order to be the most efficient as possible.

All along this step, we will use the following image lena declared as follow:

  image2d<value::rgb8> lena;
  io::ppm::load(lena, MLN_IMG_DIR "/small.ppm");

data::fill has the following prototype:

namespace data

  template <typename I, typename D>
  void fill(Image<I>& ima, const D& data);

So keep in mind that the first argument we will try to construct in each example is an image. Note that this image must be writable, e.g. non-const.

Image domain restricted by a site set

Here, we would like to fill a small square with green in lena. We want this square to be of size 20x20 and to be located at (20,20). First, we just need to declare this square which is actually a site set, a box2d.

  box2d roi = make::box2d(20, 20, 39, 39);

Then, we just need to tell data::fill that we would like to fill the image lena but only in this restricted part of the image domain.

  data::fill((lena | roi).rw(), literal::green);
Operator ’|’ can be read ’restricted to’. So below, we wrote ’image lena restricted to the region of interest roi’. Actually this is not directly lena which is restricted but its domain.

Note the use of rw() which is mandatory due to C++ limitations. In C++, the image created by lena | roi is const, e.g. read-only, though data::fill expect a non-const image, e.g. read-write. rw() is a workaround to make it read-write.

Fill with blue a region of interest defined by a box2d.

Image domain restricted by a function

Sometimes it may not be easy to construct a site set to restrict an image. For instance, if we would like to fill with green one point out of two in the whole image, we do not want to write anyloop or construct any site set by hand:

  p_array<point2d> arr;
  for (def::coord row = geom::min_row(lena); row < geom::max_row(lena); ++row)
    for (def::coord col = geom::min_row(lena); col < geom::max_col(lena); ++col)
      if (((row + col) % 2) == 0)
        arr.append(point2d(row, col));
  for (def::coord row = geom::min_row(lena); row < geom::max_row(lena); ++row)
    for (def::coord col = geom::min_row(lena); col < geom::max_col(lena); ++col)
      if (((row + col) % 2) == 0)
        opt::at(lena, row, col) = literal::green;

A shorter way to get exactly the same result, is to define that behavior by a function. In Milena, a function fun::p2b::chess is available and does exactly what we want. Like if it was a site set, simply restrict the image with the function.

  data::fill((lena | fun::p2b::chess()).rw(), literal::green);

Fill with green a region of interest defined by a Function.

Note that the functions provided by default in Olena are actually functors. Thus, they must be constructed like any object which why it is written lena | fun::p2v::chess() and not lena | fun::p2v::chess.

Image domain restricted by a mask

Sometimes instead of having a site site or a function defining the regions of interest we want to work on, we may have a binary image, e.g. a mask. When a site has its value set to true, it means it will be considered as part of the masked image domain. Otherwise, it will not.

We construct a mask, mask. It is initialized with the same geometry properties as lena (domain, extension...).

  image2d<bool> mask;
  initialize(mask, lena);
  data::fill(mask, false);
  data::fill((mask | make::box2d(10, 10, 14, 14)).rw(), true);
  data::fill((mask | make::box2d(25, 15, 29, 18)).rw(), true);
  data::fill((mask | make::box2d(50, 50, 54, 54)).rw(), true);

Then, we cannot restrict directly lena with mask. These two images have the same domain, so lena | mask.domain() would not do anything. mask is a classical image, there is not specific type for mask images. Therefore, we need to express that we want that binary image to be considered as a mask.

  data::fill((lena | pw::value(mask)).rw(), literal::green);
pw::value(mask) makes explicit the fact that mask is actually a mask. It means, that for each site of mask, if its value is set to true, then the value associated to this site in lena must be set to green. In this example, we use two images for two different use case: lena store the result and the modifications make by the algorithm and mask allows the algorithm to know whether it must treat a site or not.

Fill with green a region of interest defined by a mask image.

Image domain restricted by a predicate

Restricting by a predicate is exactly like restricting with a function. We want to talk about that separately in order to present the small routines available. They enable the user to write quick and efficient predicate/function.

The two routines are :

Let’s see a common use case. First, we binarize lena according to specific criterions, only site values with specific colors are set to true in lena_bw. Others are set to false. This image will be used in order to label the components. Let’s consider a labeled image label. Each component of lena is labeled with a unique index. Now, we consider that that our region of interest is a component with id 16. Then we want to express ’for each site fill its value in lena if its value in label is equal to 16’.

  image2d<bool> lena_bw = binarization::binarization(lena, keep_specific_colors());
  value::label_8 nlabels;
  image2d<value::label_8> label = labeling::blobs(lena_bw, c8(), nlabels);

  data::fill((lena | (pw::value(label) == pw::cst(0u))).rw(), literal::blue);

Fill with green a region of interest defined by its label.

←— Go to Read and write images    

This document was translated from LATEX by HEVEA.