我想将图像处理从Image J(Fiji)转移到Python。
在图像J中,我将图像分成HSB,然后在B通道上使用Moments Auto-threshold。在Python上,我希望具有阈值t的值,从该值开始进行分割。我找不到关于该主题的任何帮助或代码,所以我在这里。
从论文“保持瞬间阈值:一种新方法,蔡”(here)中,我做到了:
import numpy as np
import cv2
import skimage
from skimage import io
img = io.imread("C:\\Users\\Image.tif")
hsv_img = cv2.cvtColor(filt_img, cv2.COLOR_RGB2HSV)
H, S, B = cv2.split(img) # spliting the image into HSB
B_histo = skimage.exposure.histogram (B) # making the histogram
pix_sum = B.shape[0]*B.shape[1] # calculating the sum of the pixels
#from the paper, calculating the 4 first odrers m0, m1, m2, m3 to get to p0. The name of the further variables stems from the paper.
pj = B_histo[0] / pix_sum
pj_z1 = np.power(B_histo[1], 1) * pj
pj_z2 = np.power(B_histo[1], 2) * pj
pj_z3 = np.power(B_histo[1], 3) * pj
m0 = np.sum(pj)
m1 = np.sum(pj_z1)
m2 = np.sum(pj_z2)
m3 = np.sum(pj_z3)
cd = (m0*m2) - (m1*m1)
c0 = ((-m2*m2) - (-m3*m1))/cd
c1 = ((m0*-m3) - (m1*-m2))/cd
z0 = 0.5 *(-c1 - (np.power(np.power(c1, 2) - 4*c0, 1/2)))
z1 = 0.5 *(-c1 + (np.power(np.power(c1, 2) - 4*c0, 1/2)))
pd = z1 - z0
p0 = (z1 - m1) / pd # p0 should be the percentage of the pixels to which the value 0 is attributed
# using cumulative histogram and comparing it to a target value by calculating the difference. When the difference is the lowest, the index indicates the value of the threshold t
cum_pix = np.cumsum(B_histo[0])
target_value = p0 * pix_sum
#td = cum_pix
diff = [abs(i - target_value) for i in cum_pix]
cum_pix[1]
diff[0]
t = [abs(i - target_value) for i in cum_pix].index(np.min(diff))
print(t)
抱歉,代码混乱。 无论如何,我在Python上计算的值与在Image J上计算的值不同。 您知道问题可能出在哪里吗?还是Python中有一个函数可以检索auto-threshold时刻的值? 我会非常感谢您挖掘的技巧或提示,谢谢
答案 0 :(得分:0)
矩量和与阈值的比例的计算结果很好,但是skimage直方图存在一个问题,即会缩小bin(即使指定了256 bin)并计算 t 的方式。 这是解决问题的方法:
#Instead of skimage.exposure.histogram (B, nbins=256)
grey_value = np.arange(256)
B_freq = cv2.calcHist([S], [0],None,[256],[0,255])
B_freq = B_freq.reshape((256,))
B_freq = np.int64(B_freq)
B_histo = (B_freq, grey_value)
pix_sum = B.shape[0]*B.shape[1] # calculating the sum of the pixels
#from the paper, calculating the 3 first odrers
pj = B_histo[0] / pix_sum
pj_z1 = np.power(B_histo[1], 1) * pj
pj_z2 = np.power(B_histo[1], 2) * pj
pj_z3 = np.power(B_histo[1], 3) * pj
m0 = np.sum(pj)
m1 = np.sum(pj_z1)
m2 = np.sum(pj_z2)
m3 = np.sum(pj_z3)
cd = (m0*m2) - (m1*m1)
c0 = ((-m2*m2) - (-m3*m1))/cd
c1 = ((m0*-m3) - (m1*-m2))/cd
z0 = 0.5 *(-c1 - (np.power(np.power(c1, 2) - 4*c0, 1/2)))
z1 = 0.5 *(-c1 + (np.power(np.power(c1, 2) - 4*c0, 1/2)))
pd = z1 - z0
p0 = (z1 - m1) / pd # p0 should be the percentage of the pixels to which the threshold t should be done
# using cumulative histogram and comparing it to a target value by calculating the difference. When the difference is the lowest, the index indicates the value of the threshold t
cum_pix = np.cumsum(B_freq)
target_value = p0 * pix_sum
diff = [(i - target_value) for i in cum_pix]
def find_nearest(array, value):
array = np.asarray(array)
idx = (np.abs(array - value)).argmin()
return array[idx]
t = diff.index(find_nearest(diff, 0))
print(t)
因此,此代码为您提供了图像J的Moments自动阈值的阈值。