OpenCV-圖像預處理?【圖像顏色空間轉換、灰度化實驗、二值化處理、鏡像翻轉 和 仿射變換】

文章目錄

  • 先言
  • 一、圖像顏色空間轉換
    • 1.RGB顏色空間
    • 2.顏色加法
    • 3.顏色加權加法
    • 4.HSV顏色空間
    • 5.圖像轉換(cvtColor())
  • 二、灰度實驗
    • 1.灰度圖
    • 2.圖像灰度化(最大值法)
    • 3.圖像灰度化(平均值法)
    • 4.圖像灰度化(加權平均值法)
  • 三、圖像二值化
    • 1.閾值法(THRESH_BINARY)和反閾值法(THRESH_BINARY_INV)
    • 2.截斷閾值法(THRESH_TRUNC)
    • 3.低閾值零處理(THRESH_TOZERO)與超閾值零處理(THRESH_TOZERO_INV)
    • 4.OTSU閾值法(threshold())
    • 5.自適應二值化(adaptiveThreshold())
  • 四、圖像鏡像翻轉與仿射變換
    • 1.圖像翻轉(圖像鏡像旋轉)
    • 2.圖像旋轉
    • 3.圖像平移
    • 4.圖像縮放
  • 結語


先言

在計算機視覺任務中,圖像預處理是至關重要的一環。無論是目標檢測、人臉識別還是圖像分類,原始圖像數據往往需要經過一系列變換才能更好地被算法理解。OpenCV 提供了強大的圖像處理工具,幫助我們高效完成這些預處理操作。

本文將重點介紹 圖像顏色空間轉換、灰度化實驗、二值化處理、鏡像翻轉 和 仿射變換 等核心預處理技術,通過代碼示例和效果對比,帶你掌握如何用 OpenCV 優化圖像數據


一、圖像顏色空間轉換

OpenCV中,圖像色彩空間轉換是一個非常基礎且重要的操作,就是將圖像從一種顏色表示形式轉換為另一種表示形式的過程。通過將圖像從一個色彩空間轉換到另一個色彩空間,可以更好地進行特定類型的圖像處理和分析任務。常見的顏色空間包括RGB、HSV、YUV等。

  • 色彩空間轉換的作用

    • 提高圖像處理效果

    • 節省計算資源

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操作添加兩個圖像,如res = img1 + img2。兩個圖像應該具有相同的大小和類型。

cv.add() 飽和運算:

import cv2 as cv
#讀取兩個圖像
cao = cv.imread("../images/cao.png")
pig = cv.imread("../images/pig.png")
#cv的飽和操作add(img1,img2)
dst1 = cv.add(cao,pig)
cv.imshow("add",dst1)
cv.waitKey(0)
cv.destroyAllWindows()

numpy 直接加法:

import cv2 as cv
import numpy as np#讀取圖像
cao = cv.imread("../images/cao.png")
pig = cv.imread("../images/pig.png")
#numpy直接相加,取模運算 對256取模 250+10=4
dst2 = cao+pig
cv.imshow("numpy",dst2)
cv.waitKey(0)
cv.destroyAllWindows()

OpenCV加法和Numpy加法之間存在差異。OpenCV的加法是飽和操作,而Numpy添加是模運算。

3.顏色加權加法

cv2.addWeighted(src1,alpha,src2,deta,gamma)
  • src1src2:輸入圖像。
  • alphabeta:兩張圖象權重。
  • 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 + γ

示例:

import cv2 as cv
#讀取圖像
cao = cv.imread("../images/cao.png")
pig = cv.imread("../images/pig.png")
#加權顏色加法cv.addWeighted(img1,alpha,img2,beta,gamma)
dst3 = cv.addWeighted(cao,0.5,pig,0.6,15)
cv.imshow("addWeighted",dst3)
cv.waitKey(0)
cv.destroyAllWindows()

4.HSV顏色空間

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.圖像轉換(cvtColor())

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

  cv2.cvtColor(img,code)
  • img:輸入圖像,可以是一個Numpy數組繪著一個OpenCV的Mat對象
    • Mat 是一個核心的數據結構,主要用于存儲圖像和矩陣數據。在 Python 中使用 OpenCV 時,通常直接處理的是 NumPy 數組,cv2 模塊自動將 Mat 對象轉換為 NumPy 數組。二者之間的轉換是透明且自動完成的。例如,當你使用 cv2.imread() 函數讀取圖像時,返回的是一個 NumPy 數組,但在C++中則是 Mat 對象。
  • code:指定轉換的類型,可以使用預定義的轉換代碼。
    • 例如cv2.COLOR_RGB2GRAY表示從rgb到灰度圖像的轉換。

代碼示例

import cv2 as cv
#讀取圖像
img = cv.imread("../images/1.jpg")
#顏色轉換 cv.cvtColor(img,code)code這里表示轉化模式
#BGR to GRAY
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
#BGR to HSV
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
#BGR to RGB
rgb = cv.cvtColor(img,cv.COLOR_BGR2RGB)
cv.imshow("gray",gray)
cv.imshow("hsv",hsv)
cv.imshow("rgb",rgb)
cv.waitKey(0)
cv.destroyAllWindows()

二、灰度實驗

將彩色圖像轉換為灰度圖像的過程稱為灰度化,這種做法在圖像處理和計算機視覺領域非常常見。

灰度圖與彩色圖最大的不同就是:彩色圖是由R、G、B三個通道組成,而灰度圖只有一個通道,也稱為單通道圖像,所以彩色圖轉成灰度圖的過程本質上就是將R、G、B三通道合并成一個通道的過程。本實驗中一共介紹了三種合并方法,分別是最大值法、平均值法以及加權均值法。

1.灰度圖

每個像素只有一個采樣顏色的圖像,這類圖像通常顯示為從最暗黑色到最亮的白色的灰度,盡管理論上這個采樣可以任何顏色的不同深淺,甚至可以是不同亮度上的不同顏色。灰度圖像與黑白圖像不同,在計算機圖像領域中黑白圖像只有黑色與白色兩種顏色;但是,灰度圖像在黑色與白色之間還有許多級的顏色深度。灰度圖像經常是在單個電磁波頻譜如可見光內測量每個像素的亮度得到的,用于顯示的灰度圖像通常用每個采樣像素8位的非線性尺度來保存,這樣可以有256級灰度。

import cv2 as cv
#讀取圖像
img = cv.imread("../images/1.jpg")
#顏色轉換 cv.cvtColor(img,code)
#BGR to GRAY
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
print(gray.shape)    #shape:(h,w)

在上述代碼中將一張BGR圖像轉為灰度圖查看他的維度,發現這是一張二維圖像,原本的三通道(一維數組)轉換為一個零維常量(指8位非線性尺寸0~255)儲存在二維數組中

2.圖像灰度化(最大值法)

實現對彩色圖像的灰度化有三種方式,其中最大值法對于彩色圖像的每個像素,它會從R、G、B三個通道的值中選出最大的一個,并將其作為灰度圖像中對應位置的像素值。
代碼如下(示例):

import cv2 as cv
import numpy as np
#讀取圖像
src = cv.imread("../images/lvbo3.png")
#創建一個新的圖像,用于保存結果
img = np.zeros((src.shape[0],src.shape[1]),dtype=src.dtype)
#循環遍歷圖像的每一個像素
for i in range(src.shape[0]):for j in range(src.shape[1]):# #修改像素值img[i,j]=max(src[i,j,0],src[i,j,1],src[i,j,2])
cv.imshow("result",img)
cv.waitKey(0)
cv.destroyAllWindows()

3.圖像灰度化(平均值法)

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

import cv2 as cv
import numpy as np
#讀取圖像
src = cv.imread("../images/lvbo3.png")
#創建一個新的圖像,用于保存結果
img = np.zeros((src.shape[0],src.shape[1]),dtype=src.dtype)
#循環遍歷圖像的每一個像素
for i in range(src.shape[0]):for j in range(src.shape[1]):#轉為更大的數據類型,防止溢出img[i,j]=(int(src[i,j,0])+int(src[i,j,1])+int(src[i,j,2]))//3
cv.imshow("result",img)
cv.waitKey(0)
cv.destroyAllWindows()

4.圖像灰度化(加權平均值法)

對于彩色圖像的每個像素,它會按照一定的權重去乘以每個通道的像素值,并將其相加,得到最后的值就是灰度圖像中對應位置的像素值。本實驗中,權重的比例為: R乘以0.299,G乘以0.587,B乘以0.114,這是經過大量實驗得到的一個權重比例,也是一個比較常用的權重比例(在上面講到對圖像顏色空間轉換的cvtColor函數cv.COLOR_BGR2GRAY實現的圖像灰度化比例一致)。

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

import cv2 as cv
import numpy as np
#讀取圖像
src = cv.imread("../images/lvbo3.png")
#創建一個新的圖像,用于保存結果
img = np.zeros((src.shape[0],src.shape[1]),dtype=src.dtype)
#定義權重
wb,wg,wr = 0.114,0.587,0.299
#循環遍歷圖像的每一個像素
for i in range(src.shape[0]):for j in range(src.shape[1]):img[i,j] = round(wb*src[i,j,0]+wg*src[i,j,1]+wr*src[i,j,2])
cv.imshow("result",img)
cv.waitKey(0)
cv.destroyAllWindows()

三、圖像二值化

圖像二值化處理:將某張圖像的所有像素改成只有兩種值之一

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

在這里插入圖片描述

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

  • 簡便:降低計算量和計算需求,加快處理速度。
  • 節約資源:二值圖像占用空間遠小于彩色圖。
  • 邊緣檢測:二值化常作為邊緣檢測的預處理步驟,因為簡化后的圖易于識別出輪廓和邊界。

1.閾值法(THRESH_BINARY)和反閾值法(THRESH_BINARY_INV)

全局閾值法:

  _,binary = cv2.threshold(img,thresh,maxval,type)
  • img:輸入圖像,要進行二值化處理的灰度圖。
  • thresh:設定的閾值。當像素值大于(或小于,取決于閾值類型)thresh時,該像素被賦予的值。
  • type:閾值處理的類型。
  • 返回值:
    • 第一個值(通常用下劃線表示):計算出的閾值,若使用自適應閾值法,會根據算法自動計算出這個值。
    • 第二個值(binary):二值化后的圖像矩陣。與輸入圖像尺寸相同。

代碼如下(示例):

import cv2 as cv
#讀取圖像
flower = cv.imread('../images/flower.png')
#灰度處理
gray = cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
gray = cv.resize(gray,(400,400))#二值化處理 閾值法(大于閾值為maxval,小于閾值為0)
_, binary = cv.threshold(gray,200,255,cv.THRESH_BINARY)
cv.imshow("binary",binary)#二值化處理 反閾值法(大于閾值的為0,小于閾值為maxval)
_, inv = cv.threshold(gray,200,255,cv.THRESH_BINARY_INV)
cv.imshow("inv",inv)
cv.waitKey(0)
cv.destroyAllWindows()

運行結果:
在這里插入圖片描述

2.截斷閾值法(THRESH_TRUNC)

截斷閾值法,指將灰度圖中的所有像素與閾值進行比較,像素值大于閾值的部分將會被修改為閾值,小于等于閾值的部分不變(當閾值為255時二值化處理的灰度圖與原灰度圖沒有區別)。

換句話說,經過截斷閾值法處理過的二值化圖中的最大像素值就是閾值。
代碼如下(示例):

import cv2 as cv
#讀取圖像
flower = cv.imread('../images/flower.png')
#灰度處理
gray = cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
gray = cv.resize(gray,(400,400))
#截斷閾值法(大于閾值等于閾值,小于閾值不變)
_, trunc = cv.threshold(gray,200,0,cv.THRESH_TRUNC)
cv.imshow("trunc",trunc)
cv.waitKey(0)
cv.destroyAllWindows()

使用截斷閾值法進行圖像二值化處理時,設置的maxval參數實際上是不起作用的(如圖):
在這里插入圖片描述

3.低閾值零處理(THRESH_TOZERO)與超閾值零處理(THRESH_TOZERO_INV)

  • 低閾值零處理,像素值小于等于閾值的部分被置為0(黑色),像素值大于閾值部分不變。
  • 超閾值零處理,像素值大于閾值的部分置為0(黑色),像素值小于等于閾值的部分不變。

代碼如下(示例):

import cv2 as cv
#讀取圖像
flower = cv.imread('../images/flower.png')
#灰度處理
gray = cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
gray = cv.resize(gray,(400,400))
#低閾值零處理(低于閾值為0,高于閾值不變)
_, tozero = cv.threshold(gray,127,0,cv.THRESH_TOZERO)
cv.imshow("tozero",tozero)
#超閾值零處理(高于閾值為0,低于閾值不變)
_, tozero_inv = cv.threshold(gray,127,0,cv.THRESH_TOZERO_INV)
cv.imshow("tozero_inv",tozero_inv)
cv.waitKey(0)
cv.destroyAllWindows()

運行結果如下:
在這里插入圖片描述

4.OTSU閾值法(threshold())

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

代碼如下(示例):

import cv2 as cv
#讀取圖像
flower = cv.imread('../images/flower.png')
#灰度處理
gray = cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
gray = cv.resize(gray,(400,400))#OTSU閾值法(thresh)由函數計算得到,默認結合閾值法
_,otsu = cv.threshold(gray,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
cv.imshow("otsu",otsu)
#OTSU結合反閾值法
_,otsu_inv = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)
cv.imshow("otsu_inv",otsu_inv)
cv.waitKey(0)
cv.destroyAllWindows()

運行結果:
在這里插入圖片描述

5.自適應二值化(adaptiveThreshold())

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

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:最終閾值等于小區域計算出的閾值再減去此值

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

  • 取均值法
    假如我們使用的小區域是3*3的,那么就會從圖片的左上角開始(也就是像素值為162的地方)計算其鄰域內的平均值,如果處于邊緣地區就會對邊界進行填充,填充值就是邊界的像素點,如下圖所示:
    在這里插入圖片描述
    代碼如下(示例):
import cv2 as cv
#讀取圖像
flower = cv.imread('../images/flower.png')
#灰度處理
gray = cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
gray = cv.resize(gray,(400,400))
#均值法
mean = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,11,2)
cv.imshow("mean",mean)
cv.waitKey(0)
cv.destroyAllWindows()
  • 高斯核加權均值法

對小區域內的像素進行加權求和得到新的閾值,其權重值來自于高斯分布。
高斯分布,通過概率密度函數來定義高斯分布,一維高斯概率分布函數為:
p(y)=1σ2πe?(y?μ)22σ2p(y)={\frac{1}{\sigma{\sqrt{2\pi}}}}e^{{\frac{-(y-\mu)^{2}}{2\sigma^{2}}}} p(y)=σ2π?1?e2σ2?(y?μ)2?
我們拓展到二維圖像,一般情況下我們使x軸和y軸的相等并且,此時我們可以得到二維高斯函數的表達式為:
g(x,y)=12πσ2e?(x2+y2)2σ2g(x,y)=\frac{1}{2\pi\sigma ^{2}}e^{-\frac{(x^{2}+y^{2})}{2\sigma^{2}}} g(x,y)=2πσ21?e?2σ2(x2+y2)?
高斯概率函數是相對于二維坐標產生的,其中(x,y)為點坐標,要得到一個高斯濾波器模板,應先對高斯函數進行離散化,將得到的值作為模板的系數。例如:要產生一個3*3的高斯權重核,以核的中心位置為坐標原點進行取樣,其周圍的坐標如下圖所示(x軸水平向右,y軸豎直向上)
在這里插入圖片描述
通過這個高斯核,即可對圖片中的每個像素去計算其閾值,并將該閾值減去固定值得到最終閾值,然后根據二值化規則進行二值化。

在這里插入圖片描述
代碼如下(示例):

import cv2 as cv
#讀取圖像
flower = cv.imread('../images/flower.png')
#灰度處理
gray = cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
gray = cv.resize(gray,(400,400))
#自適應二值化(高斯核加權法)
gauss = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,11,2)
cv.imshow("gauss",gauss)
cv.waitKey(0)
cv.destroyAllWindows()

兩種方法執行對比:
在這里插入圖片描述
上述兩種方法,僅僅只是卷積核的參數會發生變化,計算過程是一樣的,很明顯高斯加權均值法的二值化細致程度要高一些。

四、圖像鏡像翻轉與仿射變換

  • 仿射變換的基本原理

    • 線性變換

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

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

      (類似于y=kx+b)

      在這里插入圖片描述

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

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

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

  • cv2.warpAffine()函數

仿射變換函數

    cv2.warpAffine(img,M,dsize)
  • img:輸入圖像。

  • M:2x3的變換矩陣,類型為np.float32

  • dsize:輸出圖像的尺寸,形式為(width,height)

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

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

  • cv2.flip(img,flipcode)

  • 參數

    • img: 要翻轉的圖像
    • flipcode: 指定翻轉類型的標志
      • flipcode=0: 垂直翻轉,圖片像素點沿x軸翻轉
      • flipcode>0: 水平翻轉,圖片像素點沿y軸翻轉
      • flipcode<0: 水平垂直翻轉,水平翻轉和垂直翻轉的結合
        代碼如下(示例):
import cv2 as cv
import numpy as np
#讀取圖像
cao = cv.imread("../images/cao.png")
cao=cv.resize(cao,(300,300))
#翻轉,鏡像翻轉,以圖像原點為中心(cv.flip(img,flipcode))
#0(垂直翻轉沿X軸)>0(水平翻轉沿Y軸)<0(垂直水平翻轉)
flip_0 = cv.flip(cao,0)
flip_1 = cv.flip(cao,1)
flip_2 = cv.flip(cao,-1)
cv.imshow("cao",cao)
cv.imshow("flip_0",flip_0)
cv.imshow("flip_1",flip_1)
cv.imshow("flip_2",flip_2)
cv.waitKey(0)
cv.destroyAllWindows()

執行效果:
在這里插入圖片描述

2.圖像旋轉

cv2.getRotationMatrix2D()函數

獲取旋轉矩陣

  cv2.getRotationMatrix2D(center,angle,scale)
  • center:旋轉中心點的坐標,格式為(x,y)
  • angle:旋轉角度,單位為度,正值表示逆時針旋轉負值表示順時針旋轉。
  • scale:縮放比例,若設為1,則不縮放。
  • 返回值M,2x3的旋轉矩陣。

代碼示例:

import cv2 as cv
#讀取圖像
img = cv.imread("../images/1.jpg")
cv.imshow("img",img)
#獲取旋轉矩陣cv2.getRotationMatrix2D(旋轉中心,旋轉角度,縮放比例)
M = cv.getRotationMatrix2D((img.shape[1]/2,img.shape[0]/2),45,1)
#仿射變換cv2.warpAffine(src, M, (width, height))
dst = cv.warpAffine(img,M,(img.shape[1],img.shape[0]))
cv.imshow("src",dst)
cv.waitKey(0)
cv.destroyAllWindows()

執行效果:
在這里插入圖片描述

3.圖像平移

移操作可以將圖像中的每個點沿著某個方向移動一定的距離。
在這里插入圖片描述
假設我們有一個點 P(x,y)P(x,y)P(x,y),希望將其沿x軸方向平移txt_xtx?*個單位,沿y軸方向平移tyt_yty?個單位到新的位置P′(x′,y′)P′(x′,y′)P(x,y),那么平移公式如下:

? x′=x+txx′=x+txx=x+tx

? y′=y+tyy′=y+tyy=y+ty

在矩陣形式下,該變換可以表示為:
在這里插入圖片描述
代碼示例:

import cv2 as cv
import numpy as np
#讀取圖像
img = cv.imread("../images/1.jpg")
img = cv.resize(img,(300,300))
#創建一個平移矩陣
M = np.float32([[1,0,100],[0,1,50]])
#仿射變換
dst = cv.warpAffine(img,M,(img.shape[1]*2,img.shape[0]*2))
cv.imshow("img",img)
cv.imshow("src",dst)
cv.waitKey(0)
cv.destroyAllWindows()

運行效果:
在這里插入圖片描述

4.圖像縮放

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

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

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

    x′=sx?xx′=s_x*xx=sx??x

    ? y′=sy?yy′=s_y*yy=sy??y

    在矩陣形式下,該變換可以表示為:
    在這里插入圖片描述

  • 相較于圖像旋轉中只能等比例的縮放,圖像縮放更加靈活,可以在指定方向上進行縮放。
    sx和sy分別表示在x軸和y軸方向上的縮放因子
    代碼示例:

import cv2 as cv
import numpy as np
#讀取圖像
img = cv.imread("../images/1.jpg")
img = cv.resize(img,(400,400))
#創建一個縮放矩陣
M = np.float32([[0.5,0,100],[0,0.5,100]])
dst = cv.warpAffine(img,M,(img.shape[1],img.shape[0]))
cv.imshow("img",img)
cv.imshow("src",dst)
cv.waitKey(0)
cv.destroyAllWindows()

執行效果:
在這里插入圖片描述


結語

圖像預處理是計算機視覺任務的“隱形引擎”,合理運用這些技術可以顯著提升模型的性能和魯棒性。本文從 顏色空間轉換 到 仿射變換,系統介紹了 OpenCV 的核心預處理方法,并提供了可復現的代碼示例。

📌 動手挑戰: 嘗試對一張傾斜的名片圖片進行仿射變換矯正,并利用二值化提取清晰的文字信息!

🔗 后續預告: 在下一篇文章中,我們將深入探討 圖像濾波與邊緣檢測,進一步解鎖 OpenCV 的高級功能!

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

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

相關文章

APP逆向 day9 安卓開發基礎

一.前言 app逆向當然要學安卓基礎啦&#xff01;今天我們來教安卓基礎當然&#xff0c;安卓基礎不會教的很多&#xff0c;比java還要少&#xff0c;還是那句話&#xff0c;了解就好。 二.安卓環境搭建 2.1 安卓介紹 如果做安卓開發 需要會java代碼安卓SDK(安卓提供的內置…

Jmeter的元件使用介紹:(三)配置元件詳解02

六、計數器 可以用來做一些變量自增操作。 1、Starting value:定義初始值 2、遞增&#xff1a;定義每次執行遞增多少 3、Maximum value:定義承受的最大值 4、數據格式&#xff1a;可以不填&#xff0c;也可以定義成000;001;002等等任意格式都行。&#xff08;1&#xff09;如…

JavaWeb學習打卡15(JSP標簽、JSTL標簽、EL表達式)

EL表達式&#xff1a;${ }獲取數據執行運算獲取web開發的常用對象在pom.xml 文件中導入JSP、JSTL相關依賴&#xff1a;<!--JSP依賴--><!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --><dependency><groupId>java…

7.22數據結構——順序表

文章目錄一、思維導圖二、實現順序表的功能代碼head.htest.cmain.c一、思維導圖 二、實現順序表的功能代碼 head.h #ifndef __HEAD_H__ #define __HEAD_H__#include <stdio.h> #include <string.h> #include <stdlib.h> //數組的最大長度 #define MAXSIZE …

【如何無限制免費試用 IDEA || Pycharm(JB 全家桶)】

如何無限制免費試用 IDEA || Pycharm(JB 全家桶) 一、目標:解決 JB 全家桶試用時長痛點 如果你是程序員,大概率用過 JetBrains 家的 IDE——IDEA 寫 Java、Pycharm 寫 Python、WebStorm 做前端,體驗確實頂流,但官方 30 天試用到期后,動輒幾千的年費實在讓人肉痛。 咱…

Qt(資源庫和按鈕組)

這一節是對上一節的補充&#xff0c;上一節提到QLabel類和QAabstractButton類&#xff0c;這節內容&#xff1a;1.如設置資源庫&#xff0c;使用資源設置圖片2. 使用按鈕組管理多個按鈕。一、資源庫1. 資源庫作用Qt的資源庫&#xff08;Resource System&#xff0c;.qrc文件&am…

一道檢驗編碼能力的字符串的題目

#include<iostream> #include<vector> #include<string> using namespace std; int bNum0,gNum0; int findEnd(string& s,int si){int lens.size();//當前字母在哪個字符串中,存入comp中string comp;if(s[si]b||s[si]o||s[si]y){comp"boy";bNu…

UniApp X 網絡請求避坑指南:從 JS 到 UTS 的 JSON 數據處理全解析

在 UniApp 開發中&#xff0c;我們經常需要通過 uni.request 獲取服務器返回的 JSON 數據&#xff0c;并將其綁定到頁面或進行邏輯處理。但在 UniApp X&#xff08;基于 UTS&#xff09; 中&#xff0c;由于引入了 強類型語言特性&#xff0c;處理 JSON 數據的方式與 JS 有明顯…

iOS 網絡請求常用依賴庫與系統自帶 API 介紹與示例

iOS 網絡請求常用依賴庫與系統自帶 API 介紹與示例 在 iOS 開發中&#xff0c;進行網絡請求是幾乎所有應用都不可或缺的功能。開發者有多種選擇來處理網絡通信&#xff0c;從系統自帶的 URLSession 到各種流行的第三方庫。下面我將為您介紹 URLSession、AFNetworking、Alamofir…

JavaScript 中 let 在循環中的作用域機制解析

一、let在循環中的特殊性 let作為ES6引入的塊級作用域聲明&#xff0c;在循環結構中存在特殊行為&#xff0c;其核心區別于var的函數作用域特性。理解這一特性對于編寫正確的閉包邏輯至關重要。 在 ECMAScript 規范里&#xff0c;let聲明的變量具有塊級作用域特性&#xff0c;這…

@Subscribe@AllowConcurrentEvents解析這兩個注解

@Subscribe@AllowConcurrentEvents解析這兩個注解 @Subscribe 和 @AllowConcurrentEvents 是 Guava EventBus(Google 開源的事件總線框架)中用于處理事件訂閱的注解,主要用于實現組件間的解耦通信。下面分別解析: 1. @Subscribe 注解 作用:標記一個方法為事件訂閱者方法,…

好看的小程序推廣單頁HTML源碼 可用作導航頁

內容目錄一、詳細介紹二、效果展示1.部分代碼2.效果圖展示三、學習資料下載一、詳細介紹 響應式的小程序推廣單頁HTML源碼。這個設計采用了現代化的UI元素&#xff0c;包含吸引人的標題、特性展示、二維碼區域和行動號召按鈕。 二、效果展示 1.部分代碼 代碼如下&#xff0…

華為倉頡編程語言實踐體驗

華為倉頡編程語言實踐體驗 目前華為倉頡編程語言因為其推出時間較短&#xff0c;生態系統不完善。官網資料權威&#xff0c;但比較龐大難懂。快速實驗入門&#xff0c;是學習一門編程語言的法寶。網上靠譜的資料稀少&#xff0c;特此撰文介紹&#xff0c;幫助初學者減少挫折感&…

YOLOv11實戰,使用YOLOv11訓練自己的數據集和推理(附YOLOv11網絡結構圖)

2024年計算機視覺領域的顛覆性突破,YOLOv11以22%的參數量減少和0.3%的mAP提升重新定義實時目標檢測的邊界 本文將手把手帶你完成YOLOv11的全流程實戰,包含環境配置、數據準備、模型訓練、推理部署及創新優化方案,并深度解析其網絡架構設計思想。 一、YOLOv11核心創新解析 …

macOS xcode打包ios測試ipa應用包

可以參考&#xff1a; https://blog.csdn.net/sinat_34104446/article/details/133684756 過程中遇到很多稀奇古怪的報錯&#xff0c;基本重啟電腦即可解決。。。在我按照上面的步驟申請并導入新證書后&#xff0c;還遇到了一個問題&#xff1a;解決辦法&#xff1a; https://b…

STM32基礎知識學習筆記:ICODE、DCODE、DMA等常見名詞的解釋

基于AI生成內容。 ICODEICODE&#xff1a;指令總線&#xff08;Instruction Bus&#xff09; 主要用于處理 CPU 對程序指令的讀取操作。它是 STM32 存儲架構中重要的組成部分&#xff0c;與數據總線&#xff08;DCODE&#xff09;、系統總線&#xff08;System Bus&#xff09;…

誰將統治AI游戲時代?騰訊、網易、米哈游技術暗戰

游戲行業的“產能天花板”正被AI技術轟然擊穿。騰訊、網易、米哈游……所有的游戲廠商都在押注AI&#xff0c;騰訊混元發布混元游戲視覺生成平臺&#xff0c;分鐘級生成高精度游戲角色&#xff1b;網易《蛋仔派對》借AI實現UGC創作平民化&#xff1b;米哈游新作更以實時多模態對…

基于springboot的工商局商家管理系統

博主介紹&#xff1a;java高級開發&#xff0c;從事互聯網行業六年&#xff0c;熟悉各種主流語言&#xff0c;精通java、python、php、爬蟲、web開發&#xff0c;已經做了六年的畢業設計程序開發&#xff0c;開發過上千套畢業設計程序&#xff0c;沒有什么華麗的語言&#xff0…

ABP VNext + Razor 郵件模板:動態、多租戶隔離、可版本化的郵件與通知系統

&#x1f680; ABP VNext Razor 郵件模板&#xff1a;動態、多租戶隔離、可版本化的郵件與通知系統 &#x1f4da; 目錄&#x1f680; ABP VNext Razor 郵件模板&#xff1a;動態、多租戶隔離、可版本化的郵件與通知系統&#x1f31f; 一、TL;DR&#x1f4c8; 二、系統流程圖…

瘋狂星期四第19天運營日記

網站運營第19天&#xff0c;點擊觀站&#xff1a; 瘋狂星期四 crazy-thursday.com 全網最全的瘋狂星期四文案網站 運營報告 今日訪問量 今日訪問量42&#xff0c;瘋狂之后的冷靜&#xff0c;落差太大~~ 今日搜索引擎收錄情況 必應仍然是24條記錄&#xff0c;無變化 百度0收…