[Insight-developers] FloodFill Iterator : Stack vs Queue

Luis Ibanez luis.ibanez@kitware.com
Wed, 02 Apr 2003 14:24:21 -0500


This is a multi-part message in MIME format.
--------------060305070502080005030601
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit


Hi,

As we discussed in one of the recent Tcons, the FloodFill
iterator is using the STL stack container for holding the
pixels to be visited.

However,  the queue is more appropriate for this task


Andy Cedilnik just made a very convincing test of the
advantge of using the Queue instead of the Stack.

His test is a python script that implements both
approaches for flood fill and display their evolution.

The test prints out both the computing time and the
maximum depth of the container (queue or stack).


Andy's  script is attached.

I'll give it a shot at replacing the std::stack container with
the std::queue container in the itkFloodFill iterator.


    Luis


BTW
Andy is joking about rewriting ITK in Python,
at least I think it was a joke...    :-)

--------------060305070502080005030601
Content-Type: text/plain;
 name="flood.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="flood.py"

#!/usr/bin/env python

import sys
import time

width = 300
height = 200
factor = 2
do_stack = 0
radius = min(width, height)/6
gui = 1

radius_sq = radius * radius
if len(sys.argv) > 1:
  do_stack = 1

if gui:
  import Tkinter
  root = Tkinter.Tk()
  cv = Tkinter.Canvas(root)
  cv["width"] = width*factor
  cv["height"] = height*factor
  cv.pack(fill=Tkinter.BOTH, expand=1)

point = (width/2, height/2)
screen = []
for x in range(width):
  line = []
  px = x - width/2
  for y in range(height):
    py = y - height/2
    if px*px + py*py > radius_sq:
      line.append( 1 )
    else:
      line.append( 0 )
  screen.append(line)

class Queue:
  def __init__(self):
    self.Data = []
    self.Maxlen = 0
  def Put(self, point):
    self.Data.append(point)
    self.Maxlen = max(self.Maxlen, len(self.Data))
  def Get(self):
    if len(self.Data) == 0:
      return 0
    pt = self.Data[0]
    self.Data = self.Data[1:]
    return pt

class Stack:
  def __init__(self):
    self.Data = []
    self.Maxlen = 0
  def Put(self, point):
    self.Data.append(point)
    self.Maxlen = max(self.Maxlen, len(self.Data))
  def Get(self):
    if len(self.Data) == 0:
      return 0
    pt = self.Data[len(self.Data)-1]
    self.Data = self.Data[:len(self.Data)-1]
    return pt


def Check(x, y):
  if (x < 0 or y < 0 or 
      x >= width or 
      y >= height ):
    return 1
  if screen[x][y]:
    return 1
  return 0

def PutCheck(pt, ds):
  if Check(pt[0], pt[1]):
    return
  ds.Put(pt)
  


def process_one_step():
  pt = ds.Get()
  if not pt:
    End()
    return 0
  # check if pixel set
  pixel_set = Check(pt[0], pt[1])

  if not pixel_set:
    #print "Create pixel at:", pt
    if gui:
      cv.create_oval((pt[0]*factor, pt[1]*factor, (pt[0]+1)*factor, (pt[1]+1)*factor))
      root.update()
    screen[pt[0]][pt[1]] = 1
   
    PutCheck((pt[0]-1, pt[1]-1), ds)
    PutCheck((pt[0]  , pt[1]-1), ds)
    PutCheck((pt[0]+1, pt[1]-1), ds)
    PutCheck((pt[0]-1, pt[1]), ds)
    PutCheck((pt[0]+1, pt[1]), ds)
    PutCheck((pt[0]-1, pt[1]+1), ds)
    PutCheck((pt[0]  , pt[1]+1), ds)
    PutCheck((pt[0]+1, pt[1]+1), ds)
  return 1

def End():
  end_timer = time.time()
  print "Maximum size of data structure: %d" % ds.Maxlen
  print "                  Elapsed time: %.3f" % (end_timer-start_timer)

start_timer = time.time()
if do_stack:
  print "Process stack"
  ds = Stack()
else:
  print "Process queue"
  ds = Queue()
ds.Put(point)

while process_one_step():
  pass

if gui:
  root.mainloop()

--------------060305070502080005030601--