def rgb2gray(img):
    h=img.shape[0]
    w=img.shape[1]
    img1=np.zeros((h,w),np.uint8)
    for i in range(h):
        for j in range(w):
            img1[i,j]=0.144*img[i,j,0]+0.587*img[i,j,1]+0.299*img[i,j,1]
    return img1

def otsu(img):
    h=img.shape[0]
    w=img.shape[1]
    m=h*w   # 图像像素点总和
    otsuimg=np.zeros((h,w),np.uint8)
    threshold_max=threshold=0   # 定义临时阈值和最终阈值
    histogram=np.zeros(256,np.int32)   # 初始化各灰度级个数统计参数
    probability=np.zeros(256,np.float32)   # 初始化各灰度级占图像中的分布的统计参数
    for i in range (h):
        for j in range (w):
            s=img[i,j]
            histogram[s]+=1   # 统计像素中每个灰度级在整幅图像中的个数
    for k in range (256):
        probability[k]=histogram[k]/m   # 统计每个灰度级个数占图像中的比例
    for i in range (255):
        w0 = w1 = 0   # 定义前景像素点和背景像素点灰度级占图像中的分布
        fgs = bgs = 0   # 定义前景像素点灰度级总和and背景像素点灰度级总和
        for j in range (256):
            if j<=i:   # 当前i为分割阈值
                w0+=probability[j]   # 前景像素点占整幅图像的比例累加
                fgs+=j*probability[j]
            else:
                w1+=probability[j]   # 背景像素点占整幅图像的比例累加
                bgs+=j*probability[j]
        u0=fgs/w0   # 前景像素点的平均灰度
        u1=bgs/w1   # 背景像素点的平均灰度
        g=w0*w1*(u0-u1)**2   # 类间方差
        if g>=threshold_max:
            threshold_max=g
            threshold=i
    print(threshold)
    for i in range (h):
        for j in range (w):
            if img[i,j]>threshold-3:
                otsuimg[i,j]=255
            else:
                otsuimg[i,j]=0
    return otsuimg

image = cv.imread(r"C:/Users/zhou/Desktop/oil meter/images/2_2021.jpg")

grayimage = rgb2gray(image)

otsuimage = otsu(grayimage)
cv.imshow("image", image)
cv.imshow("grayimage",grayimage)
cv.imshow("otsu", otsuimage)
cv.waitKey(0)
cv.destroyAllWindows()