本文目錄一覽:
OpenCV Python 系列教程4 – OpenCV 圖像處理(上)
學習目標:
OpenCV 中有 150 多種色彩空間轉化的方法,這裡只討論兩種:
HSV的色相範圍為[0,179],飽和度範圍為[0,255],值範圍為[0,255]。不同的軟件使用不同的規模。如果要比較 OpenCV 值和它們,你需要標準化這些範圍。
HSV 和 HLV 解釋
運行結果:該段程序的作用是檢測藍色目標,同理可以檢測其他顏色的目標
結果中存在一定的噪音,之後的章節將會去掉它
這是物體跟蹤中最簡單的方法。一旦你學會了等高線的函數,你可以做很多事情,比如找到這個物體的質心,用它來跟蹤這個物體,僅僅通過在相機前移動你的手來畫圖表,還有很多其他有趣的事情。
菜鳥教程 在線 HSV- BGR 轉換
比如要找出綠色的 HSV 值,可以使用上面的程序,得到的值取一個上下界。如上面的取下界 [H-10, 100, 100],上界 [H+10, 255, 255]
或者使用其他工具如 GIMP
學習目標:
對圖像進行閾值處理,算是一種最簡單的圖像分割方法,基於圖像與背景之間的灰度差異,此項分割是基於像素級的分割
threshold(src, thresh, maxval, type[, dst]) – retval, dst
計算圖像小區域的閾值。所以我們對同一幅圖像的不同區域得到不同的閾值,這給我們在不同光照下的圖像提供了更好的結果。
三個特殊的輸入參數和一個輸出參數
adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) – dst
opencv-threshold-python
OpenCV 圖片集
本節原文
學習目標:
OpenCV 提供兩種變換函數: cv2.warpAffine 和 cv2.warpPerspective
cv2.resize() 完成縮放
文檔說明
運行結果
說明 : cv2.INTER_LINEAR 方法比 cv2.INTER_CUBIC 還慢,好像與官方文檔說的不一致? 有待驗證。
速度比較: INTER_CUBIC INTER_NEAREST INTER_LINEAR INTER_AREA INTER_LANCZOS4
改變圖像的位置,創建一個 np.float32 類型的變換矩陣,
warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) – dst
運行結果:
旋轉角度( )是通過一個變換矩陣變換的:
OpenCV 提供的是可調旋轉中心的縮放旋轉,這樣你可以在任何你喜歡的位置旋轉。修正後的變換矩陣為
這裡
OpenCV 提供了 cv2.getRotationMatrix2D 控制
cv2.getRotationMatrix2D(center, angle, scale) → retval
運行結果
cv2.getAffineTransform(src, dst) → retval
函數關係:
\begin{bmatrix} x’_i \ y’_i \end{bmatrix}\begin{bmatrix} x’_i \ y’_i \end{bmatrix} =
其中
運行結果:圖上的點便於觀察,兩圖中的紅點是相互對應的
透視變換需要一個 3×3 變換矩陣。轉換之後直線仍然保持筆直,要找到這個變換矩陣,需要輸入圖像上的 4 個點和輸出圖像上的對應點。在這 4 個點中,有 3 個不應該共線。通過 cv2.getPerspectiveTransform 計算得到變換矩陣,得到的矩陣 cv2.warpPerspective 變換得到最終結果。
本節原文
平滑處理(smoothing)也稱模糊處理(bluring),是一種簡單且使用頻率很高的圖像處理方法。平滑處理的用途:常見是用來 減少圖像上的噪點或失真 。在涉及到降低圖像分辨率時,平滑處理是很好用的方法。
圖像濾波:盡量保留圖像細節特徵的條件下對目標圖像的噪聲進行抑制,其處理效果的好壞將直接影響到後續圖像處理和分析的有效性和可靠性。
消除圖像中的噪聲成分叫做圖像的平滑化或濾波操作。信號或圖像的能量大部分集中在幅度譜的低頻和中頻段,在高頻段,有用的信息會被噪聲淹沒。因此一個能降低高頻成分幅度的濾波器就能夠減弱噪聲的影響。
濾波的目的:抽出對象的特徵作為圖像識別的特徵模式;為適應圖像處理的要求,消除圖像數字化時混入的噪聲。
濾波處理的要求:不能損壞圖像的輪廓及邊緣等重要信息;圖像清晰視覺效果好。
平滑濾波是低頻增強的空間濾波技術,目的:模糊和消除噪音。
空間域的平滑濾波一般採用簡單平均法,即求鄰近像元點的平均亮度值。鄰域的大小與平滑的效果直接相關,鄰域越大平滑效果越好,但是鄰域過大,平滑也會使邊緣信息的損失的越大,從而使輸出圖像變得模糊。因此需要選擇合適的鄰域。
濾波器:一個包含加權係數的窗口,利用濾波器平滑處理圖像時,把這個窗口放在圖像上,透過這個窗口來看我們得到的圖像。
線性濾波器:用於剔除輸入信號中不想要的頻率或者從許多頻率中選擇一個想要的頻率。
低通濾波器、高通濾波器、帶通濾波器、帶阻濾波器、全通濾波器、陷波濾波器
boxFilter(src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]]) – dst
均值濾波是方框濾波歸一化後的特殊情況。歸一化就是要把處理的量縮放到一個範圍內如 (0,1),以便統一處理和直觀量化。非歸一化的方框濾波用於計算每個像素鄰近內的積分特性,比如密集光流算法中用到的圖像倒數的協方差矩陣。
運行結果:
均值濾波是典型的線性濾波算法,主要方法為鄰域平均法,即用一片圖像區域的各個像素的均值來代替原圖像中的各個像素值。一般需要在圖像上對目標像素給出一個模板(內核),該模板包括了其周圍的臨近像素(比如以目標像素為中心的周圍8(3×3-1)個像素,構成一個濾波模板,即 去掉目標像素本身 )。再用模板中的全體像素的平均值來代替原來像素值。即對待處理的當前像素點(x,y),選擇一個模板,該模板由其近鄰的若干像素組成,求模板中所有像素的均值,再把該均值賦予當前像素點(x,y),作為處理後圖像在該點上的灰度個g(x,y),即個g(x,y)=1/m ∑f(x,y) ,其中m為該模板中包含當前像素在內的像素總個數。
均值濾波本身存在着固有的缺陷,即它不能很好地保護圖像細節,在圖像去噪的同時也破壞了圖像的細節部分,從而使圖像變得模糊,不能很好地去除噪聲點。
cv2.blur(src, ksize[, dst[, anchor[, borderType]]]) → dst
結果:
高斯濾波:線性濾波,可以消除高斯噪聲,廣泛應用於圖像處理的減噪過程。高斯濾波就是對整幅圖像進行加權平均的過程,每一個像素點的值,都由其本身和鄰域內的其他像素值經過 加權平均 後得到。高斯濾波的具體操作是:用一個模板(或稱卷積、掩模)掃描圖像中的每一個像素,用模板確定的鄰域內像素的加權平均灰度值去替代模板中心像素點的值。
高斯濾波有用但是效率不高。
高斯模糊技術生成的圖像,其視覺效果就像是經過一個半透明屏幕在觀察圖像,這與鏡頭焦外成像效果散景以及普通照明陰影中的效果都明顯不同。高斯平滑也用於計算機視覺算法中的預先處理階段,以增強圖像在不同比例大小下的圖像效果(參見尺度空間表示以及尺度空間實現)。從數學的角度來看,圖像的高斯模糊過程就是圖像與正態分布做卷積。由於正態分布又叫作高斯分布,所以這項技術就叫作高斯模糊。
高斯濾波器是一類根據高斯函數的形狀來選擇權值的線性平滑濾波器。 高斯平滑濾波器對於抑制服從正態分布的噪聲非常有效。
一維零均值高斯函數為: 高斯分布參數 決定了高斯函數的寬度。
高斯噪聲的產生
GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]]) – dst
線性濾波容易構造,並且易於從頻率響應的角度來進行分析。
許多情況,使用近鄰像素的非線性濾波會得到更好的結果。比如在噪聲是散粒噪聲而不是高斯噪聲,即圖像偶爾會出現很大值的時候,用高斯濾波器進行圖像模糊時,噪聲像素不會被消除,而是轉化為更為柔和但仍然可見的散粒。
中值濾波(Median filter)是一種典型的非線性濾波技術,基本思想是用像素點鄰域灰度值的中值來代替該像素點的灰度值,該方法在去除脈衝噪聲、椒鹽噪聲『椒鹽噪聲又稱脈衝噪聲,它隨機改變一些像素值,是由圖像傳感器,傳輸信道,解碼處理等產生的黑白相間的亮暗點噪聲。椒鹽噪聲往往由圖像切割引起。』的同時又能保留圖像邊緣細節,
中值濾波是基於排序統計理論的一種能有效抑制噪聲的非線性信號處理技術,其基本原理是把數字圖像或數字序列中一點的值用該點的一個鄰域中各點值的中值代替,讓周圍的像素值接近的真實值,從而消除孤立的噪聲點,對於 斑點噪聲(speckle noise)和椒鹽噪聲(salt-and-pepper noise) 來說尤其有用,因為它不依賴於鄰域內那些與典型值差別很大的值。中值濾波器在處理連續圖像窗函數時與線性濾波器的工作方式類似,但濾波過程卻不再是加權運算。
中值濾波在一定的條件下可以克服常見線性濾波器如最小均方濾波、方框濾波器、均值濾波等帶來的圖像細節模糊,而且對濾除脈衝干擾及圖像掃描噪聲非常有效,也常用於保護邊緣信息, 保存邊緣的特性使它在不希望出現邊緣模糊的場合也很有用,是非常經典的平滑噪聲處理方法。
與均值濾波比較:
說明:中值濾波在一定條件下,可以克服線性濾波器(如均值濾波等)所帶來的圖像細節模糊,而且對濾除脈衝干擾即圖像掃描噪聲最為有效。在實際運算過程中並不需要圖像的統計特性,也給計算帶來不少方便。 但是對一些細節多,特別是線、尖頂等細節多的圖像不宜採用中值濾波。
雙邊濾波(Bilateral filter)是一種非線性的濾波方法,是結合 圖像的空間鄰近度和像素值相似度 的一種折衷處理,同時考慮空域信息和灰度相似性,達到保邊去噪的目的。具有簡單、非迭代、局部的特點。
雙邊濾波器的好處是可以做邊緣保存(edge preserving),一般過去用的維納濾波或者高斯濾波去降噪,都會較明顯地模糊邊緣,對於高頻細節的保護效果並不明顯。雙邊濾波器顧名思義比高斯濾波多了一個高斯方差 sigma-d ,它是基於空間分布的高斯濾波函數,所以在邊緣附近,離的較遠的像素不會太多影響到邊緣上的像素值,這樣就保證了邊緣附近像素值的保存。 但是由於保存了過多的高頻信息,對於彩色圖像里的高頻噪聲,雙邊濾波器不能夠乾淨的濾掉,只能夠對於低頻信息進行較好的濾波。
運行結果
學習目標:
形態變換是基於圖像形狀的一些簡單操作。它通常在二進制圖像上執行。
膨脹與腐蝕實現的功能
侵蝕的基本思想就像土壤侵蝕一樣,它會侵蝕前景物體的邊界(總是試圖保持前景為白色)。那它是做什麼的?內核在圖像中滑動(如在2D卷積中)。只有當內核下的所有像素都是 1 時,原始圖像中的像素( 1 或 0 )才會被視為 1 ,否則它將被侵蝕(變為零)
erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) – dst
與腐蝕的操作相反。如果內核下的至少一個像素為“1”,則像素元素為“1”。因此它增加了圖像中的白色區域或前景對象的大小增加。通常,在去除噪音的情況下,侵蝕之後是擴張。因為,侵蝕會消除白噪聲,但它也會縮小我們的物體。所以我們擴大它。由於噪音消失了,它們不會再回來,但我們的物體區域會增加。它也可用於連接對象的破碎部分
CV2 — 處理圖像
環境:Anaconda 3.6
首先安裝cv2的包: pip3 install opencv-python
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
def img_show(img_name, img):
cv2.imshow(img_name, img)
cv2.waitKey(0) # 只顯示第一幀
cv2.destroyAllWindows() # 銷毀所有的窗口
img_file = ‘sudoku.png’
img = cv2.imread(img_file) # 已彩色模式讀取圖像文件
rows, cols, ch = img.shape # 獲取圖像形狀
img_show(‘raw img’, img)
# 圖像縮放
img_scale = cv2.resize(img, None, fx=0.6, interpolation=cv2.INTER_CUBIC)
img_show(‘scale img’, img_scale)
# 圖像平移
M = np.float32([[1,0,100],[0,1,50]]) # x=100, y=50
img_transform = cv2.warpAffine(img, M, (rows,cols)) # 平移圖像
img_show(‘transform img’, img_transform)
# 圖像旋轉
M = cv2.getRotaionMatrix2D((cols/2, rows/2), 45, 0.6)
img_rotation = cv2.warpAffine(img, M, (cols, rows))
img_show(‘rotation img’, img_rotation)
# 透視轉化
pst1 = np.float32([[x1,y1],[x2,y2], [x3,y3], [x4,y4]]) # 轉換前四個點坐標
pst2 = np.float32([[x5,y5],[x6,y6], [x7,y7], [x8,y8]]) # 轉換後四個點坐標
M = cv2.getPerspectiveTransform(pst1, pst2)
img_perspective = cv2.warpPerspective(img, M, (x,y))
img_show(‘perspective img’, img_perspective)
# 轉化為灰度圖片
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 圖像轉灰色
img_show(‘gray img’, gray_img)
# 邊緣檢測
edge_img = cv2.Canny(img, 50,100)
img_show(‘edge img’, edge_img)
# 二值化處理
ret, th1 = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)
# 127為閥值,255為(超過或小於閥值)賦予的值,THRESH_BINARY類型
th2 = cv2.adaptive(gray_img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11,2)
#均值閥值,11=圖像分塊數, 2=計算閥值的常數項
th3 = cv2.adaptive(gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11,2) # 自適應高斯閥值
titles = [‘GRAY_IMG’, ‘GLOBAL img’, ‘mean_img’, ‘gussian img’]
imgs = [gray_img, th1, th2, th3]
for i in range(4):
plt.subplot(2,2, i+1),plt.imshow(imgs[i], ‘gray’) # 以灰度模式展開各個子網格
plt.title(titles[i])
plt.xticks([]), plt.yticks([]) # 設置坐標顯示值
plt.suptitle(‘img’) # 表頭
plt.show() # 顯示圖像
# 圖像平滑
kernel = np.ones((5,5), np.float32) /25 # 設置平滑內核大小
img_smoth_filter2D = cv2.filter2D(img, -1, kernel) # 2D 卷積法
img_smoth_blur = cv2.blur(img, (5,5)) # 平均法
img_smoth_gaussianblur = cv2.GaussianBlur(img, (5,5), 0) # 高斯模糊
img_smoth_medianblur = cv2.medianBlur(img, 5) # 中值法
titles = [‘filter2D’, ‘blur’, ‘GaussianBlur’, ‘medianBlur’]
imges = [img_smoth_filter2D, img_smoth_blur, img_smoth_gaussianblur, img_smoth_medianblur]
for i in range(4):
plt.subplot(2,2,i+1), plt.imshow(imges[i])
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.suptitle(‘smoth images’)
plt.show()
# 形態學處理
img2 = cv2.imread(‘j.png’, 0) # 以灰度模式讀取圖像
kernel = np.ones((5,5), np.uint8)
erosion = cv2.erode(img2, kernel, iterations=1) # 腐蝕
dilation = cv2.dilate(img2, kernel, iterations=1) # 膨脹
plt.subplot(1,3,1), plt.imshow(img2, ‘gray’)
plt.subplot(1,3,2), plt.imshow(erosion, ‘gray’)
plt.subplot(1,3,3), plt.imshow(dilation, ‘gray’)
plt.show()
使用OpenCV和Python進行圖像拼接
么是圖像拼接呢?簡單來說,對於輸入應該有一組圖像,輸出是合成圖像。同時,必須保留圖像之間的邏輯流。
首先讓我們了解圖像拼接的概念。基本上,如果你想捕捉一個大的場景,你的相機只能提供一個特定分辨率的圖像(如:640×480),這當然不足以捕捉大的全景。所以,我們可以做的是捕捉整個場景的多個圖像,然後把所有的碎片放在一起,形成一個大的圖像。這些有序的照片被稱為全景。獲取多幅圖像並將其轉換成全景圖的整個過程稱為圖像拼接。
首先,需要安裝opencv 3.4.2.16。
接下來我們將導入我們將在Python代碼中使用的庫:
在我們的教程中,我們將拍攝這張精美的照片,我們會將其分成兩張左右兩張照片,然後我們會嘗試拍攝相同或非常相似的照片。
因此,我將此圖像切成兩個圖像,它們會有某種重疊區域:
在此,我們將列出我們應採取的步驟,以取得最終的結果:
因此,從第一步開始,我們將導入這兩個圖像並將它們轉換為灰度,如果您使用的是大圖像,我建議您使用cv2.resize,因為如果您使用較舊的計算機,它可能會非常慢並且需要很長時間。如果要調整圖像大小,即調整50%,只需將fx = 1更改為fx = 0.5即可。
我們還需要找出兩幅圖像中匹配的特徵。我們將使用opencv_contrib的SIFT描述符。SIFT (Scale constant Feature Transform)是一種非常強大的OpenCV算法。這些最匹配的特徵作為拼接的基礎。我們提取兩幅圖像的關鍵點和sift描述符如下:
kp1和kp2是關鍵點,des1和des2是圖像的描述符。如果我們用特徵來畫這幅圖,它會是這樣的:
左邊的圖像顯示實際圖像。右側的圖像使用SIFT檢測到的特徵進行注釋:
一旦你有了兩個圖像的描述符和關鍵點,我們就會發現它們之間的對應關係。我們為什麼要這麼做?為了將任意兩個圖像連接成一個更大的圖像,我們必須找到重疊的點。這些重疊的點會讓我們根據第一幅圖像了解第二幅圖像的方向。根據這些公共點,我們就能知道第二幅圖像是大是小還是旋轉後重疊,或者縮小/放大後再fitted。所有此類信息的產生是通過建立對應關係來實現的。這個過程稱為registration。
對於匹配圖像,可以使用opencv提供的FLANN或BFMatcher方法。我會寫兩個例子證明我們會得到相同的結果。兩個示例都匹配兩張照片中更相似的特徵。當我們設置參數k = 2時,這樣我們就要求knnMatcher為每個描述符給出2個最佳匹配。“matches”是列表的列表,其中每個子列表由“k”個對象組成。以下是Python代碼:
FLANN匹配代碼:
BFMatcher匹配代碼:
通常在圖像中,圖像的許多地方可能存在許多特徵。所以我們過濾掉所有的匹配來得到最好的。因此我們使用上面得到的前2個匹配項進行比值檢驗。如果下面定義的比值大於指定的比值,則考慮匹配。
現在我們定義在圖像上繪製線條的參數,並給出輸出以查看當我們在圖像上找到所有匹配時的樣子:
這是輸出的匹配圖像:
這部分完整Python代碼:
因此,一旦我們獲得了圖像之間的最佳匹配,我們的下一步就是計算單應矩陣。如前所述,單應矩陣將與最佳匹配點一起使用,以估計兩個圖像內的相對方向變換。
在OpenCV中估計單應性是一項簡單的任務,只需一行代碼:
在開始編碼拼接算法之前,我們需要交換圖像輸入。所以img_現在會取右圖像img會取左圖像。
那麼讓我們進入拼接編碼:
因此,首先,我們將最小匹配條件count設置為10(由MIN_MATCH_COUNT定義),並且只有在匹配良好的匹配超出所需匹配時才進行拼接。否則,只需顯示一條消息,說明匹配不夠。
因此,在if語句中,我們將關鍵點(從匹配列表)轉換為findHomography()函數的參數。
只需在這段代碼中討論cv2.imshow(“original_image_overlapping.jpg”,img2),我們就會顯示我們收到的圖像重疊區域:
因此,一旦我們建立了單應性,我們需要扭曲視角,我們將以下單應矩陣應用於圖像:
所以我們使用如下:
在上面兩行Python代碼中,我們從兩個給定的圖像中獲取重疊區域。然後在“dst”中我們只接收到沒有重疊的圖像的右側,因此在第二行代碼中我們將左側圖像放置到最終圖像。所以在這一點上我們完全拼接了圖像:
剩下的就是去除圖像的黑色,所以我們將編寫以下代碼來從所有圖像邊框中刪除黑邊:
這是我們調用修剪邊界的最終定義函數,同時我們在屏幕上顯示該圖像。如果您願意,也可以將其寫入磁盤:
使用上面的Python代碼,我們將首先收到原始圖片:
這是完整的最終代碼:
在本教程中,我們學習了如何使用OpenCV執行圖像拼接和全景構造,並編寫了最終的圖像拼接代碼。
我們的圖像拼接算法需要四個主要步驟:檢測關鍵點和提取局部不變描述符; 獲得圖像之間的匹配描述符; 應用RANSAC估計單應矩陣; 使用單應矩陣應用warping transformation。
當僅為兩個圖像構建全景圖時,該算法在實踐中工作良好。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/193266.html