Regarding examples
All the examples in this section are meant to give you an overview of the
possibilities given by the Mamba Library. They can be used as a starting
point for coding your own applications.
To understand them, we strongly recommand you to read the user manual which
is available in the documentation page.
There are three types of examples :
- Easy: These are mainly intended for beginners so they could refer to some basic examples to start their own code.
- Moderate: In these examples, more elaborated actions are performed and presented. They cover usage that may not be difficult to do provided that you read the documentation, but are more easily explained and understood with an example.
- Advanced: These are more complex examples that should be considered as demonstrators of the capabilities of the Mamba library.
Examples presented here may not correctly work. We tried to put a wide range of examples and produced this small selection after some efforts (some of them are non-trivial) but we may have broken them in the process of publishing them. If it so happens, try to see this as an exercise or e-mail us.
Opening and creating images

This example shows various ways to open or create image using the constructor of the imageMb class. This example is meant to be replayed inside a python console. If you run this script directly, nothing will happen. (script)
![]() |
| snake.png |
1 # Importing the mamba module 2 from mamba import * 3 4 # Opening an existing image (will be greyscale, 8-bit) 5 im1 = imageMb('snake.png') 6 # Creating a 8-bit image with the same size 7 im2 = imageMb(im1, 8) 8 # Then a binary image (still same size) 9 im3 = imageMb(im1, 1) 10 # And a 32-bit image (same size but do I need to be more specific ?) 11 im4 = imageMb(im1, 32) 12 13 # Opening an existing image but as binary image 14 im5 = imageMb('snake.png', 1) 15 # or as a 32-bit image 16 im6 = imageMb('snake.png', 32) 17 # For the last two examples, this might not be pertinent because of the 18 # properties of the example image. 19 20 # Creating an image with a specified size 21 im7 = imageMb(200, 340) 22 # In this example, the created image will have a corrected size of 256x340. 23 24 # Creating an image without option 25 im8 = imageMb() 26 # im8 is now a greyscale image (8-bit) of size 256x256. These are the default 27 # values when they are not overriden in the constructor. 28 29 # Images are automatically garbage collected by Python once there is no more 30 # reference pointing to it. 31
Messing about with display, part 1 : activation

This example shows you how to activate the display and presents some of the options related to the display. This example is meant to be replayed inside a Python console. If you run directly this script, nothing will happen. (script)
![]() |
| snake.png |
1 # Importing the mamba module 2 from mamba import * 3 4 # Loading an image 5 im = imageMb('snake.png') 6 7 # Activating the display. This will make a window appear 8 im.showDisplay() 9 10 # You can deactivate the display at all time by either 11 # - Closing the window 12 # - Calling the appropriate method like this 13 im.hideDisplay() 14 15 # Reactivate it 16 im.showDisplay() 17 18 # You can update the display (if your image changed) by calling the following 19 # method 20 im.updateDisplay() 21 # This action is automatically performed by every Mamba functions so it is 22 # likely you will not have to use it on your own 23 24 # The two last methods related to display allow you to freeze/unfreeze the 25 # display to prevent mamba updating it but keeping the window visible. 26 im.freezeDisplay() # <- the display is no longer updated 27 im.unfreezeDisplay() # <- the display will be updated (and returns to what the 28 # image looks like if there were modifications) 29 30 # Sometimes, you will have lots of images opened and displayed making it quite 31 # messy on your desktop and thus very difficult to read and analyze. To make 32 # sure displays are properly organised you can call the following function 33 tidyDisplays() 34 # The function does not do miracles (like increasing your screen resolution) so 35 # don't have too much expectations 36 37
Messing about with display, part 2 : palette and shortcut

This example shows you some options you can use to increase your display skills. (script)
![]() |
| snake.png |
![]() |
| snake_palette.png |
1 # Importing the mamba module 2 from mamba import * 3 4 # Let's start with an image and an activated display 5 im = imageMb('snake.png') 6 im.showDisplay() 7 8 # Setting up a rainbow palette for image im 9 im.setPalette(rainbow) 10 11 # You can disable it by calling the resetPalette method 12 im.resetPalette() 13 14 # You can create your own palette 15 your_palette = ( 16 0, 0, 131, 0, 0, 135, 0, 0, 139, 0, 0, 143, 0, 0, 147, 0, 0, 151, 0, 0, 155, 0, 0, 17 159, 0, 0, 163, 0, 0, 167, 0, 0, 171, 0, 0, 175, 0, 0, 179, 0, 0, 183, 0, 0, 187, 18 0, 0, 191, 0, 0, 195, 0, 0, 199, 0, 0, 203, 0, 0, 207, 0, 0, 211, 0, 0, 215, 0, 0, 19 219, 0, 0, 223, 0, 0, 227, 0, 0, 231, 0, 0, 235, 0, 0, 239, 0, 0, 243, 0, 0, 247, 20 0, 0, 251, 0, 0, 255, 0, 3, 255, 0, 7, 255, 0, 11, 255, 0, 15, 255, 0, 19, 255, 0, 21 23, 255, 0, 27, 255, 0, 31, 255, 0, 35, 255, 0, 39, 255, 0, 43, 255, 0, 47, 255, 0, 22 51, 255, 0, 55, 255, 0, 59, 255, 0, 63, 255, 0, 67, 255, 0, 71, 255, 0, 75, 255, 0, 23 79, 255, 0, 83, 255, 0, 87, 255, 0, 91, 255, 0, 95, 255, 0, 99, 255, 0, 103, 255, 24 0, 107, 255, 0, 111, 255, 0, 115, 255, 0, 119, 255, 0, 123, 255, 0, 127, 255, 0, 25 131, 255, 0, 135, 255, 0, 139, 255, 0, 143, 255, 0, 147, 255, 0, 151, 255, 0, 155, 26 255, 0, 159, 255, 0, 163, 255, 0, 167, 255, 0, 171, 255, 0, 175, 255, 0, 179, 255, 27 0, 183, 255, 0, 187, 255, 0, 191, 255, 0, 195, 255, 0, 199, 255, 0, 203, 255, 0, 28 207, 255, 0, 211, 255, 0, 215, 255, 0, 219, 255, 0, 223, 255, 0, 227, 255, 0, 231, 29 255, 0, 235, 255, 0, 239, 255, 0, 243, 255, 0, 247, 255, 0, 251, 255, 0, 255, 255, 30 3, 255, 255, 7, 255, 251, 11, 255, 247, 15, 255, 243, 19, 255, 239, 23, 255, 235, 31 27, 255, 231, 31, 255, 227, 35, 255, 223, 39, 255, 219, 43, 255, 215, 47, 255, 211, 32 51, 255, 207, 55, 255, 203, 59, 255, 199, 63, 255, 195, 67, 255, 191, 71, 255, 187, 33 75, 255, 183, 79, 255, 179, 83, 255, 175, 87, 255, 171, 91, 255, 167, 95, 255, 163, 34 99, 255, 159, 103, 255, 155, 107, 255, 151, 111, 255, 147, 115, 255, 143, 119, 255, 35 139, 123, 255, 135, 127, 255, 131, 131, 255, 127, 135, 255, 123, 139, 255, 119, 143, 36 255, 115, 147, 255, 111, 151, 255, 107, 155, 255, 103, 159, 255, 99, 163, 255, 95, 37 167, 255, 91, 171, 255, 87, 175, 255, 83, 179, 255, 79, 183, 255, 75, 187, 255, 71, 38 191, 255, 67, 195, 255, 63, 199, 255, 59, 203, 255, 55, 207, 255, 51, 211, 255, 47, 39 215, 255, 43, 219, 255, 39, 223, 255, 35, 227, 255, 31, 231, 255, 27, 235, 255, 23, 40 239, 255, 19, 243, 255, 15, 247, 255, 11, 251, 255, 7, 255, 255, 3, 255, 255, 0, 255, 41 251, 0, 255, 247, 0, 255, 243, 0, 255, 239, 0, 255, 235, 0, 255, 231, 0, 255, 227, 42 0, 255, 223, 0, 255, 219, 0, 255, 215, 0, 255, 211, 0, 255, 207, 0, 255, 203, 0, 43 255, 199, 0, 255, 195, 0, 255, 191, 0, 255, 187, 0, 255, 183, 0, 255, 179, 0, 255, 44 175, 0, 255, 171, 0, 255, 167, 0, 255, 163, 0, 255, 159, 0, 255, 155, 0, 255, 151, 45 0, 255, 147, 0, 255, 143, 0, 255, 139, 0, 255, 135, 0, 255, 131, 0, 255, 127, 0, 46 255, 123, 0, 255, 119, 0, 255, 115, 0, 255, 111, 0, 255, 107, 0, 255, 103, 0, 255, 47 99, 0, 255, 95, 0, 255, 91, 0, 255, 87, 0, 255, 83, 0, 255, 79, 0, 255, 75, 0, 255, 48 71, 0, 255, 67, 0, 255, 63, 0, 255, 59, 0, 255, 55, 0, 255, 51, 0, 255, 47, 0, 255, 49 43, 0, 255, 39, 0, 255, 35, 0, 255, 31, 0, 255, 27, 0, 255, 23, 0, 255, 19, 0, 255, 50 15, 0, 255, 11, 0, 255, 7, 0, 255, 3, 0, 255, 0, 0, 251, 0, 0, 247, 0, 0, 243, 0, 51 0, 239, 0, 0, 235, 0, 0, 231, 0, 0, 227, 0, 0, 223, 0, 0, 219, 0, 0, 215, 0, 0, 52 211, 0, 0, 207, 0, 0, 203, 0, 0, 199, 0, 0, 195, 0, 0, 191, 0, 0, 187, 0, 0, 183, 53 0, 0, 179, 0, 0, 175, 0, 0, 171, 0, 0, 167, 0, 0, 163, 0, 0, 159, 0, 0, 155, 0, 54 0, 151, 0, 0, 147, 0, 0, 143, 0, 0, 139, 0, 0, 135, 0, 0, 131, 0, 0 55 ) 56 57 # And then apply it to your image 58 im.setPalette(your_palette) 59 60 # If you save at this point, the saved image will use the palette 61 im.save('snake_palette.png') 62 63 # Now you can play with the display shortcuts 64 # Try pressing P, it disables the palette (only in display not in save) 65 # Try zooming in or out with A and Z or with your mouse wheel 66 # Try Ctrl-R to reset the display 67 # Try pressing the right button of your mouse to spawn the contextual menu 68 69 70
Image properties

This example shows you how to get image properties like size and depth. It also describes how the image constructor can be used to create images sharing the same properties. (script)
![]() |
| snake.png |
1 # Importing the mamba module 2 from mamba import * 3 4 # Loading an image 5 im = imageMb('snake.png') 6 7 # This image is 320x230 in 8-bit greyscale 8 print im.getSize() 9 print im.getDepth() 10 11 # Creating an image with the same properties 12 im1 = imageMb(im) 13 print im1.getSize() 14 print im1.getDepth() 15 16 # Creating an image with the same properties except for depth 17 im2 = imageMb(im, 1) 18 print im2.getSize() 19 print im2.getDepth() # <- here the return is 1 20 21 22
Pixels manipulation

In this example, we use the pixels manipulation methods. (script)
1 # Importing the mamba module 2 from mamba import * 3 4 # Creating a default image, 256x256 8-bit image 5 im = imageMb() 6 7 # Setting the pixel at (128,128) to value 50 8 im.setPixel(50, (128,128)) 9 # Getting the pixel value at the same position 10 print im.getPixel((128,128)) 11 12 # When trying to access a pixel outside image boundary an exception is raised 13 try: 14 im.getPixel((256,256)) # position start at 0 to width-1 or height-1 15 except MambaError: 16 print "error catch" 17 18 # The two methods to set a pixel vary on one aspect: the display update 19 im.showDisplay() 20 im.setPixel(255, (10,10)) # <- Pixel is set and visible in display 21 im.fastSetPixel(255, (20,20)) # <- Pixel is set but not visible 22 im.updateDisplay() # Now it is 23 24
Drawing in Mamba

These examples shows some of the drawing functions available in Mamba (script)
![]() | ![]() | ![]() |
| draw_line.png | draw_square.png | draw_circle.png |
1 # Importing the mamba module 2 from mamba import * 3 # Importing the mambaDraw module 4 import mambaDraw 5 6 # Creating a default image, 256x256 8-bit image 7 im = imageMb() 8 9 # Drawing a line. The line is drawn according to the given 10 # 4 value tuple interpreted as (x_start, y_start, x_stop, y_stop). 11 # So, in our case, the line goes from point (45,163) to point (221,8) 12 mambaDraw.drawLine(im, (45,163,221,8), 180) 13 im.save("draw_line.png") 14 15 16 im.reset() 17 # Drawing a square (actually a rectangle) filled with value 160. 18 # The middle tuple indicates from where to where the square extends 19 mambaDraw.drawSquare(im, (120,15,160,95), 160) 20 # Drawing another square filled with value 220. Notice that this 21 # square overlaps the first one. The last drawn is always on top 22 # of the others 23 mambaDraw.drawSquare(im, (50,80,200,180), 220) 24 im.save("draw_square.png") 25 26 im.reset() 27 # Drawing an empty circle centered in the middle of the image with a 28 # radius of 50 and white (255). 29 mambaDraw.drawCircle(im, (128,128,50), 255) 30 # Then drawing a filled circle. 31 mambaDraw.drawFillCircle(im, (128,128,20), 255) 32 im.save("draw_circle.png") 33 34
Conversion between PIL image format and Mamba image format

This example shows how to convert your Mamba image into a PIL image enabling you to use PIL functionnalities and how to convert the result back into a Mamba image. Image source is http://commons.wikimedia.org/wiki/File:Ebenthal\_Schlosswirt\_20052010\_06.jpg (script)
![]() |
| colorful.jpg |
![]() |
| colorful_transposed.png |
1 # Importing the mamba module, the mambaExtra module and the Image module (PIL) 2 from mamba import * 3 import mambaExtra 4 import Image 5 6 # Opening an image and storing it in Mamba format 7 im = imageMb('colorful.jpg') 8 9 # Converting the image in PIL format 10 pilim = mambaExtra.Mamba2PIL(im) 11 12 # Doing a bit of computation using the PIL library 13 pilim = pilim.transpose(Image.FLIP_LEFT_RIGHT) 14 15 # Then converting back into mamba format 16 mambaExtra.PIL2Mamba(pilim, im) 17 18 # And saving it, notice that color disappeared 19 im.save("colorful_transposed.png") 20
mambaExtra Dynamic thresholder usage

This is a small demonstration of the mambaExtra dynamic thresholder GUI. It allows you to search manually for the best threshold value (script)
![]() |
| snake.png |
![]() |
| dynamicThreshold_snap.png |
1 # Importing the mamba module and of course the mambaExtra module 2 from mamba import * 3 import mambaExtra 4 # Opening an image 5 im = imageMb('snake.png') 6 7 # Calling the dynamic threshold GUI 8 # This will block script progression until user hit the close button 9 # You can change the threshold values by using keys q, s, w and x. Of course 10 # the display can be zoom in or out and has most of the functionalities 11 # available in the standard mamba display. 12 tvals = mambaExtra.dynamicThreshold(im) 13 14 # The value obtained can be then used to compute a binary 15 # image with the threshold value (upper and lower threshold) 16 thresh = imageMb(im, 1) 17 threshold(im, thresh, *tvals) 18
mambaExtra superposer usage

This is a small demonstration of the mambaExtra superposer GUI. It allows you to display two images at the same time in a superposed manner. (script)
![]() |
| coffee_grains.jpg |
![]() |
| superpose_snap.png |
1 # Importing the mamba module and of course the mambaExtra module 2 from mamba import * 3 import mambaExtra 4 5 # Opening an image 6 im = imageMb('coffee_grains.jpg') 7 # To create a superposable image we will generate a binary threshold image 8 thresh = imageMb(im, 1) 9 threshold(im, thresh, 0, 128) 10 11 # Calling the superposer GUI 12 # This will block script progression until user hit the close button 13 # You can change the color in the legend. 14 # Of course the display can be zoom in or out and has most of the 15 # functionalities available in the standard mamba display. 16 mambaExtra.superpose(im, thresh) 17
Erosion and structuring elements

This example shows you how to create a structuring element and how to use it with the erode function (script)
![]() |
| snake.png |
![]() |
| snake_ero10rt.png |
1 # Importing the mamba module and the mambaComposed package 2 from mamba import * 3 import mambaComposed as mC 4 5 # Opening and creating images 6 im1 = imageMb('snake.png') 7 im2 = imageMb(im1) 8 9 # Creating a reversed triangle (as opposed to the TRIANGLE found in Mamba 10 # source) structuring element 11 reverse_triangle = mC.structuringElement([0,1,6], grid=HEXAGONAL) 12 13 # Performing an erosion of size 10 with the created structuring element 14 mC.erode(im1, im2, 10, se=reverse_triangle) 15 16 im2.save("snake_ero10rt.png") 17
Valued minima of a greyscale image

This example is a small variation of the minima function found in the mambaComposed geodesy module. It shows that there are various possibilities to attain the same result in Mamba. (script)
![]() |
| snake.png |
![]() |
| snake_valmin.png |
1 # Importing the mamba module 2 from mamba import * 3 4 def valuedMinima(imIn, imOut, h=1, grid=DEFAULT_GRID): 5 """ 6 Computes the valued minima of 'imIn' using a dual build operation and 7 puts the result in 'imOut'. 8 9 'h' can be used to define the minima depth. Grid used by the dual build 10 operation can be specified by 'grid'. 11 12 Only works with greyscale images as input and output. 13 """ 14 15 imWrk = imageMb(imIn) 16 imWrk_bin = imageMb(imIn, 1) 17 copy(imIn, imWrk) 18 addConst(imWrk, h, imWrk) 19 hierarDualBuild(imIn, imWrk, grid=grid) 20 sub(imWrk, imIn, imWrk) 21 threshold(imWrk, imWrk_bin, 1, computeMaxRange(imIn)[1]) 22 mul(imWrk_bin, imIn, imOut) 23 24 # Opening and creating images 25 im1 = imageMb('snake.png') 26 im2 = imageMb(im1) 27 28 # Computing the valued minima 29 valuedMinima(im1, im2) 30 31 im2.setPalette(rainbow) 32 im2.save("snake_valmin.png") 33
Watershed segmentation using gradient minima as markers

In this example, the watershed line is computed on the gradient image using its minima as a marker image. The resulting image is then superposed to the original to show the possibilities offered by some of the palette extra function. (script)
![]() |
| snake.png |
![]() |
| snake_watmin.png |
1 # Importing the mamba module 2 from mamba import * 3 import mambaExtra 4 import mambaComposed as mC 5 6 def watershedByGradMinima(imIn, imOut, grid=DEFAULT_GRID): 7 """ 8 Computes the watershed line of imIn using its gradient minima as a marker 9 image 10 """ 11 grad = imageMb(imIn, 8) 12 marker = imageMb(imIn, 32) 13 minbin = imageMb(imIn, 1) 14 mC.gradient(imIn, grad) 15 mC.minima(grad, minbin, grid=grid) 16 label(minbin, marker, grid=grid) 17 watershedSegment(grad, marker, grid=grid) 18 copyBytePlane(marker, 3, imOut) 19 20 # Opening and creating images 21 im1 = imageMb('snake.png') 22 im2 = imageMb(im1) 23 im3 = imageMb(im1) 24 25 # Computing the watershed by minima marker 26 watershedByGradMinima(im1, im2) 27 28 # For a better view the watershed line is superposed on the original image 29 subConst(im1, 1, im3) 30 # The watershed line is set to 255 and the basins are empty in im2. 31 logic(im3, im2, im3, "sup") 32 # a special palette is created 33 palws = mambaExtra.tagOneColorPalette(255, (255,0,0)) 34 im3.setPalette(palws) 35 im3.save("snake_watmin.png") 36
Color channels manipulations

This example shows you how to extract a specific color channel out of an image and how to reconstruct color images with three mamba images and the mix function. The colorful image was taken from wikimedia at http://commons.wikimedia.org/wiki/File:Ebenthal\_Schlosswirt\_20052010\_06.jpg (script)
![]() |
| colorful.jpg |
![]() |
| colorful_grad.png |
1 # Importing the mamba module, the mambaComposed package and the mambaExtra 2 # module 3 from mamba import * 4 import mambaExtra 5 import mambaComposed as mC 6 7 # Opening the image for each color channel (red, green and blue) 8 imRed = imageMb('colorful.jpg', rgbfilter=(1.0, 0.0, 0.0)) 9 imGreen = imageMb('colorful.jpg', rgbfilter=(0.0, 1.0, 0.0)) 10 imBlue = imageMb('colorful.jpg', rgbfilter=(0.0, 0.0, 1.0)) 11 12 # We will perform a half gradient on each color channel 13 mC.halfGradient(imRed, imRed) 14 mC.halfGradient(imGreen, imGreen) 15 mC.halfGradient(imBlue, imBlue) 16 17 # Then we recombine the three channel image into one using the 18 # mix function. This function actually returns a PIL image 19 pilim = mambaExtra.mix(imRed, imGreen, imBlue) 20 21 # We save it 22 pilim.save("colorful_grad.png") 23
Automatic thresholding using gradient

This example shows how to compute an automatic threshold value using the gradient, histogram and volume computationss. (script)
![]() |
| coffee_grains.jpg |
![]() |
| threshold_coffee_grains.jpg |
1 # Importing the mamba module and the mambaComposed package 2 # module 3 from mamba import * 4 import mambaComposed as mC 5 6 def autoThreshold(imIn, imOut): 7 """ 8 Computes an automatic threshold image using the gradient. 9 This function works well with greyscale images displaying two 10 highly contrasted sets. 11 It produces a binary image that sort of "segments" the two sets in two. 12 """ 13 14 grad = imageMb(imIn) 15 wrk = imageMb(imIn) 16 level = imageMb(imIn, 1) 17 # First the gradient is computed 18 mC.gradient(imIn, grad) 19 20 # Then the histogram 21 histo = getHistogram(imIn) 22 23 distri = [] 24 for i in range(256): 25 # First no point at looking at a particular value if there is no 26 # pixel in it. 27 if histo[i]!=0: 28 29 # for each each possible pixel value, we extract the pixels 30 # in imIn with that value 31 threshold(imIn, level, i, i) 32 # then we compute the volume of their corresponding pixels 33 # in the gradient image (normalised by the number of 34 # pixels) 35 mul(level, grad, wrk) 36 vol = computeVolume(wrk)/histo[i] 37 # The volume is added to a distribution function 38 distri.append(vol) 39 else: 40 distri.append(0) 41 42 # Finding the median of the distribution 43 sd = sum(distri) 44 sr = distri[0] 45 threshval = 0 46 while(sr<(sd/2)): 47 threshval += 1 48 sr += distri[threshval] 49 50 # Final computation 51 threshold(imIn, imOut, threshval, 255) 52 53 return threshval 54 55 im = imageMb("coffee_grains.jpg") 56 imbin = imageMb(im, 1) 57 58 # Computing the automatic threshold image 59 autoThreshold(im, imbin) 60 # And saving it 61 # The resulting image has a black band on the right because 62 # Mamba padded the original image so its width is a multiple of 64 63 # for performance reasons. This has a no impact on the quality of the result. 64 # Also notice that the result is not a very good segmentation as different 65 # coffee grains are connected in a unique set. 66 imbin.save("threshold_coffee_grains.jpg") 67 68
Particles (coffee grains) separation and counting

This example shows how to separate touching or slightly overlapping particles (coffee grains in this example)in order to measure and count them. This example also illustrates how some small enhancements may deeply increase the quality of the final result. (script)
![]() |
| coffee_grains.jpg |
![]() | ![]() |
| segmented_grains_1.png | segmented_grains_2.png |
1 # Importing the mamba module and the mambaComposed package 2 # module 3 from mamba import * 4 import mambaComposed as mC 5 6 def autoThreshold(imIn, imOut): 7 # Informations regarding this function can be found in previous 8 # example. 9 grad = imageMb(imIn) 10 wrk = imageMb(imIn) 11 level = imageMb(imIn, 1) 12 mC.gradient(imIn, grad) 13 histo = getHistogram(imIn) 14 distri = [] 15 for i in range(256): 16 if histo[i]!=0: 17 threshold(imIn, level, i, i) 18 mul(level, grad, wrk) 19 vol = computeVolume(wrk)/histo[i] 20 distri.append(vol) 21 else: 22 distri.append(0) 23 sd = sum(distri) 24 sr = distri[0] 25 threshval = 0 26 while(sr<(sd/2)): 27 threshval += 1 28 sr += distri[threshval] 29 threshold(imIn, imOut, threshval, 255) 30 return threshval 31 32 def segmentGrains1(imIn, imOut): 33 """ 34 Segments a binary image 'imIn' displaying grains using the distance 35 function and puts the result in binary image 'imOut'. 36 """ 37 imDist = imageMb(imIn, 32) 38 imDist8 = imageMb(imIn, 8) 39 imWTS = imageMb(imIn, 8) 40 41 # Segmentation of the grains with the distance function. Firstly, we 42 # compute the distance function (note the edge programming) 43 computeDistance(imIn, imDist, edge=FILLED) 44 45 # We verify (with computeRange) that the distance image is lower than 46 # 256 and we copy it into a greyscale (8-bit) image 47 computeRange(imDist) 48 copyBytePlane(imDist, 0, imDist8) 49 50 # The distance function is inverted and its valued watershed is computed 51 negate(imDist8, imDist8) 52 mC.valuedWatershed(imDist8, imWTS) 53 54 # The watershed lines are extracted (by thresholding) and subtracted from the 55 # initial image to give the first result 56 threshold(imWTS, imOut, 1, 255) 57 diff(imIn, imOut, imOut) 58 59 def segmentGrains2(imIn, imOut): 60 """ 61 Segments a binary image 'imIn' displaying grains using the distance 62 function and puts the results in greyscale image 'imOut'. 63 This segmentation uses a specific marker image and watershed segmentation 64 to obtain better results than the previous function. 65 This function returns the number of grains counted. 66 """ 67 imMarker = imageMb(imIn, 1) 68 imDist = imageMb(imIn, 32) 69 imDist8 = imageMb(imIn, 8) 70 imWTS32 = imageMb(imIn, 32) 71 imWTS = imageMb(imIn, 8) 72 73 # Segmentation of the grains with the distance function. Firstly, we 74 # compute the distance function (note the edge programming) 75 computeDistance(imIn, imDist, edge=FILLED) 76 77 # We verify (with computeRange) that the distance image is lower than 78 # 256 and we copy it into a greyscale (8-bit) image 79 computeRange(imDist) 80 copyBytePlane(imDist, 0, imDist8) 81 82 # The distance function is inverted and its valued watershed is computed 83 negate(imDist8, imDist8) 84 85 # Computing a marker image 86 mC.minima(imDist8, imMarker) 87 mC.dilate(imMarker, imMarker, 2) 88 89 # Then, we compute the watershed of the inverted distance function controlled 90 # by this marker set (note the number of connected components given by the 91 # labelling operator; they should correspond to the number of grains) 92 nb = label(imMarker, imWTS32) 93 watershedSegment(imDist8, imWTS32) 94 95 # We build the labelled catchment basins 96 copyBytePlane(imWTS32, 3, imWTS) 97 negate(imWTS, imWTS) 98 copyBytePlane(imWTS32, 0, imOut) 99 logic(imOut, imWTS, imOut, "inf") 100 101 # Then, we obtain the final (and better) result. Each grain is labelled 102 convert(imIn, imWTS) 103 logic(imOut, imWTS, imOut, "inf") 104 105 return nb 106 107 # Loading the initial image and creating some working images 108 im = imageMb("coffee_grains.jpg") 109 imthresh = imageMb(im, 1) 110 111 # Using the function describes in exampleA1.py we compute the automatic 112 # threshold of our initial image 113 autoThreshold(im, imthresh) 114 # A bit of tidying 115 mC.open(imthresh, imthresh, 2) 116 negate(imthresh, imthresh) 117 118 # Computing the first segmentation of the coffee grains 119 imSeg1 = imageMb(im, 1) 120 segmentGrains1(imthresh, imSeg1) 121 # We store this result 122 imSeg1.save("segmented_grains_1.png") 123 124 # This first result is not perfect as some grains are badly segmented. This 125 # over-segmentation is due to parity problems affecting some maxima of the 126 # distance function. In order to cope with these defects, we use a marker 127 # controlled watershed of the inverted distance function. The markers are 128 # generated by a dilation of the minima of the inverted distance function 129 130 # Computing the second segmentation of the coffee grains 131 imSeg2 = imageMb(im, 8) 132 nb = segmentGrains2(imthresh, imSeg2) 133 # We store this result 134 # The palette can be changed before saving the result 135 imSeg2.setPalette(patchwork) 136 imSeg2.save("segmented_grains_2.png") 137 print "number of grains :", nb 138 # The result shoulb be 50, however due to the black band on the right 139 # the function counts 51 coffee grains. 140 141
Color image segmentation with quasi-distance of the gradient

This example illustrates the use of the quasi-distance operator applied on a color gradient to segment a scene. It also uses the Python Imaging Library (PIL) and the Mamba split operator to extract the three channels of a color image. The gallery image is coming from the EC Funded CAVIAR (Context Aware Vision using Image-based Active Recognition) project/IST 2001 37540, found at URL: http://homepages.inf.ed.ac.uk/rbf/CAVIAR/. (script)
![]() |
| gallery.png |
![]() | ![]() |
| binary_segmentation.png | segmented_gallery.png |
1 # Importing the Image PIL module, mamba module, the mambaComposed package and 2 # the mambaExtra module 3 import Image 4 from mamba import * 5 import mambaComposed as mC 6 import mambaExtra as mE 7 8 # Opening the image (PIL format) and splitting it into three color channels 9 pilim = Image.open('gallery.png') 10 imRed = imageMb(pilim.size[0], pilim.size[1], 8) 11 imGreen = imageMb(imRed) 12 imBlue = imageMb(imRed) 13 mE.split(pilim, imRed, imGreen, imBlue) 14 15 # We will perform a thick gradient on each color channel (contours in original 16 # picture are more or less fuzzy) and we add all these gradients 17 gradIm = imageMb(imRed) 18 imWrk1 = imageMb(imRed) 19 gradIm.reset() 20 mC.gradient(imRed, imWrk1, 2) 21 add(imWrk1, gradIm, gradIm) 22 mC.gradient(imGreen, imWrk1, 2) 23 add(imWrk1, gradIm, gradIm) 24 mC.gradient(imBlue, imWrk1, 2) 25 add(imWrk1, gradIm, gradIm) 26 27 # Then we invert the gradient image and we compute its quasi-distance 28 qDist = imageMb(gradIm, 32) 29 negate(gradIm, gradIm) 30 mC.quasiDistance(gradIm, imWrk1, qDist) 31 32 # The maxima of the quasi-distance are extracted and filtered (too close maxima, 33 # less than 6 pixels apart, are merged) 34 imWrk2 = imageMb(imRed) 35 imMark = imageMb(gradIm, 1) 36 copyBytePlane(qDist, 0, imWrk1) 37 subConst(imWrk1, 3, imWrk2) 38 mC.build(imWrk1, imWrk2) 39 mC.maxima(imWrk2, imMark) 40 41 # The marker-controlled watershed of the gradient is performed 42 imWts = imageMb(gradIm) 43 label(imMark, qDist) 44 negate(gradIm, gradIm) 45 watershedSegment(gradIm, qDist) 46 copyBytePlane(qDist, 3, imWts) 47 48 # The segmented binary and color image are stored 49 logic(imRed, imWts, imRed, "sup") 50 logic(imGreen, imWts, imGreen, "sup") 51 logic(imBlue, imWts, imBlue, "sup") 52 pilim = mE.mix(imRed, imGreen, imBlue) 53 pilim.save('segmented_gallery.png') 54 negate(imWts, imWts) 55 imWts.save('binary_segmentation.png') 56 57 58
Road segmentation in realtime condition

This example demonstrates the realtime capabilities offered by the mambaRealtime module with a very specific algorithm of road segmentation This algorithm extracts the road and colorizes it. This is a very simple algorithm and as you will be able to see if you run it, the segmentation is not perfect and depends greatly on the "quality" of the road texture. Passing from shade to sun light also proves to be difficult. However, the algorithm manages to stay "on track". The video is a small excerpt (starting at 6:11) of a rally race onboard video recorded by the official wrc organisation you can find at http://www.youtube.com/watch?v=Z9X03IJiLmo. The small excerpt can be found in the examples directory of the mamba sources. (script)
![]() |
| road_seg_snapshot.png |
1 # Importing mamba and associates 2 from mamba import * 3 from mambaComposed import * 4 from mambaDraw import * 5 from mambaExtra import * 6 # Importing the realtime module 7 from mambaRealtime import * 8 9 import time 10 11 def roadSegmentation(imIn, imOut, gradsize=1, erosize=10, draw=0, coefth=0.2): 12 """ 13 A road segmentation algorithm. 14 This algorithm uses the im_marker 32-bit image to remember previous 15 results from call to call. 16 """ 17 global im_marker, w, h 18 grad = imageMb(imIn, 8) 19 pre_mark = imageMb(imIn, 8) 20 marker_n = imageMb(imIn, 1) 21 marker_n1 = imageMb(imIn, 1) 22 infi = imageMb(imIn, 1) 23 supi = imageMb(imIn, 1) 24 wtshed = imageMb(imIn, 8) 25 basins = imageMb(imIn, 8) 26 27 # We first copy the lower byte of the marker image for future use. 28 copyBytePlane(im_marker, 0, pre_mark) 29 convert(pre_mark, marker_n) 30 # Performing a watershed segmentation on the gradient using the 31 # marker image for the initial wells. 32 gradient(imIn, grad, gradsize) 33 watershedSegment(grad, im_marker) 34 # Extracting the watershed line and basins. 35 copyBytePlane(im_marker, 3, wtshed) 36 copyBytePlane(im_marker, 0, basins) 37 # The next lines are here to compute what we display. 38 # If draw is 1, basins is displayed which means all the road 39 # will appear in red. 40 # Otherwise, only the road edge will be drawn in red. 41 subConst(imIn, 1, imOut) 42 if draw==1: 43 logic(imOut, basins, imOut, "sup") 44 else: 45 logic(imOut, wtshed, imOut, "sup") 46 # We then compute the next marker image. 47 im_marker.reset() 48 # First we extract the basin corresponding to the road as it will 49 # serve as the well in the next segmentation. 50 # The basin is then eroded to shrink its size to prevent it 51 # from being larger than the road it will have to segment 52 # in next call. 53 convert(basins, marker_n1) 54 largeHexagonalErode(marker_n1, marker_n1, erosize) 55 # The following computation is here to ensure the new well is not 56 # too different than the previous one. 57 logic(marker_n, marker_n1, infi, "inf") 58 logic(marker_n, marker_n1, supi, "sup") 59 vinf = computeVolume(infi) 60 vsup = computeVolume(supi) 61 if float(vinf)<coefth*vsup: 62 # if ok the marker image is rebuilt using it. 63 # The outside marker is generated by inverting the road marker 64 # and by eroding it (5 times the size of the erosion used for 65 # the inner one). 66 negate(marker_n1, infi) 67 convertByMask(marker_n1, basins, 0, 255) 68 largeHexagonalErode(infi, infi, erosize*5) 69 add(basins, infi, basins) 70 copyBytePlane(basins, 0, im_marker) 71 else: 72 # If too different, we reuse the older one. 73 copyBytePlane(pre_mark, 0, im_marker) 74 75 # Launching the realtime acquisition using the video "excerpt_rally.mp4" as 76 # the source. 77 launchRealtime("excerpt_rally.mp4", AVC) 78 79 # The video has a specific dimension that we need to know to create our 80 # marker image. 81 w,h = getSizeRealtime() 82 83 # the marker image is used to initialise the watershed segmentation wells 84 # Two markers : the road (255) that is assumed to be at the center of the 85 # video at the beginning and the rest of the image (not the road (1), which is 86 # assumed to be at the border of the video at the beginning (of course in this 87 # example we can see the car hood so there is no road at the bottom). 88 im_marker = imageMb(w,h,32) 89 drawBox(im_marker, [15,15,w-15,h-15], 1) 90 drawSquare(im_marker, [w/2-15,h/2-15,w/2+15,h/2+15], 255) 91 92 # Only the road will be output in color (red). 93 pal = tagOneColorPalette(255, (255,0,0)) 94 setPaletteRealtime(pal) 95 96 # Launching the processing. 97 setProcessRealtime(roadSegmentation, INSTANT, gradsize=2, erosize=10, draw=1, coefth=0.2) 98 99 # Taking a snapshot picture of the result. 100 time.sleep(0.2) 101 takePictureRealtime("road_seg_snapshot.png") 102 time.sleep(1) 103 104




















