画像セグメンテーションのしきい値を設定する 7 つの方法
1. 閾値セグメンテーションとは
閾値セグメンテーションは、画像の灰色の特徴に応じて、設定された閾値に従って画像を異なるサブ領域に分割することです。簡単に理解すると、最初に画像をグレースケールで処理し、次にグレースケール値と設定されたグレースケール範囲に従って画像のグレースケールを分類することになります。たとえば、0 ~ 128 は 1 つのカテゴリ、129 ~ 255 は 1 つのカテゴリです。
さまざまな分類方法に応じて、しきい値セグメンテーションには次の 7 つの方法があります。
- 固定閾値セグメンテーション
- ヒストグラム二峰性法
- 反復閾値画像セグメンテーション
- 適応閾値画像セグメンテーション
- 大津法 OTSU
- 平均法
- 最適なしきい値
2. 固定閾値セグメンテーション
固定閾値分割は最も単純な閾値分割手法であり、ある閾値以上の濃淡値を持つ画素点を255に設定し、閾値以下の画素点を0に設定する方法である。これは最も単純な画像分割方法であり、適用範囲は非常に狭いです。単純な画像に適しています。対応する CV2 関数は cv2.threshold(src, thresh, maxval,cv2.THRESH_BINARY) です。numpy を使用したこの機能の実装は非常に簡単で、必要なコードは 1 行だけです。
return np.where(((img>thresh) & (img<maxval)),255,0)
np.where の最初のパラメータは条件であり、複数の条件を設定できます。2 番目のパラメータは条件が true の場合の numpy 配列の値で、3 番目のパラメータは条件が true でない場合の値です。
完成した比較コードは次のとおりです。
# coding:utf8
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fix_threshold(img, thresh, maxval=255):
return np.where(((img > thresh) & (img < maxval)), 255, 0)
img = cv2.imread('xk.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
ret, th = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
fix = fix_threshold(img_gray, 127, 255)
plt.subplot(131), plt.imshow(img_gray, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(th, cmap='gray')
plt.title('CV2 Image1'), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(fix, cmap='gray')
plt.title('Fix Image2'), plt.xticks([]), plt.yticks([])
plt.show()
3. グレーヒストグラムバイモーダル法
グレースケール ヒストグラムは通常、二峰性です (二峰性、1 つの前景ピークともう 1 つの背景ピーク)。2 つのピーク間の最小値は、最適な 2 値化のカットオフ ポイントと考えることができます。
アルゴリズムは次のとおりです。
(1) ヒストグラム firstPeak の最大値を見つける
(2) 次の式で 2 番目のピークを計算します。
Second P eak = max x [ ( x − frist P eak ) 2 ∗ hist ( x ) ] SecondPeak = \max \limits_{x}[(x-fristPeak)^2*hist(x)]2番目のピーク_ _ _ _ _ _=バツマックス[ ( x−最初のピーク) _ _ _ _ _ _2∗h i s t ( x ) ]
(3) 2 つのピーク間の最小グレー値がカットオフ ポイントです (最大のピークのグレー値が 2 番目に大きいピークのグレー値よりも小さい可能性があることを考慮する必要があります)で得られた閾値は
CV2 と一致します 閾値関数で得られた閾値は完全には一致しません。この方法は比較的単純であり、単純な画像を処理する場合には効果的ですが、リモートセンシング画像などの複雑な画像に対しては効果が低くなります。今後の記事では、リモート センシング画像の解釈に関するセクションを追加する予定です。
# coding:utf8
import cv2
import numpy as np
from matplotlib import pyplot as plt
def GrayHist(img):
grayHist = np.zeros(256,dtype=np.uint64)
for v in range(256):
grayHist[v] = np.sum(img==v)
return grayHist
def threshTwoPeaks(image):
# 计算灰度直方图
hist = GrayHist(image)
# 寻找灰度直方图的最大峰值对应的灰度值
maxLoc = np.where(hist == np.max(hist)) #maxLoc 中存放的位置
firstPeak = maxLoc[0][0]
# 寻找灰度直方图的第二个峰值对应的灰度值
elementList = np.arange(256,dtype = np.uint64)
measureDists = np.power(elementList - firstPeak,2) * hist
maxLoc2 = np.where(measureDists == np.max(measureDists))
secondPeak = maxLoc2[0][0]
# 找到两个峰值之间的最小值对应的灰度值,作为阈值
thresh = 0
if secondPeak > firstPeak:
firstPeak,secondPeak=secondPeak,firstPeak
temp = hist[secondPeak:firstPeak]
minloc = np.where(temp == np.min(temp))
thresh = secondPeak + minloc[0][0] + 1
# 找到阈值之后进行阈值处理,得到二值图
threshImage_out = image.copy()
# 大于阈值的都设置为255
threshImage_out[threshImage_out > thresh] = 255
# 小于阈值的都设置为0
threshImage_out[threshImage_out <= thresh] = 0
return thresh, threshImage_out
if __name__ == "__main__":
img = cv2.imread('dt.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
th, img_new = threshTwoPeaks(img_gray)
th1,img_new_1 = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_TRIANGLE)
print(th,th1)
plt.subplot(131), plt.imshow(img_gray, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(img_new, cmap='gray')
plt.title('Image'), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(img_new_1, cmap='gray')
plt.title('CV2 Image1'), plt.xticks([]), plt.yticks([])
plt.show()