大津门槛内膜

时间:2019-06-11 01:30:58

标签: python numpy opencv image-processing masking

我正在使用Python并尝试对图像进行Otsu阈值处理,但仅在蒙版内部进行(是的,我有一个图像和一个蒙版图像)。这意味着图像中较少的像素将包含在直方图中以计算Otsu阈值。

我目前正在使用cv2.threshold函数,但没有遮罩图像,也不知道如何进行此类工作。

ret, OtsuMat = cv2.threshold(GaborMat, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

由于此功能还合并了遮罩外部的像素,因此我认为其阈值将不太准确。

这是图像及其遮罩的示例:

https://drive.google.com/drive/folders/1p8JMhncJs19oOWO9RdkWuEADVGqE-gzQ?usp=sharing

希望有一个OpenCV或其他lib函数可以很容易地做到这一点(以及快速计算),但是任何形式的帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

我尝试使用 skimage 中的threshold_otsu()方法和Numpy蒙版数组对此进行了尝试。我不知道是否有更快的方法- skimage 通常进行了很好的优化。如果有人想获取我的样本数据并尝试其他想法,请放心-尽管需要支付一笔费用;-)

#!/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

# 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


根据您自己的样本数据,我得到了:

#!/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