Я попробовал это, используя метод threshold_otsu()
из skimage и массив Numpy.Я не знаю, есть ли более быстрые способы - лыжный маг обычно довольно хорошо оптимизирован.Если кто-то еще захочет взять мои образцы данных и попробовать другие идеи на них, пожалуйста, не стесняйтесь - хотя с одного сбора взимается плата за обслуживание; -)
#!/usr/bin/env python3
import cv2
import numpy as np
import numpy.ma as ma
from skimage.filters import threshold_otsu
# Set up some repeatable test data, 4 blocks 100x100 pixels each of random normal np.uint8s centred on 32, 64, 160,192
np.random.seed(42)
a=np.random.normal(size = (100,100), loc = 32,scale=10).astype(np.uint8)
b=np.random.normal(size = (100,100), loc = 64,scale=10).astype(np.uint8)
c=np.random.normal(size = (100,100), loc = 160,scale=10).astype(np.uint8)
d=np.random.normal(size = (100,100), loc = 192,scale=10).astype(np.uint8)
# Stack (concatenate) the 4 squares horizontally across the page
im = np.hstack((a,b,c,d))
# Next line is just for debug
cv2.imwrite('start.png',im)
Это дает нам следующее:
![enter image description here](https://i.stack.imgur.com/3IOa2.png)
# Now make a mask revealing only left half of image, centred on 32 and 64
mask=np.zeros((100,400))
mask[:,200:]=1
masked = ma.masked_array(im,mask)
print(threshold_otsu(masked.compressed())) # Prints 47
# Now do same revealing only right half of image, centred on 160 and 192
masked = ma.masked_array(im,1-mask)
print(threshold_otsu(masked.compressed())) # Prints 175
Гистограмма тестовых данных выглядит следующим образом, ось x равна 0..255
![enter image description here](https://i.stack.imgur.com/fkTQe.png)
Адаптируясь к вашим собственным образцам данных, я получаю это:
#!/usr/bin/env python3
import cv2
import numpy as np
import numpy.ma as ma
from skimage.filters import threshold_otsu
# Load images
im = cv2.imread('eye.tif', cv2.IMREAD_UNCHANGED)
mask = cv2.imread('mask.tif', cv2.IMREAD_UNCHANGED)
# Calculate Otsu threshold on entire image
print(threshold_otsu(im)) # prints 130
# Now do same for masked image
masked = ma.masked_array(im,mask>0)
print(threshold_otsu(masked.compressed())). # prints 124