tft每日頭條

 > 科技

 > pythonopencv圖像特征檢測

pythonopencv圖像特征檢測

科技 更新时间:2024-07-24 09:25:31

摘要: 使用Numpy和OpenCV完成圖像的基本數據分析第三部分,主要包含圖像變換、卷積操作等。

pythonopencv圖像特征檢測(使用Numpy和Opencv完成圖像的基本數據分析)1

引言

本文是使用python進行圖像基本處理系列的第三部分,在本人之前的文章裡介紹了一些非常基本的圖像分析操作,見文章《使用Numpy和Opencv完成圖像的基本數據分析Part I》和《使用Numpy和Opencv完成圖像的基本數據分析 Part II》,下面我們将繼續介紹一些有關圖像處理的好玩内容。

本文介紹的内容基本反映了我本人學習的圖像處理課程中的内容,并不會加入任何工程項目中的圖像處理内容,本文目的是嘗試實現一些基本圖像處理技術的基礎知識,出于這個原因,本文繼續使用 SciKit-Image,numpy數據包執行大多數的操作,此外,還會時不時的使用其他類型的工具庫,比如圖像處理中常用的OpenCV等:

本系列分為三個部分,分别為part I、part II以及part III。剛開始想把這個系列分成兩個部分,但由于内容豐富且各種處理操作獲得的結果是令人着迷,因此不得不把它分成三個部分。系列所有的源代碼地址:GitHub-Image-Processing-Python。

在上一篇文章中,我們已經完成了以下一些基本操作。為了跟上今天的内容,回顧一下之前的基本操作:

  • 導入圖像并觀察其屬性
  • 拆分圖層
  • 灰度處理
  • 對像素值使用邏輯運算符
  • 使用邏輯運算符進行掩碼

現在開始本節的内容:

強度變換|Intensity Transformation

首先導入一張圖像作為開始:

%matplotlibinline import imageio import matplotlib.pyplot as plt import warnings import matplotlib.cbook warnings.filterwarnings("ignore",category=matplotlib.cbook.mplDeprecation) pic=imageio.imread('img/parrot.jpg') plt.figure(figsize=(6,6)) plt.imshow(pic); plt.axis('off');

pythonopencv圖像特征檢測(使用Numpy和Opencv完成圖像的基本數據分析)2

圖像底片|Image negative

強度變換函數在數學上定義為:

S = T(r)

其中r是輸入圖像的像素,S是輸出圖像的像素,T是一個轉換函數,它将r的每個像素值映射到s中對應的像素值。

負變換,即恒等變換的逆。在負變換中,輸入圖像的每個像素值從L-1中減去并映射到輸出圖像上。

在這種情況下,完成以下轉換:

S =(L-1)-r

因此,每個像素值都減去255。這樣的操作導緻的結果是,較亮的像素變暗,較暗的圖像變亮,類似于圖像底片。

negative =255- pic # neg = (L-1) - img plt.figure(figsize= (6,6)) plt.imshow(negative); plt.axis('off');

pythonopencv圖像特征檢測(使用Numpy和Opencv完成圖像的基本數據分析)3

對數變換|log transformation

對數轉換可以通過以下公式定義:

s = c *log(r 1)

其中s和r是輸出和輸入圖像的像素值,c是常數。輸入圖像的每個像素值都會加1,之後再進行對數操作,這是因為如果圖像中的像素值為0時,log(0)的結果等于無窮大。因此,為了避免這種情況的發生,輸入圖像中的每個像素值都加1,使最小像素值至少為1。

在對數變換過程中,與較高像素值相比,圖像中的低像素被擴展。較高的像素值在對數變換中被壓縮,這導緻圖像增強。

對數變換中的c值調整了我們想要的增強程度:

%matplotlibinline import imageio import numpyasnp import matplotlib.pyplotasplt pic=imageio.imread('img/parrot.jpg') gray=lambdargb:np.dot(rgb[...,:3],[0.299,0.587,0.114]) gray=gray(pic) ''' log transform -> s = c*log(1 r) So, we calculate constant c to estimate s -> c = (L-1)/log(1 |I_max|) ''' max_=np.max(gray) def log_transform(): return(255/np.log(1 max_))*np.log(1 gray) plt.figure(figsize=(5,5)) plt.imshow(log_transform(),cmap=plt.get_cmap(name='gray')) plt.axis('off');

pythonopencv圖像特征檢測(使用Numpy和Opencv完成圖像的基本數據分析)4

伽馬校正| Gamma Correction

伽馬校正,或通常簡稱為伽瑪,是用于對視頻或靜止圖像系統中的亮度或三刺激值進行編碼和解碼的非線性操作,伽瑪校正也稱為幂律變換。首先,圖像的像素值大小範圍必須從0~255被縮放至0~1.0。然後,通過應用以下等式獲得伽馬校正後的輸出圖像:

Vo = Vi ^(1 / G)

其中Vi是我們的輸入圖像,G是設置的伽瑪值,然後将輸出圖像Vo縮放回0-255範圍。

對于伽馬值而言,G <1有時被稱為編碼伽瑪,并且利用該壓縮幂律非線性進行編碼的過程被稱為伽馬壓縮; Gamma值小于1會将圖像移向光譜的較暗端。

相反,伽馬值G> 1被稱為解碼伽馬,并且膨脹幂律非線性的應用被稱為伽馬展開。Gamma值大于1将使圖像顯得更亮。将伽瑪值設置為G = 1時對輸入圖像沒有影響:

import imageio import matplotlib.pyplotasplt # Gamma encoding pic=image io.imread('img/parrot.jpg') gamma=2.2# Gamma < 1 ~ Dark ; Gamma > 1 ~ Bright gamma_correction=((pic/255)**(1/gamma)) plt.figure(figsize=(5,5)) plt.imshow(gamma_correction) plt.axis('off');

pythonopencv圖像特征檢測(使用Numpy和Opencv完成圖像的基本數據分析)5

伽馬校正的原因|Reason for Gamma Correction

我們應用伽馬校正的原因是,由于我們的眼睛感知顔色和亮度這一過程與數碼相機中的傳感器的工作原理不同。當數碼相機上的傳感器獲得兩倍的光子量時,信号會加倍。但是,我們人類的眼睛的工作原理與這不同,當我們的眼睛感知兩倍的光量時,視野中隻有一小部分顯得更亮。因此,數碼相機在亮度之間具有線性關系,而我們人類的眼睛具有非線性關系。為了解釋這種關系,我們應用伽瑪校正。

還有一些其他的線性變換函數,比如:

  • 對比度拉伸(Contrast Stretching)
  • 強度切片(Intensity-Level Slicing)
  • 位平面切片(Bit-Plane Slicing)

卷積|Convolution

在上一篇文章中,對卷積操作作了簡要讨論。當計算機看到圖像時,它看到不是一整幅圖像,它的眼裡看到的隻是一個像素值數組。假設讀取一個32X32大小的彩色圖像,根據圖像的分辨率和大小,計算機它将看到一個32 x 32 x 3維的數字數組,其中3表示RGB值或三通道。假設現在我們有一個PNG格式的彩色圖像,它的大小是480 x 480。将其讀入後,其表示數組将是480 x 480 x 3維。數組中的所有的每個數字值範圍都在0到255之間,它描述的是那個點的像素強度。

就像我們剛才提到的那樣,假設輸入圖像是一個32 x 32 x 3的像素值數組,解釋卷積的最佳方法是想象一個閃爍在圖像左上方的手電筒。假設手電筒照射區域大小為3 x 3。現在,讓我們假設這個手電筒滑過輸入圖像的所有區域。在機器學習術語中,這個手電筒被稱為過濾器(filter)或内核(kernel),或者有時被稱為權重(weights) 或 掩模(mask),它所照射的區域稱為 感受野(receptive field)。

現在,此過濾器也是一個數字數組,數組中的數字稱為權重或參數,在這裡要着重注意一點,此過濾器的深度必須與輸入圖像的深度相同,即通道數相同,因此此過濾器的尺寸為3 x 3 x 3。

圖像内核 或過濾器是一個小矩陣,用于應用我們可能在Photoshop或Gimp中找到的效果,例如模糊、銳化、輪廓或浮雕等。此外,它們還被用于在機器學習中進行圖像特征提取(CNN),這是一種用于确定圖像最重要部分的技術。更多相關信息,請查看Gimp關于使用Image kernel的文檔,我們可以該文檔中找到最常見的内核列表 。

現在,讓我們将過濾器放在圖像的左上角。當濾波器圍繞輸入圖像滑動或卷積時,它将濾波器中的值乘以圖像的原始像素值(也稱為計算元素乘法)。這些乘法操作最後都會求和,所以卷積操作後隻得到一個數字值。請記住,此數字僅代表過濾器位于圖像的左上角。現在,我們對輸入圖像上的每個位置重複此過程,移動過濾器使其與圖像矩陣的每個像素值進行卷積操作,這個過程需要設置移動步幅,依此類推,完成整幅圖像的卷積操作。輸入圖中的每個唯一位置都會生成一個數字。步幅的取值一般為1,也可以取其它大小的值,但我們關心的是它是否适合輸入圖像。

pythonopencv圖像特征檢測(使用Numpy和Opencv完成圖像的基本數據分析)6

過濾器滑過輸入圖像上的所有位置後,我們會發現,我們剩下的是一個30 x 30 x 1的數組,我們将其稱為激活圖 或特征圖。将3 x 3過濾器可以放在32 x 32輸入圖像上,可以得到30 x 30大小的陣列,原因是有300個不同的位置,這900個數字映射到30 x 30陣列。我們可以通過以下方式計算卷積圖像後圖像的大小:

  • 卷積:(N-F)/ S 1

其中N和F分别代表輸入圖像大小和卷積核大小,S代表步幅或步長。因此,對于上述情況,輸出圖像的大小将是

  • 32-31 1 = 30

假設我們有一個3x3濾波器,在5x5大小的矩陣上進行卷積,根據等式,我們應該得到一個3x3矩陣,現在讓我們看一下:

pythonopencv圖像特征檢測(使用Numpy和Opencv完成圖像的基本數據分析)7

此外,我們實際上使用的過濾器不止一個,過濾器的數量自己設定,假設過濾器的數量設置為n,則我們的輸出将是28x28xn大小(其中n是特征圖的數量 )。

通過使用更多的過濾器,我們能夠更好地保留空間維度信息。

然而,對于圖像矩陣邊界上的像素,卷積核的一些元素移動時會出現在圖像矩陣之外,因此不具有來自圖像矩陣的任何對應元素。在這種情況下,我們可以消除這些位置的卷積運算,最終輸出矩陣大小将會小于輸入圖像,或者我們可以對輸入圖像矩陣進行填充(padding),以保證輸出圖像大小維度不變。

為了保持本系列的簡潔而保持内容的完整性,本文提供了全部的資源鍊接,在其中更詳細地解釋了有關内容。

下面,讓我們首先将一些自定義卷積核個數的窗口應用于圖像中,這可以通過平均每個像素值與附近的像素值來處理圖像:

%%time import numpy as np import imageio import matplotlib.pyplot as plt from scipy.signal import convolve2d def Convolution(image, kernel): conv_bucket= [] for d in range(image.ndim): conv_channel= convolve2d(image[:,:,d], kernel, mode="same", boundary="symm") conv_bucket.append(conv_channel) returnnp.stack(conv_bucket, axis=2).astype("uint8") kernel_sizes= [9,15,30,60] fig, axs=plt.subplots(nrows=1, ncols=len(kernel_sizes), figsize=(15,15)); pic =imageio.imread('img:/parrot.jpg') for k, ax in zip(kernel_sizes, axs): kernel =np.ones((k,k)) kernel /=np.sum(kernel) ax.imshow(Convolution(pic, kernel)); ax.set_title("Convolved By Kernel: {}".format(k)); ax.set_axis_off(); Wall time: 43.5 s

pythonopencv圖像特征檢測(使用Numpy和Opencv完成圖像的基本數據分析)8

更多内容可以在此查看,其中已經深入讨論了各種類型的内核,并展示了它們之間的差異。

作者信息

Mohammed Innat,機器學習和數據科學研究者

本文由阿裡雲雲栖社區組織翻譯。

文章原标題《Basic Image Data Analysis Using Numpy and OpenCV – Part 3》,譯者:海棠,審校:Uncle_LLD。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved