简体   繁体   English

大津门槛内膜

[英]Otsu thresholding inside mask

I'm working with Python and trying to do Otsu thresholding on an image but only inside the mask (yes, I have an image and a mask image). 我正在使用Python并尝试对图像进行Otsu阈值处理,但仅在蒙版内部进行(是的,我有一个图像和一个蒙版图像)。 It means less pixel on the image will be included in the histogram for calculating the Otsu threshold. 这意味着图像中较少的像素将包含在直方图中以计算Otsu阈值。

I'm currently using the cv2.threshold function without the mask image and have no idea how to do this kind of job. 我目前正在使用没有遮罩图像的cv2.threshold函数,并且不知道如何执行此类工作。

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

Since this function also incorporates the pixels outside the mask, I think it will give a less accurate threshold. 由于此功能还合并了遮罩外部的像素,因此我认为其阈值将不太准确。

This is the example of the image and its mask: 这是图像及其遮罩的示例:

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

Hope there is a OpenCV or other lib function to do it easily (and also with fast computing), but any kind of help will be appreciated. 希望有一个OpenCV或其他lib函数可以轻松实现它(以及快速计算),但是希望获得任何帮助。

I had a try at this using the threshold_otsu() method from skimage and a Numpy masked array. 我尝试使用skimagethreshold_otsu()方法和一个Numpy掩码数组进行了尝试。 I don't know if there are faster ways - the skimage is normally pretty well optimised. 我不知道是否有更快的方法-skimage通常经过很好的优化。 If anyone else wants to take my sample data and try other ideas on it, please feel free - although there is a service charge of one upvote ;-) 如果还有其他人想获取我的样本数据并尝试其他想法,请放心使用-尽管需要支付一笔费用;-)

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

That gives us this: 这给了我们这个:

在此处输入图片说明

# 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

The histogram of the test data looks like this, x-axis is 0..255 测试数据的直方图如下所示,x轴为0..255

在此处输入图片说明


Adapting to your own sample data, I get this: 根据您自己的样本数据,我得到以下信息:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM