在一般的視覺視覺顏色是由RGB組成的,為了簡化處理的視覺的復雜度,以及得到分割出指定物體的特征形狀,通過二值化的方法更加的高效方便
二值化定義:圖像的二值化,就是將圖像上的像素點的灰度值設置為0或255,也就是將整個圖像呈現出明顯的只有黑和白的視覺效果
二值化分割定義:一幅圖像包括目標物體、背景還有噪聲,要想從多值的數字圖像中直接提取出目標物體,常用的方法就是設定一個阈值T,用T將圖像的數據分成兩部分:大於T的像素群和小於T的像素群。這是研究灰度變換的最特殊的方法,稱為圖像的二值化(Binarization)。
1.簡單的阈值-(全局阈值):cv2.threshold(src, thresh, maxval, type, dst=None)->retval,dst
參數:
src: 指原圖像,原圖像應該是灰度圖
thresh:二值化的阈值
maxval:超過thresh的像素值設置的最大值
type:二值化的方法操作
1)二進制阈值化 THRESH_BINARY
3)截斷阈值化 THRESH_TRUNC
阈值化為0 THRESH_TOZERO
反阈值化為0 THRESH_TOZERO_INV
6)大津阈值算法(OTSU):
簡介:大津法(OTSU)可以根據圖像特性,選擇最佳的阈值,不需要人為提供阈值,故它也被認為是圖像分割中阈值選取的最佳算法,計算簡單,不受圖像亮度和對比度的影響。從大津法的原理上來講,該方法又稱作最大類間方差法,按照大津法求得的阈值進行圖像二值化分割後,前景與背景圖像的類間方差最大。適合處理所需提取的前景圖像和背景圖像差距較大的圖像。其函數也十分簡單,只需要把阈值thresh設置為0,然後設置type為cv2.THRESH_BINARY+cv2.THRESH_OTSU,會自動返回一個合適的阈值。ret2,th2 =cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
dst - 輸出數組/圖像(與src相同大小和類型以及相同通道數的數組/圖像)
返回值:
2.局部阈值法 : 當圖像的色彩分布不均衡時,使用全局阈值處理的效果不是很好,這是使用局部阈值處理來進行分割,可以產生很好的效果。
局部阈值的處理原理是,針對每一個像素點專門配置一個阈值來進行處理,這些阈值就構成了和原圖像維度相同的矩陣。cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
參數:
灰度圖像上每個像素的顏色值又稱為灰度,指黑白圖像中點的顏色深度,范圍一般從0到255,白色為255,黑色為0。所謂灰度值是指色彩的濃淡程度,灰度直方圖是指一幅數字圖像中,對應每一個灰度值統計出具有該灰度值的象素數。
圖像灰度化處理有以下幾種方式:
cvtColor(src, code, dst=None, dstCn=None)->gray_image
參數:
返回值:
源代碼:
import cv2
import numpy as np
""" 二值化進行圖像的背景分割: 1.全局阈值 2.局部阈值:表示自適應阈值算法,平均 (ADAPTIVE_THRESH_MEAN_C)或高斯(ADAPTIVE_THRESH_GAUSSIAN_C) 3.用戶自己計算阈值:中值法計算阈值 4.HSV阈值的計算 """
def nothing(*arg):
pass
# 全局阈值
def threshold_demo(image, threshold_value):
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # 把輸入圖像灰度化
# 直接阈值化(對輸入的單通道矩陣逐像素進行阈值分割)表示的是二值化結合TRIANGLE法,全局自適應阈值,第二個參數值0可改為任意數字但不起作用,適用於單個波峰。
ret, binary = cv2.threshold(gray, threshold_value, 255, cv2.THRESH_BINARY)
print("threshold value %s" % ret)
cv2.namedWindow("binary0", cv2.WINDOW_NORMAL)
cv2.imshow("binary0", binary)
# 局部阈值:表示自適應阈值算法,平均 (ADAPTIVE_THRESH_MEAN_C)或高斯(ADAPTIVE_THRESH_GAUSSIAN_C)。
def local_threshold(image):
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # 把輸入圖像灰度化
# 自適應阈值化能夠根據圖像不同區域亮度分布,改變阈值
# 第三個參數必須為THRESH_BINARY或THRESH_BINARY_INV的阈值類型
# 第四個參數blockSize參數表示塊大小(奇數且大於1,比如3,5,7........ )。
# 最後一個參數是常數,表示從平均值或加權平均值中減去的數
# 補充:在使用平均和高斯兩種算法情況下,通過計算每個像素周圍blockSize x blockSize大小像素塊的加權均值並減去常量C即可得到自適應阈值。如果使用平均的方法,則所有像素周圍的權值相同;如果使用高斯的方法,則每個像素周圍像素的權值則根據其到中心點的距離通過高斯方程得到。
binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 25, 10)
cv2.namedWindow("binary1", cv2.WINDOW_NORMAL)
cv2.imshow("binary1", binary)
# 用戶自己計算阈值:中值法計算阈值
def custom_threshold(image):
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # 把輸入圖像灰度化
h, w = gray.shape[:2]
m = np.reshape(gray, [1, w * h])
mean = m.sum() / (w * h)
print("mean:", mean)
ret, binary = cv2.threshold(gray, mean, 255, cv2.THRESH_BINARY)
cv2.namedWindow("binary2", cv2.WINDOW_NORMAL)
cv2.imshow("binary2", binary)
# HSV阈值的調整,這裡也可以通過HSV來對圖像阈值進行調整
def HSV():
cap = cv2.VideoCapture(0)
# set blue thresh 設置HSV中藍色、天藍色范圍
lower_blue = np.array([78, 43, 46])
upper_blue = np.array([110, 255, 255])
while True:
# get a frame and show 獲取視頻幀並轉成HSV格式, 利用cvtColor()將BGR格式轉成HSV格式,參數為cv2.COLOR_BGR2HSV。
ret, frame = cap.read()
cv2.imshow('Capture', frame)
# change to hsv model
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# get mask 利用inRange()函數和HSV模型中藍色范圍的上下界獲取mask,mask中原視頻中的藍色部分會被弄成白色,其他部分黑色。
mask = cv2.inRange(hsv, lower_blue, upper_blue)
cv2.imshow('Mask', mask)
# detect blue 將mask於原視頻幀進行按位與操作,則會把mask中的白色用真實的圖像替換:
res = cv2.bitwise_and(frame, frame, mask=mask)
cv2.imshow('Result', res)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
cv2.namedWindow('colorThreshold')
cv2.createTrackbar('threshold_value', 'colorThreshold', 0, 255, nothing)
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
threshold_value = cv2.getTrackbarPos('threshold_value', 'colorThreshold')
threshold_demo(frame, threshold_value)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
效果:
調整的最終阈值:
分割出來的背景圖片: