OpenCV learning 30--OTSU algorithm for threshold segmentation

The OTSU algorithm, also known as the maximum inter-class variance threshold segmentation algorithm, is also called the Otsu algorithm. It was proposed by Otsu Zhanzhi of Japan in 1980. It is derived from the least squares method and is used for some simple threshold determination.

For a grayscale image, we sometimes really want to use a threshold to separate its foreground and background. We can reasonably assume that if the pixel distribution of the image is plotted, there should be two peaks on the image, the foreground color and the background color. There must be a valley between these two peaks, so we can set the threshold here to achieve a good segmentation effect on the image.

How to determine this threshold? The OTSU algorithm says that we can find the between-class variance of the two images segmented with this threshold. For each possible threshold, we calculate and take out the pixel value with the largest inter-class variance, and this value can better segment the image.

Algorithm
1. Divide the gray value into 0-m, and for each gray t of 0-m, use it as a threshold to divide the image into two parts with gray levels of 0-t and t+1-m.

2. Calculate the proportion w1, w2 of each part, the average gray value u1, u2 of each part, and the total average gray value u.

3. Calculate their inter-class variance δ2=w1(u1−u)2+w2(u2−u)2=w1w2(u1−u2)2
4. Take out the corresponding threshold t when the inter-class variance is the largest, which can be used as Our final threshold.

Python implementation:

import Image
import numpy as np

im=Image.open('test.png')
im.show()
im=im.convert('L')
im.show()
arr=np.array(im)
width,height=arr.shape
arr=arr.reshape(width*height)

freq=np.zeros(256)*1.0

total=0.
point=0.
for i in arr:
    freq[i]+=1
    total+=i
    point+=1

u=total/point

w1=0.
w2=1.
u1=0.
u2=u
eps=0.
threshold=0

for i in range(255):
    if freq[i]==0 or w2*point-freq[i]==0:
        continue
    u1=(u1*w1*point+i*freq[i])/(w1*point+freq[i])
    u2=(u2*w2*point-i*freq[i])/(w2*point-freq[i])
    w1=w1+freq[i]/point
    w2=w2-freq[i]/point
    eps_now=w1*(u1-u)*(u1-u)+w2*(u-u2)*(u-u2)
    if(eps_now>eps):
        eps=eps_now
        threshold=i

table=[]
for i in range(256):
    if i>threshold :
        table.append(255)
    else:
        table.append(0)
im=im.point(table,'L')
im.show()

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325770317&siteId=291194637