日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

otsu阈值分割

發(fā)布時(shí)間:2024/8/1 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 otsu阈值分割 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、OTSU法(大津閾值分割法)介紹

??OTSU算法是由日本學(xué)者OTSU于1979年提出的一種對(duì)圖像進(jìn)行二值化的高效算法,是一種自適應(yīng)的閾值確定的方法,又稱大津閾值分割法,是最小二乘法意義下的最優(yōu)分割。

二、單閾值OTSU法

??設(shè)圖像包含L個(gè)灰度級(jí),灰度值為i的像素點(diǎn)個(gè)數(shù)為Ni,像素總點(diǎn)數(shù)為:

N=N0+N1+?+NL?1N=N0+N1+?+NL?1

下面給出python源代碼。

#coding:utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt

image = cv2.imread(“E:/python/cv/OTSU/test.jpg”)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

plt.subplot(131), plt.imshow(image, “gray”)
plt.title(“source image”), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.hist(image.ravel(), 256)
plt.title(“Histogram”), plt.xticks([]), plt.yticks([])
ret1, th1 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) #方法選擇為THRESH_OTSU
plt.subplot(133), plt.imshow(th1, “gray”)
plt.title("OTSU,threshold is " + str(ret1)), plt.xticks([]), plt.yticks([])
plt.show()

??結(jié)果如下所示。可以看到,使用OTSU法計(jì)算出來(lái)的閾值為165。

三、多閾值OTSU法

??將單閾值的OTSU推廣到多閾值的圖像分割中,假設(shè)將圖像直方圖分為m+1類,對(duì)應(yīng)的閾值為T1,T2,···,Tm。則最大類間方差為:

σ2B(T?1,T?2,?,T?m)=max0T1T2?L?1{σ2B(T1,T2,?,Tm)}σB2(T1?,T2?,?,Tm?)=max0≤T1≤T2≤?≤L?1{σB2(T1,T2,?,Tm)}
??為求得最優(yōu)閾值,需要使用窮舉搜索,隨著m增大,計(jì)算量驟增。若使用牛頓迭代等優(yōu)化搜索方法,容易陷入局部最優(yōu)解。

四、遺傳算法解OTSU

??遺傳算法是一種基于自然選擇和群體遺傳機(jī)理的搜索算法。它模擬了自然選擇和自然遺傳過(guò)程中發(fā)生的繁殖、交配和突變現(xiàn)象,將每一個(gè)可能的解看作是群體的一個(gè)個(gè)體,并將每個(gè)個(gè)體編碼,根據(jù)設(shè)定的目標(biāo)函數(shù)對(duì)每個(gè)個(gè)體進(jìn)行評(píng)價(jià),給出一個(gè)適應(yīng)度值。開始時(shí)隨機(jī)產(chǎn)生一些個(gè)體,利用遺傳算子產(chǎn)生新一代的個(gè)體,新個(gè)體繼承上一代的優(yōu)良性狀,逐步向更優(yōu)解進(jìn)化。由于遺傳算法在每一代同時(shí)搜索參數(shù)空間的不同區(qū)域,從而能夠使找到全局最優(yōu)解的可能性大大增加。遺傳算法屬于啟發(fā)式算法,無(wú)限趨緊最優(yōu)解并收斂。

??那么怎么將圖像分割問(wèn)題抽象成遺傳問(wèn)題,即怎么將問(wèn)題編碼成基因串,如何構(gòu)造適應(yīng)度函數(shù)來(lái)度量每條基因的適應(yīng)度值。假設(shè)如上述三所示,將圖像分為m+1類,則m個(gè)閾值按順序排列起來(lái)構(gòu)成一個(gè)基因串:

α={T1,T2,?,Tm}α={T1,T2,?,Tm}
由于灰度為0~255,所以可以使用8位二進(jìn)制代碼表示每個(gè)閾值,此時(shí)每個(gè)基因串由長(zhǎng)度為8*m個(gè)比特位的傳組成。

??將類間方差作為其適應(yīng)度函數(shù),類間方差越大,適應(yīng)度函數(shù)值就越高。

??python代碼如下所示:

#coding:utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
import random

#將不足8m位的染色體擴(kuò)展為8m位
def expand(k, m):
for i in range(len(k)):
k[i] = k[i][:2] + ‘0’*(8*m+2 - len(k[i])) + k[i][2:len(k[i])]
return k

def Hist(image):
a=[0]256
h=image.shape[0]
w=image.shape[1]
MN=hw
average=0.0
for i in range(w):
for j in range(h):
pixel=int(image[j][i])
a[pixel]=a[pixel]+1
for i in range(256):
a[i]=a[i]/float(MN)
average=average+a[i]*i
return a, average

#解析多閾值基因串
def getTh(seed, m):
th = [0, 256]
seedInt = long(seed, 2)
for i in range(0, m):
tmp = seedInt & 255
if tmp != 0:
th.append(tmp)
seedInt = seedInt >> 8
th.sort()
return th

#適應(yīng)度函數(shù) Ostu全局算法
def fitness(seed, p, average, m):
Var = [0.0] * len(seed)
g_muT = 0.0

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">256</span>):g_muT = g_muT + i * p[i]<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(seed)):th = getTh(seed[i], m)<span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(len(th)-<span class="hljs-number">1</span>):w = [<span class="hljs-number">0.0</span>] * (len(th)-<span class="hljs-number">1</span>)muT = [<span class="hljs-number">0.0</span>] * (len(th)-<span class="hljs-number">1</span>)mu = [<span class="hljs-number">0.0</span>] * (len(th)-<span class="hljs-number">1</span>)<span class="hljs-keyword">for</span> k <span class="hljs-keyword">in</span> range(th[j], th[j+<span class="hljs-number">1</span>]):w[j] = w[j] + p[k]muT[j] = muT[j] + + p[k] * k<span class="hljs-keyword">if</span> w[j] &gt; <span class="hljs-number">0</span>:mu[j] = muT[j] / w[j]Var[i] = Var[i] + w[j] * pow(mu[j] - g_muT, <span class="hljs-number">2</span>) <span class="hljs-keyword">return</span>Var

#選擇算子 輪盤賭選擇算法
def wheel_selection(seed, Var):
var = [0.0]*len(Var)
s = 0.0
n = [’’]*len(seed)
sumV = sum(Var)
for i in range(len(Var)):
var[i] = Var[i]/sumV
for i in range(1, len(Var)):
var[i] = var[i] + var[i-1]
for i in range(len(seed)):
s = random.random()
for j in range(len(var)):
if s <= var[j]:
n[i] = seed[j]
return n

#單點(diǎn)交叉算子
def Cross(Next, m):
for i in range(0, len(Next) - 1, 2):
if random.random() < 0.7:
if m > 2:
tmp = Next[i][10:]
Next[i] = Next[i][:10] + Next[i+1][10:]
Next[i+1] = Next[i+1][:10] + tmp
else:
tmp = Next[i][6:]
Next[i] = Next[i][:6] + Next[i+1][6:]
Next[i+1] = Next[i+1][:6] + tmp
return Next

#變異算子
def Variation(Next):
for i in range(len(Next)):
if random.random()<0.06:
Next[i]=bin(long(Next[i],2)+2)
return Next

#多閾值分割
def genetic_thres(image, k, m):
th = image
for i in range(image.shape[0]):
for j in range(image.shape[1]):
for t in range(1, len(k)-1):
if k[t-1] <= image[i][j] < k[t]:
th[i][j] = int(k[t-1])
return th

# main
imagesrc = cv2.imread(“E:/python/cv/OTSU/test2.jpg”)
gray = cv2.cvtColor(imagesrc, cv2.COLOR_BGR2GRAY)

m = 3 #閾值數(shù)
items_x = range(0, imagesrc.shape[0])
items_y = range(0, imagesrc.shape[1])
random.shuffle(items_x)
random.shuffle(items_y)
x = items_x[0:20m] #產(chǎn)生隨機(jī)x坐標(biāo)
y = items_y[0:20m] #產(chǎn)生隨機(jī)y坐標(biāo)
seed = []
Var = 0.0
times = 0
k = 0
P, average = Hist(gray) #計(jì)算直方圖,P為各灰度的概率的數(shù)組,average為均值
for i in range(0, 20):
code = long(0)
for j in range(0, m):
code = code + gray[x[ij]][y[ij]] << j*8 #將閾值連起來(lái)組成一個(gè)8*m比特的基因串
seed.append(bin(code)) #生成第一代

while times < 2000:
Var = fitness(seed, P, average, m)
Next = wheel_selection(seed, Var)
Next = Cross(Next, m)
Next = expand(Variation(Next), m)
seed = Next
times = times + 1

for j in range(len(Var)):
if Var[j] == max(Var):
k = getTh(Next[j], m)
print k

plt.subplot(131), plt.imshow(imagesrc, “gray”)
plt.title(“source image”), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.hist(imagesrc.ravel(), 256)
plt.title(“Histogram”), plt.xticks([]), plt.yticks([])
th1 = genetic_thres(gray, k, m)
plt.subplot(133), plt.imshow(th1, “gray”)
titleName = ‘’
for i in range(1, len(k)-1):
titleName = titleName + str(k[i]) + ', ’
titleName = titleName[:len(titleName)-2]
plt.title("threshold is " + titleName), plt.xticks([]), plt.yticks([])
plt.show()

這里使用的是標(biāo)準(zhǔn)二進(jìn)制,若使用格雷碼,應(yīng)該能收斂得更好。結(jié)果如下所示:

總結(jié)

以上是生活随笔為你收集整理的otsu阈值分割的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。