Simple image math and saturation arithmetic¶
This example demonstrates how to do simple mathematical operations on images. All the operations are saturating, i.e. out-of-bounds results are clamped to the allowable value range of the pixel data type instead of wrapping around
Some operations support input images of different size. In this case, out-of-bounds pixels are taken from the nearest valid location in the edge of the image. As a result, one can e.g. multiply each slice of a 3D image by a 2D image. This process is often used to mask bad regions away (e.g. regions outside of the completely reconstructed cylinder in a tomographic image).
def math(): """ Demonstrates use of simple image math. """ # Add images img = pi.read(input_file()) pi.add(img, img) pi.writeraw(img, output_file('head_added_to_itself')) # Subtract images img = pi.read(input_file()) pi.subtract(img, img) pi.writeraw(img, output_file('head_subtracted_from_itself')) # Add constant # The math operations are saturating, i.e. if the result of an operation is out of # bounds that can be represented with pixel data type, the value is clipped # to the bounds. # For example, # 200 + 200 = 255 for uint8 image, # 200 + 200 = 400 for uint16 image, # 2*30000 = 65535 for uint16 image, # etc. img = pi.read(input_file()) pi.add(img, 65400) # Add large value to partially saturate 16-bit range pi.writeraw(img, output_file('head_saturated')) # Do you have a 2D mask that you would like to apply to # all slices of a 3D stack? # No problem, just specify True for 'allow dimension broadcast' parameter: img = pi.read(input_file()) # Create mask whose size is the same than the size of the original but it contains # only one slice. Then draw a circle into it, with color 1. mask = pi.newimage(img.get_data_type(), img.get_width(), img.get_height()) pi.sphere(mask, [img.get_width() / 2, img.get_height() / 2, 0], img.get_width() / 4, 1) pi.writetif(mask, output_file('mask')) pi.multiply(img, mask, True) pi.writetif(img, output_file('head_masked'))