python+OpenCV图像处理(五)图像的阈值分割
圖像的閾值處理
? ? ? 一幅圖像包括目標物體、背景還有噪聲,要想從多值的數字圖像中直接提取出目標物體,常用的方法就是設定一個閾值T,用T將圖像的數據分成兩部分:大于T的像素群和小于T的像素群。這是研究灰度變換的最特殊的方法,稱為圖像的二值化(Binarization)。
? ? ? ?閾值分割法的特點是:適用于目標與背景灰度有較強對比的情況,重要的是背景或物體的灰度比較單一,而且總可以得到封閉且連通區域的邊界。
(一)簡單閾值
選取一個全局閾值,然后就把整幅圖像分成非黑即白的二值圖像。
函數為cv2.threshold( )
這個函數有四個參數,第一個是原圖像矩陣,第二個是進行分類的閾值,第三個是高于(低于)閾值時賦予的新值,第四個是一個方法選擇參數,常用的有:
- cv2.THRESH_BINARY(黑白二值)
- cv2.THRESH_BINARY_INV(黑白二值翻轉)
- cv2.THRESH_TRUNC(得到額圖像為多像素值)
- cv2.THRESH_TOZERO(當像素高于閾值時像素設置為自己提供的像素值,低于閾值時不作處理)
- cv2.THRESH_TOZERO_INV(當像素低于閾值時設置為自己提供的像素值,高于閾值時不作處理)
這個函數返回兩個值,第一個值為閾值,第二個就是閾值處理后的圖像矩陣。
img = cv2.imread('4.jpg', 0) ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # binary (黑白二值) ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV) # (黑白二值反轉) ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC) # 得到的圖像為多像素值 ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO) # 高于閾值時像素設置為255,低于閾值時不作處理 ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV) # 低于閾值時設置為255,高于閾值時不作處理print(ret)cv2.imshow('thresh1', thresh1) cv2.imshow('thresh2', thresh2) cv2.imshow('thresh3', thresh3) cv2.imshow('thresh4', thresh4) cv2.imshow('thresh5', thresh5) cv2.imshow('grey-map', img) cv2.waitKey(0) cv2.destroyAllWindows()(二)自適應閾值
一中的簡單閾值是一種全局性的閾值,只需要設定一個閾值,整個圖像都和這個閾值比較。而自適應閾值可以看成一種局部性的閾值,通過設定一個區域大小,比較這個點與區域大小里面像素點 的平均值(或者其他特征)的大小關系確定這個像素點的情況。使用的函數為:
# 第一個參數為原始圖像矩陣,第二個參數為像素值上限,第三個是自適應方法(adaptive method):
# ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-----cv2.ADAPTIVE_THRESH_MEAN_C:領域內均值
# ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-----cv2.ADAPTIVE_THRESH_GAUSSIAN_C:領域內像素點加權和,權重為一個高斯窗口
# 第四個值的賦值方法:只有cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV
# 第五個Block size:設定領域大小(一個正方形的領域)
# 第六個參數C,閾值等于均值或者加權值減去這個常數(為0相當于閾值,就是求得領域內均值或者加權值)
# 這種方法理論上得到的效果更好,相當于在動態自適應的調整屬于自己像素點的閾值,而不是整幅圖都用一個閾值
img = cv2.imread('4.jpg', 0) ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 第一個參數為原始圖像矩陣,第二個參數為像素值上限,第三個是自適應方法(adaptive method): # -----cv2.ADAPTIVE_THRESH_MEAN_C:領域內均值 # -----cv2.ADAPTIVE_THRESH_GAUSSIAN_C:領域內像素點加權和,權重為一個高斯窗口 # 第四個值的賦值方法:只有cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV # 第五個Block size:設定領域大小(一個正方形的領域) # 第六個參數C,閾值等于均值或者加權值減去這個常數(為0相當于閾值,就是求得領域內均值或者加權值) # 這種方法理論上得到的效果更好,相當于在動態自適應的調整屬于自己像素點的閾值,而不是整幅圖都用一個閾值 th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 2) th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) th4 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) cv2.imshow('img', img) cv2.imshow('th1', th1) cv2.imshow('th2', th2) cv2.imshow('th3', th3) cv2.imshow('th4', th4) cv2.waitKey(0) cv2.destroyAllWindows()對于第五個參數的窗口越來越小時,發現得到的圖像越來越細了,可以設想,如果把窗口設置的足夠大的話(不能超過圖像大小),那么得到的結果可能就和第二幅圖像的相同了。
(三)Otsu's二值化
cv2.threshold( )函數有兩個返回值,一個是閾值,第二個是處理后的圖像矩陣。
前面對于閾值的設定上,我們選擇的閾值都是127,在實際情況中,有的圖像閾值不是127得到的圖像效果更好。那么這里就需要算法自己去尋找一個閾值,而Otsu's就可以自己找到一個認為最好的閾值。并且Otsu's非常適合于圖像灰度直方圖(只有灰度圖像才有)具有雙峰的情況。他會在雙峰之間找到一個值作為閾值,對于非雙峰圖像,可能并不是很好用。那么經過Otsu's得到的那個閾值就是函數cv2.threshold的第一個參數了。因為Otsu's方法會產生一個閾值,那么函數cv2.threshold( )的第二個參數(設定閾值)就是0了,并且在cv2.threshold的方法參數中還得加上語句cv2.THRESH_OTSU.
在下列這些程序和圖片中大家會有鮮明的體會:
img = cv2.imread('2.jpg', 0) ret1, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 簡單濾波 ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) # Otsu 濾波 print(ret2) cv2.imshow('img', img) cv2.imshow('th1', th1) cv2.imshow('th2', th2) # 用于解決matplotlib中顯示圖像的中文亂碼問題 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False plt.hist(img.ravel(), 256) plt.title('灰度直方圖') plt.show() cv2.waitKey(0) cv2.destroyAllWindows()總結
以上是生活随笔為你收集整理的python+OpenCV图像处理(五)图像的阈值分割的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: latex正文显示运算符
- 下一篇: window下TensorFlow CU