本文介紹圖像處理中的一些基本概念,包括圖像加強、圖像增廣、邊緣提取等。本文的代碼使用OpenCV的python接口,及Numpy。python
基礎操做
隨機生成像素
rows=200 cols=300 num=2000 #隨機像素點的個數 img=np.zeros((rows,cols,3),np.unit8) pos1=np.random.randint(200,size=(num,1)) #行位置隨機數組 pos2=np.random.randint(300,size=(num,1)) #列 #隨機位置處設置像素點值 for i in range(num): img[pos1[i],pos2[i],[0]]=np.random.randint(0,255) img[pos1[i],pos2[i],[1]]=np.random.randint(0,255) img[pos1[i],pos2[i],[2]]=np.random.randint(0,255) 若是在OpenCV中處理圖像,是BGR的順序。
調節圖像亮度
將每一個像素的RGB值變小則亮度調小,變暗;將值變大則變亮。算法
日落效果
將藍色與綠色值設爲原來的70%數組
負片
反色,將像素的三色值設爲(255-原值)dom
水印
cv2.putText(img,"xxxtext",(pos_x,pos_y),cv2.FONT_HERSHEY_PLAIN,2.0,(0,0,0),thickness=2)
機器學習
旋轉、平鋪、鏡像
旋轉必定的角度比較麻煩一些,平鋪、鏡像簡單ide
圖像融合
將兩個圖像對應元素相加取平均。函數
減均值
從圖像中減去均值有助於在不一樣光照條件下對圖像進行歸一化。通常代碼爲: image = image - image.mean()
佈局
二值化
將圖像進行二值化能夠呈現明顯的黑白視覺效果。比較簡單的方法是卡閾值:對於每個像素,大於閾值的設爲1,其它設爲0,將圖像轉換爲二值圖像,能夠用於選擇感興趣的區域。其中一種選擇閾值的方法叫Otsu,須要先把圖像轉換爲灰度圖。此外還有Ridley-Calvard方法等。 OpenCV的threshold方法:retval,dst = cv2.threshold(src,thresh,maxval,type)
用來簡單地卡閾值,adaptiveThreshold
方法能夠自適應二值化,參數blockSize決定局部閾值的block大小,其值較小時能夠提取邊緣。學習
灰度化
灰度圖像是一種具備從黑到白256級灰度色階或等級的單色圖像,每一個像素均用8位數據表示。圖像只有灰度等級,沒有顏色的變化。值越大,顯示效果越亮。 兩種方式:測試
- 求出每一個像素點的RGB三個份量的平均值,而後將此值賦予三個份量。(結果圖還是24bit深度)
- 根據RGB與YUV顏色空間的變化關係,創建亮度Y與RGB三個顏色通道的對應關係:Y=0.3R+0.59G+0.11B,以這個亮度值表達圖像的灰度值。(8bit深度)
img2 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
灰度變換與圖像加強
灰度變換
將每個像素的灰度值按照必定的數學變換公式轉換成一個新的灰度值,以此來加強圖像,擴展圖像的對比度,使圖像變清晰,使其特徵更加突出
變換方式
- 對數變換(低亮度區更清晰)
- 分段線性變換(經過壓縮高亮度區,擴展低亮度區使圖像的對比度增長)
- 指數變換(突出顯示高亮度區,使亮的更亮)
- 直方圖均衡化 經過統計灰度值的直方圖數據,再轉成累加機率函數,再映射到原來值的範圍以內。這樣使得本來相近的灰度值差值變大,像素間的對比度增大。這樣增長了全局對比度,尤爲使局部的對比更明顯。 OpenCV中有
cv2.equalizeHist(srcImg) -> dstImg
可直接使用。
彩色圖像直方圖均衡化
OpenCV 能夠對灰度圖進行equalizeHist(graySrc, dst)
; 咱們也能夠對彩色圖像作直方圖均衡化.
- 方法一. 對RGB三通道各自均衡化後,再組合輸出結果.
- 方法二. 將RGB圖像轉化爲HSI/YUV/YCbCr等顏色空間後,對亮度通道進行均衡化運算後再轉回RGB空間.
C++ 代碼實現。 方法一:各個通道分別均衡化:
vector<Mat> channels; split(inputImage, channels); Mat B,G,R; equalizeHist( channels[0], B ); equalizeHist( channels[1], G ); equalizeHist( channels[2], R ); vector<Mat> combined; combined.push_back(B); combined.push_back(G); combined.push_back(R); Mat result; merge(combined, result);
方法二: 亮度均衡化
Mat ycrcb; cvtColor(inputImage, ycrcb, COLOR_BGR2YCrCb); vector<Mat> channels; split(ycrcb, channels); equalizeHist(channels[0], channels[0]); Mat result; merge(channels,ycrcb); cvtColor(ycrcb, result, COLOR_YCrCb2BGR);
RGB各通道均衡化後圖像顏色有失真狀況,而亮度通道均衡化結果不會.均衡化是針對亮度的而不是針對顏色的.推薦使用YCbCr顏色空間對亮度進行均衡化,由於該顏色空間是爲數碼圖片設計的.
圖像噪聲
圖像加噪(椒鹽噪聲)
修改若干像素點的值爲某一像素值。生成單個隨機位置的代碼:
xi=int(np.random.uniform(0,img.shape[1])) xj=int(np.random.uniform(0,img.shape[0])) if img.ndim == 2: #gray dim img[xj,xi]=255 elif img.ndim == 3: img[xj,xi,:]=[B,G,R]
圖像加噪的目的
:爲了試驗圖像識別的效果,測試機器學習算法的能力。 pepper代指幾乎爲黑色的值,如30;salt代指幾乎爲白色的值,如170.
圖像濾波與去燥
均一化塊
核函數 K = $$\frac{1}{9} \left[ \begin{matrix} 1 & 1 & 1 \ 1 & 1 & 1 \ 1 & 1 & 1 \end{matrix} \right] \tag{1} $$ $$\frac{1}{10} \left[ \begin{matrix} 1 & 1 & 1 \ 1 & 2 & 1 \ 1 & 1 & 1 \end{matrix} \right] \tag{2} $$ $$\frac{1}{16} \left[ \begin{matrix} 1 & 2 & 1 \ 2 & 4 & 2 \ 1 & 2 & 1 \end{matrix} \right] \tag{3} $$ OpenCV 的 blur
函數能夠進行歸一化塊濾波操做。
領域平均法
核: 半徑爲1:$$\frac{1}{4} \left[ \begin{matrix} 0 & 1 & 0 \ 1 & 0 & 1 \ 0 & 1 & 0 \end{matrix} \right] \tag{1} $$ 半徑爲2:$$\frac{1}{8} \left[ \begin{matrix} 1 & 1 & 1 \ 1 & 0 & 1 \ 1 & 1 & 1 \end{matrix} \right] \tag{2} $$
中值濾波
與領域平均法的區別爲計算的是中值而不是平均值。
高斯濾波(高斯模糊)
對整幅圖像中的每一個像素計算領域內像素的加權平均值,權值即卷積核(或稱模板)。 OpenCV 有 GaussianBlur
函數。濾波器大小(標準差)越大,圖片結果越模糊。經過模糊化,把和整體佈局無關的細節都去掉了。經常使用於降噪,能夠對後續的處理有所幫助。
聚焦中心:使用高斯模糊進行模糊化,再用高斯函數賦予中心區域一個高權重。能夠圖像邊緣較爲柔和,焦點集中於中央區域。
雙邊濾波
cv2.bilateralFilter
是一種非線性的濾波方法,是結合圖像的空間鄰近度和像素值類似度的一種折中處理方法,同時考慮空域信息和灰度類似性,達到保邊去噪的目的。
卷積濾波
對每個像素,以其爲中心的卷積核大小的矩陣與卷積覈對應元素相乘再累加求和,和上邊的方法很類似。
gabor 濾波 ^gabor
gabor filter是經典的帶通濾波器之一,能夠用來提取圖像邊緣.(深度學習的相關論文有些以本身的模型可以學習出相似 gabor filter 的參數爲榮). 在圖像處理領域,以Dennis Gabor命名的Gabor濾波器,是一種用於紋理分析的線性濾波器,即它主要分析的是,圖像在某一特定區域的特定方向上是否有特定的頻率內容。當代許多視覺科學家認爲,Gabor濾波器的頻率和方向的表達與人類的視覺系統很類似,儘管並無實驗性證據和函數原理能證實這一觀點。研究發現,Gabor濾波器特別適合於紋理表示和辨別。在空間域中,2D Gabor濾波器是由正弦平面波調製的高斯核函數。
濾波與邊緣檢測
- Laplacian邊緣檢測使用了Sobel算子
- sobel非線性濾波,採用梯度的模的計算方式提取邊緣,銳化圖像。(能夠將顏色反轉,255-原值,以便更好地看出邊緣效果。)
- gabor 濾波能夠用來提取圖像邊緣。
圖像邊緣勾勒:將當前像素與鄰接的下部和右部的像素進行比較,若是類似,則將當前像素設置爲黑色,不然設置爲白色。(也能夠爲中間值設置一些中間色)。
圖像導數
圖像中的強度變化狀況一般能夠做爲重要的信息,強度的變化能夠用灰度圖像I(對於彩色圖像,一般對每一個顏色通道分別計算導數)的x和y方向導數$I_x,I_y$進行描述。 梯度向量爲$\nabla I=[I_x,I_y]^T$。 梯度有兩個重要的屬性, 一是梯度大小,描述了圖像強度變化的強弱: $$|\nabla I|=\sqrt{I_x^2+I_y^2}$$ 一是梯度的角度,描述了圖像在每一個像素點上強度變化最大的方向。 $$\alpha=\arctan2(I_y,I_x)$$
近似計算
圖像導數大多能夠經過卷積來簡單地計算離散近似值: $$I_x=ID_x$$ $$I_y=ID_y$$ 一般選擇Prewitt濾波器: $$ D_x= \begin{bmatrix} -1 & 0 & 1 \ -1 & 0 & 1 \ -1 & 0 & 1 \ \end{bmatrix} $$ $$ D_y= \begin{bmatrix} -1 & -1 & -1 \ 0 & 0 & 0 \ 1 & 1 & 1 \ \end{bmatrix} $$ 或Sobel濾波器: $$ D_x= \begin{bmatrix} -1 & 0 & 1 \ -2 & 0 & 2 \ -1 & 0 & 1 \ \end{bmatrix} $$ $$ D_y= \begin{bmatrix} -1 & -2 & -1 \ 0 & 0 & 0 \ 1 & 2 & 1 \ \end{bmatrix} $$ 這些導數濾波器可使用scipy.ndimage.filters
模塊的標準卷積操做來簡單實現。
上述方法的缺陷
濾波器的尺度須要隨着圖像分辨率的變化而變化。 爲了在圖像噪聲方面更穩健,以及在任意尺度上計算導數,咱們可使用高斯導數濾波器。filters.gaussian_filter()
模式識別
因爲歷史的緣由,圖像分類又叫作模式識別。 模式識別一般包括分解、特徵提取、分類幾個過程。分解的內容多是圖像、數據,這個分解過程實現自動化是較難的,分解後造成分區、有限的內容子集。特徵提取分析不一樣類的不一樣的特徵,須要對分解後的內容進行各類數學分析。分類基於特徵分析來進行。
模式識別難點
- 視角不一樣viewpoint variation
- 尺寸大小不一scale variation
- 變形deformation
- 光影等干擾occlusion/illumination conditions
- 背景干擾background clutter
- 同類物體的差別intra-class variation
圖像匹配
判斷圖片A是不是圖片B的子圖。
- 差分矩陣 差分矩陣 = 圖像A矩陣 - 圖像B矩陣 若差分矩陣每一個元素的和或矩陣均值小於某一閾值,則認爲匹配。
- 歐式距離 對於強噪聲環境下以及旋轉的圖像進行匹配時,歐式距離匹配方法相對於查分矩陣會有更好的效果。
def getEuclideanDist(x,y): ax=np.array(x) ay=np.array(y) return np.sqrt(np.sum((ax-ay)*(ax-ay)))
圖像增廣
圖像數據擴增(data augmentation):
- 水平翻轉(Horizontal flipping) (垂直翻轉根據視角是否有上下顛倒的需求而定)
- 隨機裁剪(Random cropping)
- 隨機放縮(Random scaling)
- 顏色抖動(Color jittering)
- 隨機平移(Random translation)
- 隨機剪切(Random shearing)
較經常使用的有水平翻轉, 隨機裁剪和顏色抖動. 而且能夠組合多種方式. 能夠改變saturation 和 value (HSV 顏色空間的S和V組件) 的值等方式.
圖像聚類
聚類能夠用於識別、劃分圖像數據集,組織與導航。此後能夠對聚類後的圖像進行類似性可視化。