上一個教程中,我們談到了關於圖像二值化的兩種方法,一種是固定閾值法,另一種是自適應閾值法,總的來說,自適應閾值法在某些方面要由於固定閾值法,但還沒完,這次我們將隆重介紹我們的重量級選手,也就是OTSU算法(又稱為大津算法和最大類間方差法)。
最大類間方差法是1979年由日本學者大津提出的,是一種自適應閾值確定的方法,又叫大津法,簡稱OTSU,是一種基於全局的二值化算法,它是根據圖像的灰度特性,將圖像分為前景和背景兩個部分。當取最佳閾值時,兩部分之間的差別應該是最大的,在OTSU算法中所采用的衡量差別的標准就是較為常見的最大類間方差。前景和背景之間的類間方差如果越大,就說明構成圖像的兩個部分之間的差別越大,當部分目標被錯分為背景或部分背景被錯分為目標,都會導致兩部分差別變小,當所取閾值的分割使類間方差最大時就意味着錯分概率最小。
OSTU原理
在大津算法中,我們窮舉搜索能使類內方差最小的閾值,定義為兩個類的方差的加權和:
權重 是被閾值 t分開的兩個類的概率,而
是這兩個類的方差
大津證明了最小化類內方差和最大化類間方差是相同的:
用類概率 和類均值 來表示。
類概率 用閾值為t 的直方圖計算:
而類均值 為:
類概率和類均值可以迭代計算,大津算法得出了0:1范圍上的一個閾值。這個閾值用於圖像中出現的像素強度的動態范圍。例如,若圖像只包含155到255之間的像素強度,大津閾值0.75會映射到灰度閾值230(而不是192,因為圖像包含的像素不是0–255全范圍的)。
對於圖像I(x,y),前景(即目標)和背景的分割閾值記作T,屬於前景的像素點數占整幅圖像的比例記為ω0,其平均灰度μ0;背景像素點數占整幅圖像的比例為ω1,其平均灰度為μ1。圖像的總平均灰度記為μ,類間方差記為g。
假設圖像的背景較暗,並且圖像的大小為M×N,圖像中像素的灰度值小於閾值T的像素個數記作N0,像素灰度大於閾值T的像素個數記作N1,則有:
(1) ω0=N0/ (M×N)
(2) ω1=N1/ (M×N)
(3) N0 + N1 = M×N
(4) ω0 + ω1 = 1
(5) μ = ω0 * μ0 + ω1 * μ1
(6) g = ω0 * (μ0 - μ)2 + ω1 * (μ1 - μ)2
將式(5)代入式(6),得到等價公式:
(7) g = ω0 *ω1 * (μ0 - μ1)2
采用遍歷的方法得到使類間方差g最大的閾值T。
OTSU算法的實現
OTSU使用於雙峰圖像,固定閾值化通常適用的圖像的灰度化直方圖是單峰的:
而如果碰到了這種直方圖的圖像,那么就會過濾掉極為重要的信息:
OTSU適用於這種雙峰圖片,它可以自己尋找最優閾值,為了表現測試的效果,我們找了一張雙峰的圖片:
首先使用固定閾值法進行實驗:
import cv2 as cv import matplotlib.pyplot as plt img = cv.imread('sh.jpg',0) ret,threshold = cv.threshold(img,60,127,cv.THRESH_BINARY) cv.imshow("res",threshold) cv.waitKey(0)
我們再用OTSU的方法實驗一下:
import cv2 as cv import matplotlib.pyplot as plt img = cv.imread('sh.jpg',0) ret,threshold = cv.threshold(img,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU) cv.imshow("res",threshold) cv.waitKey(0)
關於代碼,需要說明的是,我們在使用OTSU時,不需要設置閾值,只需要設置一個最小值0和最大值255,該算法會自動尋找最優的閾值進行計算:
可以看到,效果還是比較不錯的,總結一下,OTSU的優缺點:
優點:算法簡單,當目標與背景的面積相差不大時,能夠有效地對圖像進行分割。
缺點:當圖像中的目標與背景的面積相差很大時,表現為直方圖沒有明顯的雙峰,或者兩個峰的大小相差很大,分割效果不佳,或者目標與背景的灰度有較大的重疊時也不能准確的將目標與背景分開。
原因:該方法忽略了圖像的空間信息,同時將圖像的灰度分布作為分割圖像的依據,對噪聲也相當敏感。