Search code examples
numpyopencvimage-processinghistogrampython-imageio

How to create histograms in pure Python?


I know you can just use numpy.histogram(), and that will create the histogram for a respective image. What I don't understand is, how to create histograms without using that function.

Everytime I try to use sample code, it has issues with packages especially OpenCV.

Is there anyway to create histograms without using OpenCV or skimage, maybe using something like imageio?


Solution

  • You'd need to implement the histogram calculation using lists, dictionaries or any other standard Python data structure, if you explicitly don't want to have NumPy as some kind of import. For image histograms, you basically need to count intensity occurences, most of the time these are values in the range of 0 ... 255 (when dealing with 8-bit images). So, iterate all channels of an image, iterate all pixels within that channel, and increment the corresponding "counter" for the observed intensity value of that pixel.

    For example, that'd be a solution:

    import imageio
    
    # Read image via imageio; get dimensions (width, height)
    img = imageio.imread('path/to/your/image.png')
    h, w = img.shape[:2]
    
    # Dictionary (or any other data structure) to store histograms
    hist = {
        'R': [0 for i in range(256)],
        'G': [0 for j in range(256)],
        'B': [0 for k in range(256)]
    }
    
    # Iterate every pixel and increment corresponding histogram element
    for i, c in enumerate(['R', 'G', 'B']):
        for x in range(w):
            for y in range(h):
                hist[c][img[y, x, i]] += 1
    

    I added some NumPy code to test for equality:

    import numpy as np
    
    # Calculate histograms using NumPy
    hist_np = {
        'R': list(np.histogram(img[:, :, 0], bins=range(257))[0]),
        'G': list(np.histogram(img[:, :, 1], bins=range(257))[0]),
        'B': list(np.histogram(img[:, :, 2], bins=range(257))[0])
    }
    
    # Comparisons
    print(hist['R'] == hist_np['R'])
    print(hist['G'] == hist_np['G'])
    print(hist['B'] == hist_np['B'])
    

    And, the corresponding output in fact is:

    True
    True
    True
    
    ----------------------------------------
    System information
    ----------------------------------------
    Platform:      Windows-10-10.0.16299-SP0
    Python:        3.9.1
    imageio:       2.9.0
    NumPy:         1.20.1
    ----------------------------------------