【OpenCV篇】OpenCV——02day.圖像預處理(1)

目錄

前言

一、圖像色彩空間轉換

1 RGB顏色空間

2 顏色加法

3 顏色加權加法

4 HSV顏色空間

5 RGB轉Gray(灰度)

二、灰度實驗

1 灰度圖

2 最大值法

3 平均值法

4 加權均值法

5 兩個極端的灰度值

三、圖像二值化處理

二值圖像

1 閾值法(THRESH_BINARY)

2 反閾值法(THRESH_BINARY_INV)

3 截斷閾值法(THRESH_TRUNC)

4 低閾值零處理(THRESH_TOZERO)

5 超閾值零處理(THRESH_TOZERO_INV)

6 OTSU閾值法

7 自適應二值化

7.1.取均值

7.2.加權求和

二值化代碼示例:

四、圖像變換操作

1.圖像翻轉(圖像鏡像旋轉)

2. 圖像仿射變換

3. 圖像旋轉

4. 圖像平移

5. 圖像縮放

總結


前言

????????這一章講一下圖像在色彩空間里面的轉換,如何把色彩圖轉化為灰度圖,以及如何將圖像二值化處理和圖像的翻轉操作


一、圖像色彩空間轉換

????????在OpenCV中,圖像色彩空間轉換是一項基礎且重要的操作,它涉及將圖像從一種顏色表示形式轉換為另一種表示形式的過程。通過這種轉換,可以更有效地執行特定類型的圖像處理和分析任務。常見的顏色空間包括RGB、HSV、YUV等。

  • 色彩空間轉換的作用:
    • 提高圖像處理效果:轉換到更適合的色彩空間(如HSV用于顏色分割)可以提升算法的準確性和魯棒性。
    • 節省計算資源:在優化后的色彩空間中處理圖像,能降低計算復雜度,從而減少資源消耗。

1 RGB顏色空間

????????在圖像處理中,最常見的就是RGB顏色空間。RGB顏色空間是我們接觸最多的顏色空間,是一種用于表示和顯示彩色圖像的一種顏色模型。RGB代表紅色(Red)、綠色(Green)和藍色(Blue),這三種顏色通過不同強度的光的組合來創建其他顏色,廣泛應用于我們的生活中,比如電視、電腦顯示屏以及上面實驗中所介紹的RGB彩色圖。

????????RGB顏色模型基于笛卡爾坐標系,如下圖所示,RGB原色值位于3個角上,二次色青色、品紅色和黃色位于另外三個角上,黑色位于原點處,白色位于離原點最遠的角上。因為黑色在RGB三通道中表現為(0,0,0),所以映射到這里就是原點;而白色是(255,255,255),所以映射到這里就是三個坐標為最大值的點。

????????RGB顏色空間可以產生大約1600萬種顏色,幾乎包括了世界上的所有顏色,也就是說可以使用RGB顏色空間來生成任意一種顏色。

注意:在OpenCV中,顏色是以BGR的方式進行存儲的,而不是RGB,這也是上面紅色的像素值是(0,0,255)而不是(255,0,0)的原因。

2 顏色加法

圖像相加的方法有兩種:

  • 使用OpenCV的cv.add()函數進行圖像相加
  • 通過我們之前學過的NumPy直接相加

OpenCV加法與NumPy加法的區別:

OpenCV加法(飽和運算)
????????當計算結果超出有效像素值范圍(例如0-255)時,OpenCV會將結果截斷到最接近的邊界值。例如,加法結果為300時,輸出會被限制為255;結果為-50時,輸出會被限制為0。這種處理方式更適合圖像處理,能避免因數值溢出導致的異常亮暗區域。

NumPy加法(模運算)
????????NumPy的加法基于模運算,計算結果超出有效范圍時,會對255取模。例如,255+1=256,在8位圖像中會輸出0(對256來取模256 mod 256 = 0);300會被映射為44(對300來取模300 mod 256 = 44)。這種運算在圖像處理中可能導致不自然的像素值循環,如亮區突然變暗或暗區突然變亮。

ps:講一下模運算與取余的區別

取余運算?:
整數商(c)向 ?0 方向舍入?(即截斷小數部分,Math.trunc())。
公式:r = a - b * trunc(a / b)
?結果符號與被除數(a)相同。
?示例?:-7 ÷ 4?→ 商?c = trunc(-1.75) = -1,余數?r = -7 - (-1)*4 = -3

模運算?:
整數商(c)向 ?負無窮方向舍入?(Math.floor())。
公式:r = a - b * floor(a / b)
?結果符號與除數(b)相同。
?示例?:-7 ÷ 4?→ 商?c = floor(-1.75) = -2,余數?r = -7 - (-2)*4 = 1

只有當被除數與除數同號時,兩者結果相同(如?7 % 4 = 3,-7 % -4 = -3)

示例代碼:

import cv2 as cv
import numpy as np
# 讀取圖像
pig = cv.imread("../images/pig.png")
grass = cv.imread("../images/cao.png")# 飽和操作cv.add(img1, img2)   np.uint8 0~255  250+10=255(加到最大值也只會是255,最小為0)
saturation1 = cv.add(pig, grass)
# cv.imshow("saturation1", saturation1)# 使用numpy直接相加  取模運算  對256取模  250+10=260%256=4
saturation2 = pig + grass
# cv.imshow("saturation2", saturation2)x = np.uint8([[250]])
y = np.uint8([[10]])
xy1 = cv.add(x, y)
xy2 = x + y
print(xy1)
print(xy2)cv.waitKey(0)
cv.destroyAllWindows()

3 顏色加權加法

cv2.addWeighted(src1,alpha,src2,deta,gamma)

src1、src2:輸入圖像。

alpha、beta:兩張圖象權重。

gamma:亮度調整值。

????????gamma > 0,圖像會變亮。

????????gamma < 0,圖像會變暗。

????????gamma = 0,則沒有額外的亮度調整。

????????這也是加法,但是不同的是兩幅圖像的權重不同,這就會給人一種混合或者透明的感覺。圖像混合的計算公式如下:

g(x) = (1?α)f0(x) + αf1(x)

通過修改 α 的值(0 → 1),可以實現非常炫酷的混合。

????????現在我們把兩幅圖混合在一起。第一幅圖的權重是0.7,第二幅圖的權重是0.3。函數cv2.addWeighted()可以按下面的公式對圖片進行混合操作。

dst = α?img1 + β?img2 + γ

這里γ取為零。

# 顏色加權加法 cv.addWeighted(img1, alpha(圖片1的權重), img2, beta(圖片2的權重), gamma(亮度調整))
dst = cv.addWeighted(pig, 0.4, grass, 0.6, 30)
cv.imshow("addWeighted", dst)

4 HSV顏色空間

cv.cvtColor(img, cv.COLOR_BGR2HSV)

????????HSV顏色空間指的是HSV顏色模型,這是一種與RGB顏色模型并列的顏色空間表示法。RGB顏色模型使用紅、綠、藍三原色的強度來表示顏色,是一種加色法模型,即顏色的混合是添加三原色的強度。而HSV顏色空間使用色調(Hue)、飽和度(Saturation)和亮度(Value)三個參數來表示顏色,色調H表示顏色的種類,如紅色、綠色、藍色等;飽和度表示顏色的純度或強度,如紅色越純,飽和度就越高;亮度表示顏色的明暗程度,如黑色比白色亮度低。

HSV顏色模型是一種六角錐體模型,如下圖所示:

色調H:

????????使用角度度量,取值范圍為0°~360°,從紅色開始按逆時針方向計算,紅色為0°,綠色為120°,藍色為240°。它們的補色是:黃色為60°,青色為180°,紫色為300°。通過改變H的值,可以選擇不同的顏色

飽和度S:

????????飽和度S表示顏色接近光譜色的程度。一種顏色可以看成是某種光譜色與白色混合的結果。其中光譜色所占的比例越大,顏色接近光譜色的程度就越高,顏色的飽和度就越高。飽和度越高,顏色就越深而艷,光譜色的白光成分為0,飽和度達到最高。通常取值范圍為0%~100%,其中0%表示灰色或無色,100%表示純色,通過調整飽和度的值,可以使顏色變得更加鮮艷或者更加灰暗。

明度V:

????????明度表示顏色明亮的程度,對于光源色,明度值與發光體的光亮度有關;對于物體色,此值和物體的透射比或反射比有關。通常取值范圍為0%(黑)到100%(白),通過調整明度的值,可以使顏色變得更亮或者更暗。

????????一般對顏色空間的圖像進行有效處理都是在HSV空間進行的,然后對于基本色中對應的HSV分量需要給定一個嚴格的范圍,下面是通過實驗計算的模糊范圍(準確的范圍在網上都沒有給出)。

H: 0— 180

S: 0— 255

V: 0— 255

此處把部分紅色歸為紫色范圍:

為什么有了RGB顏色空間我們還是需要轉換成HSV顏色空間來進行圖像處理呢?

????????符合人類對顏色的感知方式:人類對顏色的感知是基于色調、飽和度和亮度三個維度的,而HSV顏色空間恰好就是通過這三個維度來描述顏色的。因此,使用HSV空間處理圖像可以更直觀地調整顏色和進行色彩平衡等操作,更符合人類的感知習慣。

????????顏色調整更加直觀:在HSV顏色空間中,色調、飽和度和亮度的調整都是直觀的,而在RGB顏色空間中調整顏色不那么直觀。例如,在RGB空間中要調整紅色系的顏色,需要同時調整R、G、B三個通道的數值,而在HSV空間中只需要調整色調和飽和度即可。

????????降維處理有利于計算:在圖像處理中,降維處理可以減少計算的復雜性和計算量。HSV顏色空間相對于RGB顏色空間,減少了兩個維度(紅、綠、藍),這有利于進行一些計算和處理任務,比如色彩分割、匹配等。

因此,在進行圖片顏色識別時,我們會將RGB圖像轉換到HSV顏色空間,然后根據顏色區間來識別目標顏色。

5 RGB轉Gray(灰度)

?cv2.cvtColor 是OpenCV中的一個函數,用于圖像顏色空間的轉換。可以將一個圖像從一個顏色空間轉換為另一個顏色空間,比如從RGB到灰度圖,或者從RGB到HSV的轉換等。

cv2.cvtColor(img,code)

img 參數
????????可以傳入 NumPy 數組或 OpenCV 的 Mat 對象。Python 中 OpenCV 函數通常直接處理 NumPy 數組,OpenCV 會自動在 Mat 和數組之間轉換。例如?cv2.imread()返回的就是 NumPy 數組。

code 參數
????????用于指定顏色空間轉換類型。例如:

????????????????cv2.COLOR_RGB2GRAY?表示將 RGB 圖像轉為灰度圖

????????????????其他常見代碼包括?cv2.COLOR_BGR2RGB?等

示例代碼:

import cv2 as cv# 讀取圖像
img = cv.imread("../images/1.jpg")# 顏色轉換 cv.cvtColor(img, code, dst, dstCn)
# 轉灰度圖
dst = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("src", dst)# 轉HSV
dst1 = cv.cvtColor(img, cv.COLOR_BGR2HSV)
cv.imshow("HSV", dst1)# 轉RGB
dst2 = cv.cvtColor(img, cv.COLOR_BGR2RGB)
cv.imshow("RGB", dst2)cv.waitKey(0)

二、灰度實驗

????????彩色圖像轉換為灰度圖像(灰度化)是圖像處理和計算機視覺中的基礎操作,其核心是將RGB三通道信息融合為單通道數據。彩色圖像由紅(R)、綠(G)、藍(B)三通道組成,而灰度圖僅保留單一亮度通道。灰度化本質是通過數學映射將三維顏色空間壓縮為一維亮度值。

1 灰度圖

????????灰度圖像指每個像素僅包含單一采樣顏色的圖像,通常表現為從純黑到純白之間的連續過渡色調。盡管采樣顏色理論上可為任意色調的不同明度變化,甚至可呈現不同亮度下的異色效果,但實際應用中多采用可見光譜范圍內的亮度測量值。

????????黑白圖像(二值圖像)僅包含絕對黑與絕對白兩種顏色狀態。相比之下,灰度圖像具有豐富的過渡層次,通過在黑白之間設置多級顏色深度實現平滑的亮度漸變。典型計算機系統中,顯示用的灰度圖像采用8位非線性存儲格式,可精確記錄256級灰度值。

????????灰度圖像的生成通常基于單電磁波頻譜的像素亮度測量。每個像素點的數值對應特定亮度級別,這種線性或非線性量化過程保留了原始場景的光照信息。8位存儲方案通過二進制編碼實現高效的灰度等級存儲,其中0代表全黑,255代表全白。

2 最大值法

????????對于彩色圖像的每個像素,它會從R、G、B三個通道的值中選出最大的一個,并將其作為灰度圖像中對應位置的像素值。

例如某圖像中某像素點的像素值如上圖所示,那么在使用最大值法進行灰度化時,就會從該像素點對應的RGB通道中選取最大的像素值作為灰度值,所以在灰度圖中的對應位置上,該像素點的像素值就是121。

示例代碼:

import cv2 as cv
import numpy as np# 讀取圖像
pig = cv.imread("../images/pig.png")
shape = pig.shape
img = np.zeros((shape[0], shape[1]),  dtype=np.uint8)
# 循環遍歷每一行
for i in range(shape[0]):for j in range(shape[1]):img[i, j] = max(pig[i, j, 0], pig[i, j, 1], pig[i, j, 2])cv.imshow("pig", img)
cv.waitKey(0)
cv.destroyAllWindows()

3 平均值法

對于彩色圖像的每個像素,它會將R、G、B三個通道的像素值全部加起來,然后再除以三,得到的平均值就是灰度圖像中對應位置的像素值。

例如某圖像中某像素點的像素值如上圖所示,那么在使用平均值進行灰度化時,其計算結果就是(91+121+46)/3=86(對結果進行取整),所以在灰度圖中的對應位置上,該像素點的像素值就是86。 ?

示例代碼:

import cv2 as cv
import numpy as np# 讀取圖像
pig = cv.imread("../images/pig.png")
shape = pig.shape
img = np.zeros((shape[0], shape[1]),  dtype=np.uint8)# 循環遍歷每一行
for i in range(shape[0]):for j in range(shape[1]):# int():轉為更大的數據類型,防止溢出img[i, j] = np.uint8((int(pig[i, j, 0]) + int(pig[i, j, 1]) + int(pig[i, j, 2])) // 3)cv.imshow("pig", img)
cv.waitKey(0)
cv.destroyAllWindows()


4 加權均值法

????????對于彩色圖像的每個像素,它會按照一定的權重去乘以每個通道的像素值,并將其相加,得到最后的值就是灰度圖像中對應位置的像素值。本實驗中,權重的比例為: R乘以0.299,G乘以0.587,B乘以0.114,這是經過大量實驗得到的一個權重比例,也是一個比較常用的權重比例。

????????所使用的權重之和應該等于1。這是為了確保生成的灰度圖像素值保持在合理的亮度范圍內,并且不會因為權重的比例不當導致整體過亮或過暗。

例如某圖像中某像素點的像素值如上圖所示,那么在使用加權平均值進行灰度化時,其計算結果就是10*0.299+121*0.587+46*0.114=79。所以在灰度圖中的對應位置上,該像素點的像素值就是79。

代碼示例:?

import cv2 as cv
import numpy as np# 讀取圖像
pig = cv.imread("../images/pig.png")
shape = pig.shape
img = np.zeros((shape[0], shape[1]),  dtype=np.uint8)# 定義權重
wb, wg, wr = 0.114, 0.587, 0.299# 循環遍歷每一行
for i in range(shape[0]):for j in range(shape[1]):img[i, j] = round(wb * pig[i, j, 0] + wg * pig[i, j, 1] + wr * pig[i, j, 2])cv.imshow("pig", img)
cv.waitKey(0)
cv.destroyAllWindows()


5 兩個極端的灰度值

在灰度圖像中,“極端”的灰度值指的是亮度的兩個極端:最暗和最亮的值。

  • 最暗的灰度值:0。這代表完全黑色,在灰度圖像中沒有任何亮度。

  • 最亮的灰度值:255。這代表完全白色,在灰度圖像中具有最大亮度。

三、圖像二值化處理

二值圖像

????????將某張圖像的所有像素改成只有兩種值之一。 一幅二值圖像的二維矩陣僅由0、1兩個值構成,“0”代表黑色,“1”代白色。由于每一像素(矩陣中每一元素)取值僅有0、1兩種可能,所以計算機中二值圖像的數據類型通常為1個二進制位。二值圖像通常用于文字、線條圖的掃描識別(OCR)和掩膜圖像的存儲。

?

????????其操作的圖像也必須是灰度圖,也就是說,二值化的過程,就是將一張灰度圖上的像素根據某種規則修改為0和maxval(maxval表示最大值,一般為255,顯示白色)兩種像素值,使圖像呈現黑白的效果,能夠幫助我們更好地分析圖像中的形狀、邊緣和輪廓等特征。

????????簡便:降低計算量和計算需求,加快處理速度。

????????節約資源:二值圖像占用空間遠小于彩色圖。

????????邊緣檢測:二值化常作為邊緣檢測的預處理步驟,因為簡化后的圖易于識別出輪廓和邊界。

1~6是所有閾值法的解釋

_,binary = cv2.threshold(img,thresh,maxval,type)

????????img:輸入圖像,要進行二值化處理的灰度圖。

????????thresh:設定的閾值。當像素值大于(或小于,取決于閾值類型)thresh時,該像素被賦予的值。

????????type:閾值處理的類型。

返回值:

????????第一個值(通常用下劃線表示):計算出的閾值,若使用自適應閾值法,會根據算法自動計算出這個值。

????????第二個值(binary):二值化后的圖像矩陣。與輸入圖像尺寸相同。

在本實驗中,使用了六種不同的方式來對灰度圖進行二值化。


1 閾值法(THRESH_BINARY)

????????閾值法就是通過設置一個閾值,將灰度圖中的每一個像素值與該閾值進行比較,小于等于閾值的像素就被設置為0(通常代表背景),大于閾值的像素就被設置為maxval(通常代表前景)。對于我們的8位圖像(0~255)來說,通常是設置為255。

???????如上圖所示,在灰度圖中像素值較高的地方,如花瓣、花莖等地方的像素值比閾值高,那么在生成的二值化圖中的對應位置的像素值就會被設置為255,也就是純白色。

cv2.IMREAD_GRAYSCALE:OpenCV 中用于指定圖像加載模式的一個標志,它告訴 cv.imread() 函數以灰度格式讀取圖像。


示例代碼統一放在7下面

2 反閾值法(THRESH_BINARY_INV)

顧名思義,就是與閾值法相反。反閾值法是當灰度圖的像素值大于閾值時,該像素值將會變成0(黑),當灰度圖的像素值小于等于閾值時,該像素值將會變成maxval。

????????如上圖所示,使用反閾值法對灰度圖進行二值化時,會將灰度圖中像素值大于閾值的地方置為0(也就是黑),將灰度圖中像素值小于閾值的地方置為255(也就是白)。

示例代碼統一放在7下面

3 截斷閾值法(THRESH_TRUNC)

????????截斷閾值法,指將灰度圖中的所有像素與閾值進行比較,像素值大于閾值的部分將會被修改為閾值,小于等于閾值的部分不變。換句話說,經過截斷閾值法處理過的二值化圖中的最大像素值就是閾值。

?

當截斷閾值為255時,如上圖所示,可以看到灰度圖與二值化圖沒有任何的區別。

使用截斷閾值法進行圖像二值化處理時,設置的maxval參數實際上是不起作用的。

示例代碼統一放在7下面

4 低閾值零處理(THRESH_TOZERO)

????????低閾值零處理,字面意思,就是像素值小于等于閾值的部分被置為0(也就是黑色),大于閾值的部分不變。 ?

如上圖所示,在灰度圖中較亮的部分,其像素值比閾值大,所以在二值化后其像素值并沒有發生變化。而灰度圖中較暗的部分,也就是像素值較低的地方,由于像素值比閾值小,就會被置為0,對應二值化圖中的黑色部分。

示例代碼統一放在7下面

5 超閾值零處理(THRESH_TOZERO_INV)

????????超閾值零處理就是將灰度圖中的每個像素與閾值進行比較,像素值大于閾值的部分置為0(也就是黑色),像素值小于等于閾值的部分不變。

????????如上圖所示,在灰度圖中較亮的部分,其像素值比閾值大,所以在二值化后其像素值會被置為0(也就是黑色),對應二值化圖中的黑色部分。而灰度圖中較暗的部分,也就是像素值較低的地方,由于像素值比閾值小,將不會發生改變。

????????以上介紹的二值化方法都需要手動設置閾值,但是在不同的環境下,攝像頭拍攝的圖像可能存在差異,導致手動設置的閾值并不適用于所有圖像,這可能會導致二值化效果不理想。

????????因此,我們需要一種能自動計算每張圖片閾值的二值化方法,能夠根據每張圖像的特點自動計算出適合該圖像的二值化閾值,從而達到更好的二值化效果。這種二值化方法可以在不同環境下適用,提高圖像處理的準確性和魯棒性。

示例代碼統一放在7下面

6 OTSU閾值法

????????cv2.THRESH_OTS 并不是一個有效的閾值類型或標。THRESH_OTSU 本身并不是一個獨立的閾值化方法,而是與 OpenCV 中的二值化方法結合使用的一個標志。具體來說,THRESH_OTSU 通常與 THRESH_BINARY 或 THRESH_BINARY_INV 結合使用。在實際應用中,如果你使用 THRESH_OTSU 標志但沒有指定其他二值化類型,默認情況下它會與 THRESH_BINARY 結合使用。也就是說,當你僅指定了 cv2.THRESH_OTSU,實際上等同于同時指定了 cv2.THRESH_BINARY + cv2.THRESH_OTSU。


????????簡單來說就是cv2.THRESH_OTSU 是 OpenCV 中用于自動計算最優閾值的標志,但它需要與其他二值化方法(如 cv2.THRESH_BINARY 或 cv2.THRESH_BINARY_INV)結合使用。單獨指定該標志時,OpenCV 默認會將其與 cv2.THRESH_BINARY 組合。

????????在介紹OTSU閾值法之前,我們首先要了解一下雙峰圖片的概念。

????????雙峰圖片就是指灰度圖的直方圖上有兩個峰值,直方圖就是對灰度圖中每個像素值的點的個數的統計圖,如下圖所示。

灰度圖直方圖的基礎概念

  1. 灰度級

    • 在灰度圖像中,每個像素的值代表其亮度,通常范圍是 0 到 255(對于 8 位灰度圖像)。

    • 0 表示黑色,255 表示白色,中間的值表示不同程度的灰色。

  2. 直方圖定義

    • 直方圖是一個柱狀圖,其中 x 軸表示灰度級(從 0 到 255),y 軸表示對應灰度級在圖像中出現的次數(頻率)。

    • 每個柱子的高度代表該灰度級在圖像中出現的像素數量。

????????OTSU算法是通過一個值將這張圖分前景色和背景色(也就是灰度圖中小于這個值的是一類,大于這個值的是一類。例如,如果你設置閾值為128,則所有大于128的像素點可以被視作前景,而小于等于128的像素點則被視為背景。),通過統計學方法(最大類間方差)來驗證該值的合理性,當根據該值進行分割時,使用最大類間方差計算得到的值最大時,該值就是二值化算法中所需要的閾值。通常該值是從灰度圖中的最小值加1開始進行迭代計算,直到灰度圖中的最大像素值減1,然后把得到的最大類間方差值進行比較,來得到二值化的閾值。以下是一些符號規定:

T:閾值

N_{0}:前景像素點數

N_{1}:背景像素點數

\omega_{0}:前景的像素點數占整幅圖像的比例

\omega_{1}:背景的像素點數占整幅圖像的比例

\mathcal{U}0:前景的平均像素值

\mathcal{U}1:背景的平均像素值

\mathcal{U}:整幅圖的平均像素值

rows×cols:圖像的行數和列數

下面舉個例子,有一張大小為4×4的圖片,假設閾值T為1,那么:

?

????????也就是這張圖片根據閾值1分為了前景(像素為2的部分)和背景(像素為0)的部分,并且計算出了OTSU算法所需要的各個數據,根據上面的數據,我們給出計算類間方差的公式:

g=\omega_{0}(\mu_{0}-\mu)^{2}+\omega_{1}(\mu_{1}-\mu)^{2}

????????g就是前景與背景兩類之間的方差,這個值越大,說明前景和背景的差別就越大,效果就越好。OTSU算法就是在灰度圖的像素值范圍內遍歷閾值T,使得g最大,基本上雙峰圖片的閾值T在兩峰之間的谷底。

通過OTSU算法得到閾值之后,就可以結合上面的方法根據該閾值進行二值化,在本實驗中有THRESH_OTSU和THRESH_INV_OTSU兩種方法,就是在計算出閾值后結合了閾值法和反閾值法。

注意:使用OTSU算法計算閾值時,組件中的thresh參數將不再有任何作用。

示例代碼統一放在7下面

?

7 自適應二值化

cv2.adaptiveThreshold(image_np_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 7, 10)

????????與二值化算法相比,自適應二值化更加適合用在明暗分布不均的圖片,因為圖片的明暗不均,導致圖片上的每一小部分都要使用不同的閾值進行二值化處理,這時候傳統的二值化算法就無法滿足我們的需求了,于是就出現了自適應二值化。

????????自適應二值化方法會對圖像中的所有像素點計算其各自的閾值,這樣能夠更好的保留圖片里的一些信息。自適應二值化組件內容如下圖所示:

?

其中各個參數的含義如下:

?maxval :最大閾值,一般為255

?adaptiveMethod :小區域閾值的計算方式:

?ADAPTIVE_THRESH_MEAN_C :小區域內取均值

?ADAPTIVE_THRESH_GAUSSIAN_C :小區域內加權求和,權重是個高斯核

?thresholdType :二值化方法,只能使用THRESH_BINARY、THRESH_BINARY_INV,也就是閾值法和反閾值法

?blockSize :選取的小區域的面積,如7就是7\*7的小塊。

?c :最終閾值等于小區域計算出的閾值再減去此值

下面介紹一下這兩種方法。

7.1.取均值

比如一張圖片的左上角像素值如下圖所示:

????????假如我們使用的小區域是3*3的,那么就會從圖片的左上角開始(也就是像素值為162的地方)計算其鄰域內的平均值,如果處于邊緣地區就會對邊界進行填充,填充值就是邊界的像素點,如下圖所示:

?

????????那么對于左上角像素值為162的這個點,161(也就是上圖中括號內的計算結果,結果會進行取整)就是根據平均值計算出來的閾值,接著減去一個固定值C,得到的結果就是左上角這個點的二值化閾值了,接著根據選取的是閾值法還是反閾值法進行二值化操作。緊接著,向右滑動計算每個點的鄰域內的平均值,直到計算出右下角的點的閾值為止。我們所用到的不斷滑動的小區域被稱之為核,比如3*3的小區域叫做3*3的核,并且核的大小都是奇數個,也就是3*3、5*5、7*7等。

????????自適應二值化(Adaptive Thresholding)的核心思想就是為圖像中的每個像素點計算一個局部閾值。這種方法與全局閾值化不同,后者對整個圖像使用同一個固定的閾值。而在自適應二值化中,每個像素的閾值是基于其周圍鄰域內的像素值動態確定的。


7.2.加權求和

對小區域內的像素進行加權求和得到新的閾值,其權重值來自于高斯分布。

高斯分布,通過概率密度函數來定義高斯分布,一維高斯概率分布函數為:

p(y)={\frac{1}{\sigma{\sqrt{2\pi}}}}e^{?{\frac{-(y-\mu)^{2}}{2\sigma^{2}}}}

通過改變函數中和的值,我們可以得到如下圖像,其中均值為\mu,標準差為\sigma^{2}

此時我們拓展到二維圖像,一般情況下我們使x軸和y軸的相等并且,此時我們可以得到二維高斯函數的表達式為:

g(x,y)=\frac{1}{2\pi\sigma ^{2}}e^{-\frac{(x^{2}+y^{2})}{2\sigma^{2}}}

高斯概率函數是相對于二維坐標產生的,其中(x,y)為點坐標,要得到一個高斯濾波器模板,應先對高斯函數進行離散化,將得到的值作為模板的系數。例如:要產生一個3*3的高斯權重核,以核的中心位置為坐標原點進行取樣,其周圍的坐標如下圖所示(x軸水平向右,y軸豎直向上)

將坐標帶入上面的公式中,即可得到一個高斯權重核。

而在opencv里,當kernel(小區域)的尺寸為1、3、5、7并且用戶沒有設置sigma的時候(sigma <= 0),核值就會取固定的系數,這是一種默認的值是高斯函數的近似。

kernel尺寸核值
1[1]
3[0.25, 0.5, 0.25]
5[0.0625, 0.25, 0.375, 0.25, 0.0625]
7[0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125]

比如kernel的尺寸為3*3時,使用

\left[\begin{array}{c}{?{0.25}}\\ {?{0.5}}\\ {?{0.25}}\end{array}\right]\times\left[0.25~~~~0.5~~~~0.25\right]

進行矩陣的乘法,就會得到如下的權重值,其他的類似。

kernel=\left[\begin{array}{c}{?{0.0625~~~0.125~~~0.0625}}\\{?{0.125~~~~0.25~~~~0.125}}\\ {?{0.0625~~~0.125~~~0.0625}} \end{array}\right]

通過這個高斯核,即可對圖片中的每個像素去計算其閾值,并將該閾值減去固定值得到最終閾值,然后根據二值化規則進行二值化。

而當kernels尺寸超過7的時候,如果sigma設置合法(用戶設置了sigma),則按照高斯公式計算.當sigma不合法(用戶沒有設置sigma),則按照如下公式計算sigma的值:

\sigma=0.3*\big((k s i z e-1)*0.5-1\big)+0.8

某像素點的閾值計算過程如下圖所示:

?

首先還是對邊界進行填充,然后計算原圖中的左上角(也就是162像素值的位置)的二值化閾值,其計算過程如上圖所示,再然后根據選擇的二值化方法對左上角的像素點進行二值化,之后核向右繼續計算第二個像素點的閾值,第三個像素點的閾值…直到右下角(也就是155像素值的位置)為止。

當核的大小不同時,僅僅是核的參數會發生變化,計算過程與此是一樣的。

cv2.adaptiveThreshold參數解釋:

1. image_np_gray: 輸入圖像,這里必須是灰度圖像(單通道)。

2. 255: 輸出圖像的最大值。在二值化后,超過自適應閾值的像素會被設置為該最大值,通常為255表示白色;未超過閾值的像素將被設置為0,表示黑色。

3. cv2.ADAPTIVE_THRESH_GAUSSIAN_C: 自適應閾值類型。在這個例子中,使用的是高斯加權的累計分布函數(CDF),并添加一個常數 C 來計算閾值。另一種可選類型是 cv2.ADAPTIVE_THRESH_MEAN_C,它使用鄰域內的平均值加上常數 C 計算閾值。

4. cv2.THRESH_BINARY: 輸出圖像的類型。這意味著輸出圖像將會是一個二值圖像(binary image),其中每個像素要么是0要么是最大值(在這里是255)。另外還有其他選項如 cv2.THRESH_BINARY_INV 會得到相反的二值圖像。

5. 7: blockSize 參數,表示計算每個像素閾值時所考慮的7x7鄰域大小(正方形區域的寬度和高度),其值必須是奇數。

6. 10: C 參數,即上面提到的常數值,在計算自適應閾值時與平均值或高斯加權值相加。正值增加閾值,負值降低閾值,具體效果取決于應用場景。

二值化代碼示例:

import cv2 as cv
# 讀圖
flower = cv.imread('../images/flower.png')flower = cv.resize(flower, (0, 0), fx=0.5, fy=0.5)
# 灰度化
gray = cv.cvtColor(flower, cv.COLOR_BGR2GRAY)
cv.imshow("1", gray)
# 二值化  閾值法
ret, binary1 = cv.threshold(gray, 127, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
# cv.imshow('binary1', binary1)# 二值化  反閾值法
_, binary_inv = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)
# cv.imshow('binary2', binary_inv)# 二值化 截斷閾值法
_, binary_trunc = cv.threshold(gray, 127, 255, cv.THRESH_TRUNC)
# cv.imshow('binary3', binary_trunc)# 二值化   低閾值零處理
_, binary_tozero = cv.threshold(gray, 127, 255, cv.THRESH_TOZERO)
# cv.imshow('binary4', binary_tozero)# 二值化   超閾值零處理
_, binary_tozero_inv = cv.threshold(gray, 127, 255, cv.THRESH_TOZERO_INV)
# cv.imshow('binary5', binary_tozero_inv)# OTSU閾值法  默認結合cv.THRESH_BINARY  cv.THRESH_OTSU = cv.THRESH_BINARY + cv.THRESH_OTSU
_, binary_otsu = cv.threshold(gray, 200, 255, cv.THRESH_OTSU)
# cv.imshow('binary_otsu', binary_otsu)_, binary_otsu1 = cv.threshold(gray, 200, 255, cv.THRESH_OTSU + cv.THRESH_BINARY_INV)
# cv.imshow('binary_otsu1', binary_otsu1)# 自適應二值化  小區域計算  必須結合閾值法或者反閾值法,否則會報錯,但只能結合一個
# 取均值
binary_adaptive = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 9, 6)
cv.imshow('binary_adaptive', binary_adaptive)# 加權均值法 高斯核
binary_adaptive_gaussian = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 9, 6)
cv.imshow('binary_adaptive_gaussian', binary_adaptive_gaussian)cv.waitKey(0)
cv.destroyAllWindows()

四、圖像變換操作

1.圖像翻轉(圖像鏡像旋轉)

在OpenCV中,圖片的鏡像旋轉是以圖像的中心為原點進行鏡像翻轉的。

  • cv2.flip(img,flipcode)

  • 參數

    • img: 要翻轉的圖像

    • flipcode: 指定翻轉類型的標志

      • flipcode=0: 垂直翻轉,圖片像素點沿x軸翻轉

      • flipcode>0: 水平翻轉,圖片像素點沿y軸翻轉

      • flipcode<0: 水平垂直翻轉,水平翻轉和垂直翻轉的結合

import cv2 as cvface = cv.imread("../images/gezi.png")
face = cv.resize(face, (0, 0), fx=0.5, fy=0.5)
cv.imshow("face", face)# flipcode = 0 表示垂直翻轉  沿著x軸翻轉 上下翻轉 1 表示水平翻轉 沿著y軸翻轉 左右翻轉
filp_0 = cv.flip(face, 0)
cv.imshow("filp_0", filp_0)
filp_1 = cv.flip(face, 1)
cv.imshow("filp_1", filp_1)
filp_2 = cv.flip(face, -1)
cv.imshow("filp_2", filp_2)cv.waitKey(0)
cv.destroyAllWindows()

2. 圖像仿射變換

仿射變換(Affine Transformation)是一種線性變換,保持了點之間的相對距離不變。

仿射變換的基本性質

  • 保持直線

  • 保持平行

  • 比例不變性

  • 不保持角度和長度

常見的仿射變換類型

  • 旋轉:繞著某個點或軸旋轉一定角度。

  • 平移:僅改變物體的位置,不改變其形狀和大小。

  • 縮放:改變物體的大小。

  • 剪切:使物體發生傾斜變形。

仿射變換的基本原理

  • 線性變換

  • 二維空間中,圖像點坐標為(x,y),仿射變換的目標是將這些點映射到新的位置 (x', y')。

  • 為了實現這種映射,通常會使用一個矩陣乘法的形式:

    (類似于y=kx+b)

?

  • a,b,c,d 是線性變換部分的系數,控制旋轉、縮放和剪切。

  • t_xt_y是平移部分的系數,控制圖像在平面上的移動。

  • 輸入點的坐標被擴展為齊次坐標形式[x,y,1],以便能夠同時處理線性變換和平移

cv2.warpAffine()函數

  • 仿射變換函數

cv2.warpAffine(img,M,dsize)
  • g:輸入圖像。
  • M:2x3的變換矩陣,類型為np.float32。
  • dsize:輸出圖像的尺寸,形式為(width,height)。

?

3. 圖像旋轉

旋轉圖像可以將圖像繞著某個點旋轉一定的角度。

cv2.getRotationMatrix2D()函數

  • 獲取旋轉矩陣

    cv2.getRotationMatrix2D(center,angle,scale)
    • center:旋轉中心點的坐標,格式為(x,y)

    • angle:旋轉角度,單位為度,正值表示逆時針旋轉負值表示順時針旋轉。

    • scale:縮放比例,若設為1,則不縮放。

    • 返回值M,2x3的旋轉矩陣。

import cv2 as cvcat = cv.imread("../images/cat1.png")
cat = cv.resize(cat, (520, 520))# 獲取旋轉矩陣 cv2.getRotationMatrix2D(旋轉中心center,旋轉角度angle,縮放因子scale)
matrix = cv.getRotationMatrix2D((260, 260), -45, 1)# 仿射變換 cv2.warpAffine(src, M, dsize)  (w, h)
result = cv.warpAffine(cat, matrix, (520, 520))
cv.imshow("result", result)cv.waitKey(0)
cv.destroyAllWindows()

4. 圖像平移

移操作可以將圖像中的每個點沿著某個方向移動一定的距離。

  • 假設我們有一個點 P(x,y),希望將其沿x軸方向平移t_x*個單位,沿y軸方向平移t_y個單位到新的位置P′(x′,y′),那么平移公式如下:

    x′=x+tx

    y′=y+ty

    在矩陣形式下,該變換可以表示為:

?這里的t_xt_y分別代表在x軸和y軸上的平移量。

import cv2 as cv
import numpy as npcat = cv.imread("../images/cat1.png")
cat = cv.resize(cat, (520, 520))# 定義平移量
tx = 80
ty = 120# 定義平移矩陣
M = np.float32([[1, 0, tx], [0, 1, ty]])
# 仿射變換
dst = cv.warpAffine(cat, M, (400, 400))
cv.imshow("result", dst)
cv.waitKey(0)
cv.destroyAllWindows()


5. 圖像縮放

縮放操作可以改變圖片的大小。

  • 假設要把圖像的寬高分別縮放為0.5和0.8,那么對應的縮放因子sx=0.5,sy=0.8。

  • 點P(x,y)對應到新的位置P'(x',y'),縮放公式為:

    在矩陣形式下,該變換可以表示為

?相較于圖像旋轉中只能等比例的縮放,圖像縮放更加靈活,可以在指定方向上進行縮放。?

sx和sy分別表示在x軸和y軸方向上的縮放因子。

import cv2 as cv
import numpy as npcat = cv.imread("../images/cat1.png")
cat = cv.resize(cat, (520, 520))# 縮小量
sx = 0.5
sy = 0.5# 定義平移矩陣
M = np.float32([[sx, 0, 0], [0, sy, 0]])# 仿射變換
dst = cv.warpAffine(cat, M, (400, 400))
cv.imshow("result", dst)
cv.waitKey(0)
cv.destroyAllWindows()

總結

? ? ? ? 今天內容有點多,我覺得重要的地方是理解公式的含義,只要知道方法,大多內容都通了,圖像變換操作部分,主要理解矩陣里面每個數字代表的含義和矩陣是如何運算的,多數的問題就都能理解了,今天依舊努力學習/.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/92918.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/92918.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/92918.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

經典IDE之Turbo C

寫的程序不多&#xff0c;換過的 IDE 不少&#xff0c;本文將列舉曾經用過的不同 C 語言相關的 IDE 環境&#xff0c;既是紀念&#xff0c;也是回憶。值得注意的是 IDE 的出現是為了提高開發效率&#xff0c;有一個相對成熟的編譯環境和程序。從編程的角度來看&#xff0c;過分…

Go 多模塊倉庫標簽管理教程

為了方便自己開發&#xff0c;自己寫了個小工具&#xff1a;DzhGO 代碼生成工具 功能特點標題 初始化項目基礎結構生成插件模塊代碼生成模型和實體代碼生成服務接口和實現代碼支持 admin 和 app 兩種模塊類型生成項目基礎目錄 具體介紹看倉庫&#xff1a; https://github.co…

IDEA 類上方注釋 簽名

File -->settings–>Editor–>File and Code Templates–>class新建 Class 類上方添加內容&#xff1a;/*** author Jagger* since ${DATE} ${TIME}*/

衛星通信終端天線對星之:參考星對星

我們在前面的文章中介紹了3種衛星通信終端的對星模式&#xff0c;分別是&#xff1a; 衛星通信終端天線的5種對星模式之一&#xff1a;信標跟蹤 衛星通信終端天線的5種對星模式之二&#xff1a;功率檢測型載波跟蹤 衛星通信終端天線的5種對星模式之二&#xff1a;DVB跟蹤 今…

來自麻省理工和AI制藥公司 Recursion 的結構與結合親和力預測模型Boltz-2,解決小分子藥物發現的關鍵問題

1. Boltz-2介紹 文章來源&#xff1a;http://jeremywohlwend.com/assets/boltz2.pdf 開源代碼來源&#xff1a;https://github.com/jwohlwend/boltz 該AI模型由麻省理工學院計算機科學與人工智能實驗室與上市AI制藥公司Recursion一起開發&#xff0c;雙方在Boltz-1的基礎之上…

從零用java實現 小紅書 springboot vue uniapp(14) 集成阿里云短信驗證碼

從零用java實現 小紅書 springboot vue uniapp&#xff08;14&#xff09; 集成阿里云短信驗證碼 移動端演示 http://8.146.211.120:8081/#/ 管理端演示 http://8.146.211.120:8088/#/ 項目整體介紹及演示 前言 在現代應用中&#xff0c;手機號不僅是用戶的唯一標識&#xff0…

`<< EOF` 與 `<< ‘EOF‘` 與 `<< “EOF“`有無引號的區別多回答筆記250722

<< EOF 與 << EOF 與 << "EOF"有無引號的區別多回答筆記250722 實測 自測代碼: # 定義變量 hello"ni hao"# 無引號 tee << EOF # 無引號 ${hello} world \n $(date) # 無引號 EOF# 單引號 tee << EOF # 單…

點擊按鈕滾動到底功能vue的v-on:scroll運用

使用vue自帶的監聽滾動功能v-on:scroll&#xff0c;滾動條變化時&#xff0c;會調用方法 checkScrollStatus&#xff0c;如果滾動條在容器底部時&#xff0c;則隱藏按鈕&#xff0c;否則顯示按鈕&#xff0c;點擊按鈕能一鍵滾動到底部。<div class"chat-area" ref…

Linux下編譯SLEPc

本文記錄在Linux下編譯安裝SLEPc的流程。 一、下載代碼 git clone https://github.com/slepc/slepc.git cd ./slepc二、安裝依賴 2.1 安裝PETSc 參見: <Linux下編譯安裝PETSc> 2.2 安裝intel oneAPI sudo apt install intel-oneapi-base-toolkit sudo apt install i…

【無標題】qwen3-8b 強化學習訓練后的模型,可以接著 進行其他grpo 強化學習訓練 嗎

ser_count’, 0),)} {((‘valid_user_count’, 1),)} 44 0.0 88 [0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.0, 0.6, 0.0, 0.6, 0.0, 0.6] 55 100%|???{‘loss’: 0.0132, ‘grad_norm’: 0.07552657276391983, ‘learning_rate’: 2e-06, ‘num_tokens’: 2098…

IDC權威認可:瑞數信息雙項入選《中國大模型安全保護市場概覽》

近日&#xff0c;國際數據公司IDC正式發布了《中國大模型安全保護市場概覽&#xff0c;2025&#xff1a;全方位安全檢測與防護構建可信AI》報告。本次報告中IDC結合全球統一定義以及中國市場特色&#xff0c;將中國大模型安全保護市場劃分為7個細分領域&#xff0c;并通過對中國…

多智能體(Multi-agent)策略模式:思維鏈CoT和ReAct

參考&#xff1a;https://zhuanlan.zhihu.com/p/704523060 &#x1f3af; 一句話記住 CoT&#xff1a;像“考試時在草稿紙上寫完所有步驟&#xff0c;再抄答案”。ReAct&#xff1a;像“玩密室逃脫&#xff0c;每開一個箱子就去找下一個線索”。 用小學生能聽懂的話 兩個小故事…

ChatGPT指令大全:輸入需求=輸出完整方案

ChatGPT指令大全提供數百個精煉過的指令語句 (提示詞)&#xff0c;讓你充分發揮 ChatGPT 的強大功能 一、核心功能模塊分類 1. 求職與面試 簡歷優化 專業反饋&#xff1a;按面試官視角分析簡歷并提出改進建議量化數據&#xff1a;為經歷添加具體數字&#xff08;如提升效率30…

Java零基礎入門學習知識點2-JDK安裝配置+Maven

文章目錄版本提示參考視頻Maven環境準備一、安裝Java開發工具包&#xff08;JDK&#xff09;二、JDK環境配置三、下載Maven安裝包*四、Maven環境配置&#xff08;可省略&#xff09;*五、驗證安裝&#xff08;上一步沒做&#xff0c;這步無法驗證&#xff0c;可省&#xff09;六…

基于單片機智能衣柜/智能衣櫥設計

傳送門 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目速選一覽表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目功能速覽 概述 本設計實現了一種基于單片機的多功能智能衣柜&#xff0c;融合環境檢測、安全防護與用戶交互功能…

自動語音識別(ASR)技術詳解

語音識別&#xff08;Automatic Speech Recognition, ASR&#xff09;是人工智能和自然語言處理領域的重要技術&#xff0c;旨在將人類的語音信號轉換為對應的文本。近年來&#xff0c;深度學習的突破推動語音識別系統從實驗室走入日常生活&#xff0c;為智能助手、實時翻譯、醫…

【MySQL】MySQL 事務和鎖詳解

一、MySQL 事務 1.1 事務介紹 在 MySQL 中&#xff0c;事務&#xff08;Transaction&#xff09; 是一組不可分割的 SQL 操作序列&#xff0c;這些操作要么全部成功執行&#xff0c;要么全部失敗回滾&#xff0c;以此保證數據庫操作的完整性和一致性。 事務將數據庫從一種一致…

虛擬直線閾值告警人員計數算法暑期應用

智慧人員計數助力暑期&#xff1a;技術賦能安全管理的創新實踐一、背景&#xff1a;暑期人流激增下的安全管理挑戰暑期是旅游、商業、交通等場景的客流高峰期&#xff0c;人員密集區域易引發踩踏事故、管理混亂等安全隱患。傳統人工計數方式效率低、誤差大&#xff0c;難以滿足…

SQL164 2021年11月每天新用戶的次日留存率

SQL164 2021年11月每天新用戶的次日留存率 思路 ?找出新用戶?&#xff1a;確定每個用戶首次活躍的日期&#xff08;即新用戶&#xff09; 例如101用戶在11月1日首次出現 ?處理跨天活躍?&#xff1a;考慮用戶可能跨天活躍的情況&#xff08;in_time和out_time不在同一天&a…

基于單片機的數字電壓表設計

2 系統原理及基本框圖 如圖2.1所示&#xff0c;模擬電壓經過檔位切換到不同的分壓電路衰減后&#xff0c;經隔離干擾送到A/D轉換器進行A/D轉換&#xff0c;然后送到單片機中進行數據處理。處理后的數據送到LCD中顯示&#xff0c;同時通過串行通訊與上位機通信。圖2.1系統基本方…