[GRASS-dev] Testing i.superpixels.slic

Hello,

thanks a lot for spending time and work implementing i.superpixels.slic.
It was awesome to see how fast the ticket was addressed, in which I asked if someone would be interested in implementing this addon.

I did some initial tests on a UAV orthoimage (Extent: 1000x1000m, GSD: 5cm) and unfortunately it delivered quite different results than a comparable Matlab implementation.

What I did:

  • i.superpixels.slic on parts of the RGB image with num_pixels = 2500 and compactness = 1

  • i.superpixels.slic on parts of the RGB image with num_pixels = 2500 and compactness = 20

  • i.superpixels.slic on parts of the RGB image with num_pixels = 2500 and compactness = 1 and -n

  • I ran the matlab implementation with the same settings

What I observed:

  • i.superpixels.slic outlines rarely align with the road outlines in the image.

  • Numerous very small superpixels are created (especially for compactness = 1 and compactness = 1 + -n). The total number of superpixel is much larger than the one defined with num_pixels. The output looks rather like that of a classical edge detector in textured regions (see screenshots attached).

My questions:

  • Why does the number of superpixels not correspond to the one defined in num_pixels?

  • How can two implementations both based on Achanta et al. provide such different results (screenshots attached)?

  • The manual says: ‘Contrary to the Achanta et al. version of SLIC0, i.superpixels.slic takes into account the compactness value chosen by the user even when the -n flag is used.’ I understand SLICO as a version of SLIC, for which the compactness is adaptively refined for each superpixel. To me, the purpose of SLICO seems to be that the compactness does not need to be defined and that the superpixels outlines are more regular-shaped. However, in the manual it sounds as if -n would rather intend to favor irregular-shaped superpixels. It is not clear to me, how the GRASS version relates to the usual SLICO version.

Screenshots:

References:

Best,

Sophie Crommelinck

Hi Sophie !

On 01/03/17 15:59, Sophie Crommelinck wrote:

Hello,

thanks a lot for spending time and work implementing /i.superpixels.slic/.
It was awesome to see how fast the ticket was addressed, in which I
asked if someone would be interested in implementing this addon.

I did some initial tests on a UAV orthoimage (Extent: 1000x1000m, GSD:
5cm) and unfortunately it delivered quite different results than a
comparable Matlab implementation.

What I did:

  * i.superpixels.slic on parts of the RGB image with /num_pixels/ =
    2500 and /compactness/ = 1
  * i.superpixels.slic on parts of the RGB image with /num_pixels/ =
    2500 and /compactness/ = 20
  * i.superpixels.slic on parts of the RGB image with /num_pixels/ =
    2500 and /compactness/ = 1 and /-n/
  * I ran the matlab implementation with the same settings

What I observed:

  * i.superpixels.slic outlines rarely align with the road outlines in
    the image.
  * Numerous very small superpixels are created (especially for
    /compactness/ = 1 and /compactness/ = 1 + /-n/). The total number of
    superpixel is much larger than the one defined with /num_pixels/.
    The output looks rather like that of a classical edge detector in
    textured regions (see screenshots attached).

My questions:
  * Why does the number of superpixels not correspond to the one defined
    in /num_pixels?/

You might have to increase the number of iterations. The default number of 10 is quite low.

Also, consider setting step instead of num_pixels.

  * How can two implementations both based on Achanta et al. provide
    such different results (screenshots attached)?/

i.superpixels.slic is based on the original Achanta et al C++ code, but it is not identical to it. Several choices were made based on the experience with our implementation and based on critical review of the original code.
The basic philosophy of the algorithm is the same. The concrete implementation is not.
I also have no idea if their Matlab code gives the same results as their C++ code...

The meaning of some parameter values is not exactly the same, notably compactness. The "compactness" indicator is a weighting criteria between the spatial and the spectral distance between a pixel and a superpixel. This value is somewhat arbitrary and it is treated slightly differently internally in i.superpixels.slic from its treatment in the original code. So, you cannot compare compactness=1 between the two implementations.

In addition, I think that the original code perturbs the location of original seeds by default. You might want to set the 'perturb' parameter.

In short: don't expect similar results using same settings. Just experiment with i.superpixels.slic until you get a satisfying result.

Also don't forget that in GRASS GIS you can input an

    /
  * The manual says: '/Contrary to the Achanta et al. version of SLIC0,
    i.superpixels.slic takes into account the compactness value chosen
    by the user even when the *-n* flag is used./' I understand SLICO as
    a version of SLIC, for which the compactness//is adaptively refined
    for each superpixel. To me, the purpose of SLICO seems to be that
    the compactness does not need to be defined and that the superpixels
    outlines are more regular-shaped. However, in the manual it sounds
    as if -n would rather intend to favor irregular-shaped superpixels.
    It is not clear to me, how the GRASS version relates to the usual
    SLICO version.

Achanta et al use the following formula in SLIC for the distance between a pixel and a superpixel:

D^2 = (dc / N)^2 + (ds / S)^2

where dc is the spectral distance, ds is the spatial distance, S is the samplig interval (total number of pixels divided by number of superpixels) and N is the maximum spectral distance which varies from cluster to cluster. They decided to replace N by a constant m and thus change the formula into

D^2 = (dc / m)^2 + (ds / S)^2

which they rewrite to

D^2 = dc^2 + (ds / S)^2 * m^2

and they consider m as compactness (i.e. when m is high the spatial term ds/S gets more important than the spectral term dc^2)

In SLIC0, they then rewrite this to

D^2 = (dc / mc)^2 + (ds / ms)^2

where mc and ms are the "maximum observed spatial and color distances" of each cluster in the previous iteration.

However, that takes away the opportunity for the user to provide a weight of spatial vs spectral distance.

MarkusM thus decided to keep that option of determining a weight (the "compactness").

In i.superpixels.slic, the equation is always:

D^2 = (dc / m)^2 + c * (ds / S)^2

where S determined by the step and m is

- in SLIC: the maximum spectral distance observed amongst all clusters
- in SLIC0: the maxium spectral distance in each cluster separately.

I agree that one can argue about the question whether this implementation should still be called SLIC0, but it it sufficiently close to the original, while, IMHO, improving it, that I think that it still warrants the name.

Moritz

Hi Moritz,

thank you for your extensive answer! Your reply was very clear and solved most of my questions, I added two comments in your mail below.

@ Vaclav Petras: You asked to provide the data as well. I uploaded the part of the orthoimage shown in the screenshots to the same folder:
https://share4land.itc.utwente.nl:5566/sharing/fS3tbiWuW

Thanks again,

Sophie

···

2017-03-01 16:45 GMT+01:00 Moritz Lennert <mlennert@club.worldonline.be>:

Hi Sophie !

On 01/03/17 15:59, Sophie Crommelinck wrote:

Hello,

thanks a lot for spending time and work implementing /i.superpixels.slic/.
It was awesome to see how fast the ticket was addressed, in which I
asked if someone would be interested in implementing this addon.

I did some initial tests on a UAV orthoimage (Extent: 1000x1000m, GSD:
5cm) and unfortunately it delivered quite different results than a
comparable Matlab implementation.

What I did:

  • i.superpixels.slic on parts of the RGB image with /num_pixels/ =
    2500 and /compactness/ = 1
  • i.superpixels.slic on parts of the RGB image with /num_pixels/ =
    2500 and /compactness/ = 20
  • i.superpixels.slic on parts of the RGB image with /num_pixels/ =
    2500 and /compactness/ = 1 and /-n/
  • I ran the matlab implementation with the same settings

What I observed:

  • i.superpixels.slic outlines rarely align with the road outlines in
    the image.
  • Numerous very small superpixels are created (especially for
    /compactness/ = 1 and /compactness/ = 1 + /-n/). The total number of
    superpixel is much larger than the one defined with /num_pixels/.
    The output looks rather like that of a classical edge detector in
    textured regions (see screenshots attached).

My questions:

  • Why does the number of superpixels not correspond to the one defined
    in /num_pixels?/

You might have to increase the number of iterations. The default number of 10 is quite low.

I also tested increasing the number of iterations to 100. This resulted in a lower number of tiny superpixels, but still some superpixels are far away from being equally shaped compared to the rest. Also this resulted in a processing time of several hours. I didn’t check the effect of changing step instead of num_pixels.

Also, consider setting step instead of num_pixels.

  • How can two implementations both based on Achanta et al. provide
    such different results (screenshots attached)?/

i.superpixels.slic is based on the original Achanta et al C++ code, but it is not identical to it. Several choices were made based on the experience with our implementation and based on critical review of the original code.
The basic philosophy of the algorithm is the same. The concrete implementation is not.
I also have no idea if their Matlab code gives the same results as their C++ code…

The meaning of some parameter values is not exactly the same, notably compactness. The “compactness” indicator is a weighting criteria between the spatial and the spectral distance between a pixel and a superpixel. This value is somewhat arbitrary and it is treated slightly differently internally in i.superpixels.slic from its treatment in the original code. So, you cannot compare compactness=1 between the two implementations.

In addition, I think that the original code perturbs the location of original seeds by default. You might want to set the ‘perturb’ parameter.

In short: don’t expect similar results using same settings. Just experiment with i.superpixels.slic until you get a satisfying result.

Also don’t forget that in GRASS GIS you can input an

Where did the rest of the sentence go?

/

  • The manual says: ‘/Contrary to the Achanta et al. version of SLIC0,
    i.superpixels.slic takes into account the compactness value chosen
    by the user even when the -n flag is used./’ I understand SLICO as
    a version of SLIC, for which the compactness//is adaptively refined
    for each superpixel. To me, the purpose of SLICO seems to be that
    the compactness does not need to be defined and that the superpixels
    outlines are more regular-shaped. However, in the manual it sounds
    as if -n would rather intend to favor irregular-shaped superpixels.
    It is not clear to me, how the GRASS version relates to the usual
    SLICO version.

Achanta et al use the following formula in SLIC for the distance between a pixel and a superpixel:

D^2 = (dc / N)^2 + (ds / S)^2

where dc is the spectral distance, ds is the spatial distance, S is the samplig interval (total number of pixels divided by number of superpixels) and N is the maximum spectral distance which varies from cluster to cluster. They decided to replace N by a constant m and thus change the formula into

D^2 = (dc / m)^2 + (ds / S)^2

which they rewrite to

D^2 = dc^2 + (ds / S)^2 * m^2

and they consider m as compactness (i.e. when m is high the spatial term ds/S gets more important than the spectral term dc^2)

In SLIC0, they then rewrite this to

D^2 = (dc / mc)^2 + (ds / ms)^2

where mc and ms are the “maximum observed spatial and color distances” of each cluster in the previous iteration.

However, that takes away the opportunity for the user to provide a weight of spatial vs spectral distance.

MarkusM thus decided to keep that option of determining a weight (the “compactness”).

In i.superpixels.slic, the equation is always:

D^2 = (dc / m)^2 + c * (ds / S)^2

where S determined by the step and m is

  • in SLIC: the maximum spectral distance observed amongst all clusters
  • in SLIC0: the maxium spectral distance in each cluster separately.

I agree that one can argue about the question whether this implementation should still be called SLIC0, but it it sufficiently close to the original, while, IMHO, improving it, that I think that it still warrants the name.

Moritz


grass-dev mailing list
grass-dev@lists.osgeo.org
https://lists.osgeo.org/mailman/listinfo/grass-dev

On 02/03/17 12:09, Sophie Crommelinck wrote:

2017-03-01 16:45 GMT+01:00 Moritz Lennert <mlennert@club.worldonline.be
<mailto:mlennert@club.worldonline.be>>:

I also tested increasing the number of iterations to 100. This resulted
in a lower number of tiny superpixels, but still some superpixels are
far away from being equally shaped compared to the rest.

If you want more equal shape, you have to increase compactness. And you can try the minsize option. In the original version, they implement a minsize internally, but then merge superpixels that are smaller than that minsize to an arbitrarily chosen neighbor. In i.superpixels.slic, the merging is done to the most similar neighbor.

Also this
resulted in a processing time of several hours.

Make sure to set the memory parameter to as much memory as you can afford. But in tests between MarkusM and me we also saw that the speed of the CPU makes a significant difference.

    In short: don't expect similar results using same settings. Just
    experiment with i.superpixels.slic until you get a satisfying result.

    Also don't forget that in GRASS GIS you can input an

Where did the rest of the sentence go?

Somewhere in the void :wink:

I wanted to point out that contrary to the original version, which is limited to three RGB layers, the GRASS version takes any arbitrary number of input layers. So, if your data is RGB + NIR for example, you can input all 4, and you can also add texture layers, NDVI, or others.

This can potentially improve your results. But it will also increase computing time.

Moritz

On 02/03/17 12:09, Sophie Crommelinck wrote:

Hi Moritz,

thank you for your extensive answer! Your reply was very clear and
solved most of my questions, I added two comments in your mail below.

@ Vaclav Petras: You asked to provide the data as well. I uploaded the
part of the orthoimage shown in the screenshots to the same folder:
https://share4land.itc.utwente.nl:5566/sharing/fS3tbiWuW
<https://share4land.itc.utwente.nl:5566/sharing/fS3tbiWuW&gt;

After import I get ortho.red, ortho.green, ortho.blue.

Using

i.group ortho.red in=ortho.red
i.superpixels.slic ortho.red out=red_sup iterations=50 step=15 perturb=50 compactness=3 memory=5000

I get the following result in 1m40s:

http://tomahawk.ulb.ac.be/moritz/superpixels_ortho_red.png

Not so bad, I would say :wink:

Moritz

I have updated the manual of i.superpixels.slic in r70724, explaining why the GRASS implementation does not provide results identical to the original implementation. Please review!

Markus M

···

On Thu, Mar 2, 2017 at 6:36 PM, Moritz Lennert <mlennert@club.worldonline.be> wrote:

On 02/03/17 12:09, Sophie Crommelinck wrote:

Hi Moritz,

thank you for your extensive answer! Your reply was very clear and
solved most of my questions, I added two comments in your mail below.

@ Vaclav Petras: You asked to provide the data as well. I uploaded the
part of the orthoimage shown in the screenshots to the same folder:
https://share4land.itc.utwente.nl:5566/sharing/fS3tbiWuW
<https://share4land.itc.utwente.nl:5566/sharing/fS3tbiWuW>

After import I get ortho.red, ortho.green, ortho.blue.

Using

i.group ortho.red in=ortho.red
i.superpixels.slic ortho.red out=red_sup iterations=50 step=15 perturb=50 compactness=3 memory=5000

I get the following result in 1m40s:

http://tomahawk.ulb.ac.be/moritz/superpixels_ortho_red.png

Not so bad, I would say :wink:

Moritz


grass-dev mailing list
grass-dev@lists.osgeo.org
https://lists.osgeo.org/mailman/listinfo/grass-dev

Hello,

@ Moritz: Thanks for the support, I will continue testing the module with further data.

@ Markus: I think the manual is clearer now.

Best,

Sophie

···

2017-03-03 21:27 GMT+01:00 Markus Metz <markus.metz.giswork@gmail.com>:

I have updated the manual of i.superpixels.slic in r70724, explaining why the GRASS implementation does not provide results identical to the original implementation. Please review!

Markus M

On Thu, Mar 2, 2017 at 6:36 PM, Moritz Lennert <mlennert@club.worldonline.be> wrote:

On 02/03/17 12:09, Sophie Crommelinck wrote:

Hi Moritz,

thank you for your extensive answer! Your reply was very clear and
solved most of my questions, I added two comments in your mail below.

@ Vaclav Petras: You asked to provide the data as well. I uploaded the
part of the orthoimage shown in the screenshots to the same folder:
https://share4land.itc.utwente.nl:5566/sharing/fS3tbiWuW
<https://share4land.itc.utwente.nl:5566/sharing/fS3tbiWuW>

After import I get ortho.red, ortho.green, ortho.blue.

Using

i.group ortho.red in=ortho.red
i.superpixels.slic ortho.red out=red_sup iterations=50 step=15 perturb=50 compactness=3 memory=5000

I get the following result in 1m40s:

http://tomahawk.ulb.ac.be/moritz/superpixels_ortho_red.png

Not so bad, I would say :wink:

Moritz


grass-dev mailing list
grass-dev@lists.osgeo.org
https://lists.osgeo.org/mailman/listinfo/grass-dev