Skip to content

HistogramBarChart

Repository source: HistogramBarChart

Other languages

See (Cxx)

Question

If you have a question about this example, please use the VTK Discourse Forum

Code

HistogramBarChart.py

#!/usr/bin/env python3


# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkIntArray
from vtkmodules.vtkCommonDataModel import vtkDataObject
from vtkmodules.vtkIOImage import vtkImageReader2Factory
from vtkmodules.vtkImagingCore import vtkImageExtractComponents
from vtkmodules.vtkImagingStatistics import vtkImageAccumulate
from vtkmodules.vtkRenderingAnnotation import vtkBarChartActor
from vtkmodules.vtkRenderingCore import (
    vtkRenderer,
    vtkRenderWindow,
    vtkRenderWindowInteractor
)


def get_program_parameters():
    import argparse
    description = 'Histogram Bar Chart.'
    epilogue = '''
    '''
    parser = argparse.ArgumentParser(description=description, epilog=epilogue,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('filename', help='Pileated.jpg.')
    parser.add_argument('-i', '--ignore_zero', action='store_true', help='Ignore zero.')
    args = parser.parse_args()
    return args.filename, args.ignore_zero


def main():
    colors = vtkNamedColors()

    file_name, ignore_zero = get_program_parameters()

    # Read the image.
    reader = vtkImageReader2Factory().CreateImageReader2(file_name)
    reader.file_name = file_name

    num_components = reader.update().output.number_of_scalar_components
    print(f'Number of components {num_components}')
    if num_components > 3:
        print(f'Error: cannot process an image with {num_components} components!')
        return

    num_tuples = 54

    histogram_colors = ((1, 0, 0), (0, 1, 0), (0, 0, 1))
    red_frequencies = vtkIntArray(number_of_components=1, number_of_tuples=num_tuples)
    green_frequencies = vtkIntArray(number_of_components=1, number_of_tuples=num_tuples)
    blue_frequencies = vtkIntArray(number_of_components=1, number_of_tuples=num_tuples)

    # Process the image, extracting and bar charting a histogram for each component.
    for i in range(0, num_components):
        extract = vtkImageExtractComponents(components=i)

        histogram = vtkImageAccumulate(component_extent=(1, num_tuples + 1, 0, 0, 0, 0),
                                       component_origin=(0, 0, 0),
                                       component_spacing=(1, 0, 0),
                                       ignore_zero=ignore_zero)
        reader >> extract >> histogram
        output = histogram.update().output

        array = vtkIntArray(number_of_components=1, number_of_tuples=0)
        current_array = vtkIntArray(number_of_components=1, number_of_tuples=num_tuples)
        for j in range(0, num_tuples):
            frequency = int(output.point_data.scalars.GetTuple1(j))
            print(j, frequency)
            array.InsertTuple1(j, frequency)

        current_array.SetVoidArray(array, num_tuples, 1)

        if i == 0:
            red_frequencies.DeepCopy(current_array)
        elif i == 1:
            green_frequencies.DeepCopy(current_array)
        else:
            blue_frequencies.DeepCopy(current_array)

    data_object = vtkDataObject()
    if num_components == 1:
        data_object.field_data.AddArray(red_frequencies)
    else:
        rgb = list()
        all_frequencies = vtkIntArray(number_of_components=1)
        if num_components == 2:
            rgb.append(red_frequencies)
            rgb.append(green_frequencies)
        else:
            rgb.append(red_frequencies)
            rgb.append(green_frequencies)
            rgb.append(blue_frequencies)

        for i in range(0, num_tuples):
            for j in range(0, num_components):
                all_frequencies.InsertNextTuple1(rgb[j].GetTuple1(i))

        data_object.GetFieldData().AddArray(all_frequencies)

    # Create a vtkBarChartActor.
    bar_chart = vtkBarChartActor(input=data_object, title='Histogram', legend_visibility=False, label_visibility=False)
    bar_chart.GetPositionCoordinate().SetValue(0.15, 0.05, 0.0)
    bar_chart.GetPosition2Coordinate().SetValue(0.95, 0.85, 0.0)

    bar_chart.GetProperty().SetColor(1, 1, 1)

    # If the number of entries is not set to the number of data array
    # tuples, the bar chart actor will crash. The crash occurs whether the legend
    # and or labels are visible or not.
    bar_chart.GetLegendActor().SetNumberOfEntries(
        data_object.GetFieldData().GetArray(0).GetNumberOfTuples())

    count = 0
    for i in range(0, num_tuples):
        for j in range(0, num_components):
            bar_chart.SetBarColor(count, histogram_colors[j])
            count += 1

    # Visualize the histogram(s)
    named_colors = vtkNamedColors()

    renderer = vtkRenderer(background=named_colors.GetColor3d('SlateGray'))
    renderer.AddActor(bar_chart)

    render_window = vtkRenderWindow(size=(640, 480), window_name='HistogramBarChart')
    render_window.AddRenderer(renderer)

    interactor = vtkRenderWindowInteractor()
    interactor.render_window = render_window

    render_window.Render()
    # Initialize the event loop and then start it.
    interactor.Initialize()
    interactor.Start()


if __name__ == '__main__':
    main()