Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - Calculate histogram of image

I'm working on teaching myself the basics of computerized image processing, and I am teaching myself Python at the same time.

Given an image x of dimensions 2048x1354 with 3 channels, efficiently calculate the histogram of the pixel intensities.

import numpy as np, cv2 as cv

img = cv.imread("image.jpg")
bins = np.zeros(256, np.int32)

for i in range(0, img.shape[0]):
    for j in range(0, img.shape[1]):

        intensity = 0
        for k in range(0, len(img[i][j])):
            intensity += img[i][j][k]

        bins[intensity/3] += 1

print bins

My issue is that this code runs pretty slowly, as in ~30 seconds. How can I speed this up and be more Pythonic?

like image 348
Jason Avatar asked Mar 03 '14 22:03

Jason


People also ask

How do you find the histogram of an image?

Histogram is based on the frequency of luminance in the image. The luminance is computed for each pixel with the formula 0.2126*R+0.7152*G+0.0722*B (ITU BT. 709).

How do I create a histogram from a photo?

To create an image histogram, use the imhist function. This function creates a histogram plot by making n equally spaced bins, each representing a range of data values. It then calculates the number of pixels within each range. The following example displays an image of grains of rice and a histogram based on 64 bins.


1 Answers

You can use newer OpenCV python interface which natively uses numpy arrays and plot the histogram of the pixel intensities using matplotlib hist. It takes less than second on my computer.

import matplotlib.pyplot as plt
import cv2

im = cv2.imread('image.jpg')
# calculate mean value from RGB channels and flatten to 1D array
vals = im.mean(axis=2).flatten()
# plot histogram with 255 bins
b, bins, patches = plt.hist(vals, 255)
plt.xlim([0,255])
plt.show()

enter image description here

UPDATE: Above specified number of bins not always provide desired result as min and max are calculated from actual values. Moreover, counts for values 254 and 255 are summed in last bin. Here is updated code which always plot histogram correctly with bars centered on values 0..255

import numpy as np
import matplotlib.pyplot as plt
import cv2

# read image
im = cv2.imread('image.jpg')
# calculate mean value from RGB channels and flatten to 1D array
vals = im.mean(axis=2).flatten()
# calculate histogram
counts, bins = np.histogram(vals, range(257))
# plot histogram centered on values 0..255
plt.bar(bins[:-1] - 0.5, counts, width=1, edgecolor='none')
plt.xlim([-0.5, 255.5])
plt.show()

enter image description here

like image 63
Ondro Avatar answered Oct 19 '22 08:10

Ondro