Sum of the intensity values of all pixels in image segment

Viewed 2059

According to the formula that is shown below, I need to calculate an average threshold value by dividing the sum of intensity values in segment on the number of pixels in segment.

formula

where Xi' is a binary mask (structure_mask), |Xi'| is a number of ones (xi_modulus). I(x,y) is a pixel intensity.

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
...
...
structure_mask = np.logical_and(magnitude_mask, intensity_mask).astype(np.uint8)
xi_modulus = np.count_nonzero(structure_mask.all(axis=2))
intensity_sum  # = ??

How to calculate the sum of intensities with numpy?

EDITED: Based on the @HansHirse's answer I've tried to do the following:

thresh_val = np.mean(img_gray[structure_mask])

And I've got IndexError: too many indices for array

Where structure_mask was of shape (1066, 1600,1) and img_gray - (1066,1600)

UPDATED: Just a dummy mistake. Shape mismatch was fixed by proper indexing

structure_mask = np.logical_and(magnitude_mask, intensity_mask)[:, :, 0]
2 Answers

Using NumPy's boolean array indexing, you can easily access the desired values. You just need to pay attention, that your mask (or segment) is of NumPy's bool_ type.

Let's see this short code snippet, where I compare the mean obtained from np.mean with the one explicitly calculated by the given formula:

import cv2
import numpy as np

# Some artificial image
img = np.uint8(255 * np.tile(np.linspace(1, 0, 400), (400, 1)))
cv2.imshow('img', img)

# Some mask (or segment)
mask = np.zeros((400, 400), np.uint8)
mask[10:390, 10:30] = 255
cv2.imshow('mask', mask)

# Convert mask to bool_ type
mask = np.bool_(mask)

# Calculate mean by NumPy's mean
mean = np.mean(img[mask])
print('mean by np.mean:\n', mean)

# Calculate mean explicitly by given formula
mean = np.sum(img[mask]) / np.count_nonzero(mask)
print('mean by formula:\n', mean)

cv2.waitKey(0)
cv2.destroyAllWindows()

Outputs (images omitted here):

mean by np.mean:
 242.05
mean by formula:
 242.05

Hope that helps!

numpy supports logical indexes so

magnitude_mask[intensity_mask].mean()

will give you what you want.

if you insist on having the sum use

magnitude_mask[intensity_mask].sum()
Related