Contents
The mango.image module contains image processing and image analysis functions and classes.
The sobel() function calculates a gradient-magnitude approximation for a specified mango.Dds image:
#!/usr/bin/env python
import scipy as sp
import scipy.ndimage
import mango.data
import mango.image
import mango.io
# Create a checker-board Dds image
ddsImg = mango.data.createCheckerDds(shape=(64,512,512), checkShape=(64,64,64), dtype="uint16")
# Replace the *white* checks with value 40000 and the
# *black* checks with 20000.
msk = sp.where(ddsImg.asarray() == 1)
ddsImg.asarray()[:] = sp.where(ddsImg.asarray() == 1, 40000, 20000)
# Sobel filter to get the gradient-magnitude image.
ddsSbl = mango.image.sobel(ddsImg)
# Write both images to file.
mango.io.writeDds("tomoImg.nc", ddsImg)
mango.io.writeDds("tomoSbl.nc", ddsSbl)
By converting mango.Dds objects to numpy.ndarray one can take advantage of the image processing routines implemented in scipy.ndimage. The following script defines the ndimageSobel function to calculate the gradient magnitude from the x, y and z gradient-vector components returned by the scipy.ndimage.filters.sobel() function:
#!/usr/bin/env python
import scipy as sp
import scipy.ndimage
import cProfile as profile
import mango.data
import mango.image
import mango.io
def ndimageSobel(array):
"""
Returns Sobel gradient-magnitude filtered array.
"""
sobelArray = sp.ndimage.sobel(array, axis=0)
sobelArray *= sobelArray
for a in range(1,3):
tmp = sp.ndimage.sobel(array, axis=a)
sobelArray += tmp*tmp
return sp.sqrt(sobelArray)
# Create a checker-board Dds image
ddsImg = mango.data.createCheckerDds(shape=(128,512,512), checkShape=(64,64,64), dtype="float64")
# Replace the *white* checks with value 40000 and the
# *black* checks with 20000.
ddsImg.asarray()[:] = sp.where(ddsImg.asarray() == 1, 40000, 20000)
# Adjust halo size.
ddsImg = mango.copy(ddsImg, halo=1)
# Sobel filter using mango.image.sobel().
ddsSblMango = None
print("=======================mango.image.sobel=============================")
profile.run("ddsSblMango = mango.image.sobel(ddsImg)")
# Convert Dds to numpy.ndarray
ddsImg.mirrorOuterLayersToBorder(True)
ddsImg.updateOverlapRegions()
ddsAsArray = ddsImg.asarray()
# Sobel filter using scipy.ndimage.sobel().
print("\n\n\n=======================scipy.ndimage.sobel========================")
profile.run("sobelArray=ndimageSobel(ddsAsArray)")
# Copy the numpy.ndimage back into a Dds object
ddsSblScipy = mango.empty_like(ddsImg)
ddsSblScipy.asarray()[:] = sobelArray
# Write three images to file.
mango.io.writeDds("tomo_floatImg.nc", mango.copy(ddsImg, mtype="tomo_float"))
mango.io.writeDds("tomo_floatSblScipy.nc", mango.copy(ddsSblScipy, mtype="tomo_float"))
mango.io.writeDds("tomo_floatSblMango.nc", mango.copy(ddsSblMango, mtype="tomo_float"))
The script performs profiling (profile) on the Sobel filtering calls and the following output shows the runtime data for the two implementations:
=======================mango.image.sobel=============================
14 function calls in 1.707 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 1.707 1.707 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 _dds_open_filters.py:12(__init__)
1 0.000 0.000 0.000 0.000 _dds_open_filters.py:16(upsizeHalo)
1 0.005 0.005 0.005 0.005 _dds_open_filters.py:34(initialiseHalo)
1 1.702 1.702 1.707 1.707 _dds_open_filters.py:51(__call__)
1 0.000 0.000 1.707 1.707 _dds_open_filters.py:88(sobel)
1 0.000 0.000 0.000 0.000 _methods.py:31(_any)
1 0.000 0.000 0.000 0.000 fromnumeric.py:1762(any)
1 0.000 0.000 0.000 0.000 numeric.py:462(asanyarray)
1 0.000 0.000 0.000 0.000 {method 'any' of 'numpy.ndarray' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {method 'lower' of 'str' objects}
1 0.000 0.000 0.000 0.000 {method 'reduce' of 'numpy.ufunc' objects}
1 0.000 0.000 0.000 0.000 {numpy.core.multiarray.array}
=======================scipy.ndimage.sobel========================
191 function calls in 2.381 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.024 0.024 2.381 2.381 <string>:1(<module>)
1 0.000 0.000 0.003 0.003 _methods.py:31(_any)
9 0.000 0.000 0.000 0.000 _ni_support.py:38(_extend_mode_to_code)
12 0.000 0.000 0.000 0.000 _ni_support.py:70(_get_output)
12 0.000 0.000 0.000 0.000 _ni_support.py:90(_check_axis)
9 0.000 0.000 1.769 0.197 filters.py:109(correlate1d)
3 0.000 0.000 1.769 0.590 filters.py:328(sobel)
1 0.000 0.000 0.003 0.003 fromnumeric.py:1762(any)
31 0.000 0.000 0.000 0.000 numeric.py:392(asarray)
2 0.000 0.000 0.000 0.000 numeric.py:462(asanyarray)
1 0.109 0.109 0.291 0.291 scimath.py:170(sqrt)
1 0.049 0.049 0.182 0.182 scimath.py:92(_fix_real_lt_zero)
1 0.297 0.297 2.357 2.357 sobel_profile.py:10(ndimageSobel)
1 0.085 0.085 0.085 0.085 type_check.py:141(imag)
1 0.044 0.044 0.129 0.129 type_check.py:207(isreal)
9 0.000 0.000 0.000 0.000 type_check.py:237(iscomplexobj)
9 0.000 0.000 0.000 0.000 {issubclass}
27 0.000 0.000 0.000 0.000 {len}
1 0.000 0.000 0.003 0.003 {method 'any' of 'numpy.ndarray' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.003 0.003 0.003 0.003 {method 'reduce' of 'numpy.ufunc' objects}
33 0.000 0.000 0.000 0.000 {numpy.core.multiarray.array}
12 0.000 0.000 0.000 0.000 {numpy.core.multiarray.zeros}
3 0.000 0.000 0.000 0.000 {range}
9 1.768 0.196 1.768 0.196 {scipy.ndimage._nd_image.correlate1d}