xnok
xnok

Reputation: 329

How to calculate the mean pixel value inside an elipse area

I would like to compare the difference of pixel intensities inside an area and for such task i am trying to use matplotlib to draw an elipse to a tiff format file. What i would like to do is draw two elipses to distinguish the eye from the sclera, by drawing two elipses to separate both and obtain the mean values from both regions, for example:

enter image description here

I'd like to calculate the mean values inside the first elipse area and the second area separately, to observe the difference between those two areas.

This is the example with the elipses generated that i would like to calculate the means from inside both areas:

Image with elipses

Tiff image plot for coordinates visualization:

enter image description here

Code used to generate elipses:

import matplotlib.image
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
figure, ax = plt.subplots(1)
ax.imshow(img)
ax.add_patch(mpatches.Ellipse((30, 24),15,8, edgecolor='black', facecolor="none"))
ax.add_patch(mpatches.Ellipse((30, 24),30,16, edgecolor='black', facecolor="none"))
img_PIL.save(r'C:/Users/image/eye.tif')

Upvotes: 0

Views: 743

Answers (1)

Derek Eden
Derek Eden

Reputation: 4618

you can define the equation of an ellipse and use it as a mask to see whether or not the tiff array elements are within a defined ellipse or not, if so then avg them, like this:

import numpy as np
import matplotlib.pyplot as plt
plt.ion()

#read/define the tiff array
img_array = np.random.rand(101,101)
plt.contourf(img_array)

tiff array

#define ellipse parameters and equation (google equation for ellipse)
h = 51
k = 51
a = 10
b = 30

def _in_ellipse(x, y, h, k, a, b):
    z = ((x-h)**2)/a**2 + ((y-k)**2)/b**2
    if z < 1: #the equation is ^ this expression == 1
        return True
    else:
        return False

#vectorize for using on arrays
in_ellipse = np.vectorize(_in_ellipse)

#make a True mask within ellipse
mask = in_ellipse(*np.indices(img_array.shape), h,k,a,b)
plt.contourf(mask)

mask

plt.contourf(np.where(mask, img_array, np.nan))

masked tiff array

avg = np.nanmean(np.where(mask, img_array, np.nan))

you can also add a threshold keyword in there if you want to tweak how the mask behaves around the circumference of the ellipse

def _in_ellipse(x, y, h, k, a, b, thresh=1):
    z = ((x-h)**2)/a**2 + ((y-k)**2)/b**2
    if z < thresh:
        return True
    else:
        return False

in_ellipse = np.vectorize(_in_ellipse)
mask = in_ellipse(*np.indices(img_array.shape), h,k,a,b,1.02)

threshold

there are of course more refined ways of doing this, perhaps an opencv approach, but this is as bare bones as it gets

Upvotes: 3

Related Questions