借鑑:
原理:分塊處理,根據當前塊內的均值,方差等資訊得出區域性閾值;但擔心有突變,分塊不好怎麼辦呢?
sauvola是一種考慮區域性均值亮度的影象二值化方法, 以區域性均值為基準在根據標準差做些微調.演算法實現上一般用積分圖方法來實現的.
步驟1 計算區域畫素積分和和積分平方和
步驟2 計算標準差,標準差的計算方法為: std=sqrt((sqdiff-diff*diff/area)/(area-1))
步驟3 sauvola二值化演算法的閾值為t = mean*(1 + k*((std / 128) - 1)).
python**如下:
def integral(img):
'''計算影象的積分和平方積分
:param img:mat--- 輸入待處理影象
:return:integral_sum, integral_sqrt_sum:mat--- 積分圖和平方積分圖
'''integral_sum=np.zeros((img.shape[0],img.shape[1]),dtype=np.int32)
integral_sqrt_sum=np.zeros((img.shape[0],img.shape[1]),dtype=np.int32)
rows,cols=img.shape
for r in range(rows):
sum=0
sqrt_sum=0
for c in range(cols):
sum+=img[r][c]
sqrt_sum+=math.sqrt(img[r][c])
if r==0:
integral_sum[r][c]=sum
integral_sqrt_sum[r][c]=sqrt_sum
else:
integral_sum[r][c]=sum+integral_sum[r-1][c]
integral_sqrt_sum[r][c]=sqrt_sum+integral_sqrt_sum[r-1][c]
return integral_sum, integral_sqrt_sum
def sauvola(img,k=0.1,kernerl=(31,31)):
'''sauvola閾值法。
根據當前畫素點鄰域內的灰度均值與標準方差來動態計算該畫素點的閾值
:param img:mat--- 輸入待處理影象
:param k:float---修正引數,一般0>1#計算領域類半徑的一半
for row in range(rows):
print('第{}行處理中...'.format(row))
for col in range(cols):
xmin=max(0,row-whalf)
ymin=max(0,col-whalf)
xmax=min(rows-1,row+whalf)
ymax=min(cols-1,col+whalf)
area=(xmax-xmin+1)*(ymax-ymin+1)
if area<=0:
sys.exit(1)
if xmin==0 and ymin==0:
diff[row,col]=integral_sum[xmax,ymax]
sqrt_diff[row,col]=integral_sqrt_sum[xmax,ymax]
elif xmin>0 and ymin==0:
diff[row, col] = integral_sum[xmax, ymax]-integral_sum[xmin-1,ymax]
sqrt_diff[row, col] = integral_sqrt_sum[xmax, ymax]-integral_sqrt_sum[xmin-1, ymax]
elif xmin==0 and ymin>0:
diff[row, col] = integral_sum[xmax, ymax] - integral_sum[xmax, ymax-1]
sqrt_diff[row, col] = integral_sqrt_sum[xmax, ymax] - integral_sqrt_sum[xmax, ymax-1]
else:
diagsum=integral_sum[xmax, ymax]+integral_sum[xmin-1, ymin-1]
idiagsum=integral_sum[xmax, ymin-1]+integral_sum[xmin-1, ymax]
diff[row,col]=diagsum-idiagsum
sqdiagsum=integral_sqrt_sum[xmax, ymax]+integral_sqrt_sum[xmin-1, ymin-1]
sqidiagsum=integral_sqrt_sum[xmax, ymin-1]+integral_sqrt_sum[xmin-1, ymax]
sqrt_diff[row,col]=sqdiagsum-sqidiagsum
mean[row,col]=diff[row, col]/area
std[row,col]=math.sqrt((sqrt_diff[row,col]-math.sqrt(diff[row,col])/area)/(area-1))
threshold[row,col]=mean[row,col]*(1+k*((std[row,col]/128)-1))
if img[row,col]img[row,col]=0
else:
img[row,col]=255
return img
OpenCV全域性二值化和區域性二值化原理
thresh otsu最適用於雙波峰。thresh 最適用於單個波峰。它是計算乙個閾值 臨界值 的演算法。先計算影象的灰度直方圖,假設灰度值的均值是130,稱這個均值為m,現在任意選取乙個灰度值t,則可以將直方圖分成前後倆部分,稱這倆部分分別為a和b,這倆部分各自的平均值成為ma和mb。a部分裡的畫...
最優二值化
昨天要做乙個最優二值化,原qr圖如下 對其做最優二值化,即在其直方圖兩個灰度波峰之間的的波谷用來做二值化的閾值。也就是下圖中所示的小紅點。在連續變數中可以用求導的方式來獲得波峰和波谷的位置,但是對於離散變數,要如何求這個小紅點的位置捏?方法一 可以設計這樣乙個檢測結構 用這個結構對直方圖上的灰度1 ...
基於opencv的sauvola二值演算法
sauvola演算法是乙個比較不錯的區域性二值化演算法,有不少人也具體實現了其 但是本人覺得裡面存在一些bug和不方便opencv呼叫,所以對其適當的修改。但是修改之後,仍然就是存在一些問題,就是難以找到乙個比較大的資料型別去儲存,這個bug等以後有空再處理。不過通過修改後的 進行學習,還是很不錯的...