詳解OpenCV實(shí)現(xiàn)特征提取的方法
前言
如何從圖像中提取特征?第一次聽(tīng)說(shuō)“特征提取”一詞是在 YouTube 上的機(jī)器學(xué)習(xí)視頻教程中,它清楚地解釋了我們?nèi)绾卧诖笮蛿?shù)據(jù)集中提取特征。
很簡(jiǎn)單,數(shù)據(jù)集的列就是特征。然而,當(dāng)我遇到計(jì)算機(jī)視覺(jué)主題時(shí),當(dāng)聽(tīng)說(shuō)我們將從圖像中提取特征時(shí),吃了一驚。是否開(kāi)始瀏覽圖像的每一列并取出每個(gè)像素?
一段時(shí)間后,明白了特征提取在計(jì)算機(jī)視覺(jué)中的含義。特征提取是降維過(guò)程的一部分,其中,原始數(shù)據(jù)的初始集被劃分并減少到更易于管理的組。
簡(jiǎn)單來(lái)說(shuō),對(duì)于圖像,每個(gè)像素都是一個(gè)數(shù)據(jù),圖像處理所做的只是從圖像中提取有用的信息,從而減少了數(shù)據(jù)量,但保留了描述圖像特征的像素。
圖像處理所做的只是從圖像中提取有用的信息,從而減少數(shù)據(jù)量,但保留描述圖像特征的像素。
在本文中,讓我們探索幾種從圖像中提取顏色、形狀和紋理特征的方法。這些方法基于處理圖像的經(jīng)驗(yàn),如果有任何錯(cuò)誤,請(qǐng)隨時(shí)添加或糾正它們!
1. 顏色
每次處理圖像項(xiàng)目時(shí),色彩空間都會(huì)自動(dòng)成為最先探索的地方。了解設(shè)置圖像環(huán)境的色彩空間對(duì)于提取正確的特征至關(guān)重要。
使用 OpenCV,我們可以將圖像的顏色空間轉(zhuǎn)換為提供的幾個(gè)選項(xiàng)之一,如 HSV、LAB、灰度、YCrCb、CMYK 等。每個(gè)顏色空間的簡(jiǎn)單分解:
a. HSV(色相飽和度值)
色調(diào):描述主波長(zhǎng),是指定顏色的通道
飽和度:描述色調(diào)/顏色的純度/色調(diào)
值:描述顏色的強(qiáng)度
import cv2 from google.colab.patches import cv2_imshow image = cv2.imread(image_file) hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) cv2_imshow(hsv_image)
RGB 與 HSV 顏色空間
b. LAB
L:描述顏色的亮度,與強(qiáng)度互換使用
A : 顏色成分范圍,從綠色到品紅色
B:從藍(lán)色到黃色的顏色分量
import cv2 from google.colab.patches import cv2_imshow image = cv2.imread(image_file) lab_image = cv2.cvtColor(image, cv2.COLOR_BGR2LAB) cv2_imshow(lab_image)
RGB 與 LAB 色彩空間
YCrCb
Y : 伽馬校正后從 RGB 顏色空間獲得的亮度
Cr:描述紅色 (R) 分量與亮度的距離
Cb:描述藍(lán)色 (B) 分量與亮度的距離
import cv2 from google.colab.patches import cv2_imshow image = cv2.imread(image_file) ycrcb_image = cv2.cvtColor(image, cv2.COLOR_BGR2YCrCb) cv2_imshow(ycrcb_image)
RGB 與 YCrCb 顏色空間
這些顏色空間的重要性有時(shí)會(huì)被低估。為了從圖像中獲得相關(guān)信息,這些顏色空間提供了一個(gè)機(jī)會(huì)來(lái)識(shí)別特征是否在每個(gè)圖像中看起來(lái)更不同。關(guān)于色彩空間最瘋狂的事情是我們可以用不同的色彩空間執(zhí)行加法/減法,結(jié)果你會(huì)感到驚訝!
探索圖像色彩空間的另一個(gè)有用函數(shù)是簡(jiǎn)單地使用*numpy.mean()*,它給出圖像數(shù)據(jù)集中色彩空間中每個(gè)通道的平均值。如果我們想查看顏色空間中的哪個(gè)通道主導(dǎo)數(shù)據(jù)集,這將特別有用。
import cv2 from google.colab.patches import cv2_imshow import numpy as np import plotly.figure_factory as ff # Check the distribution of red values red_values = [] for i in range(len(images)): red_value = np.mean(images[i][:, :, 0]) red_values.append(red_value) # Check the distribution of green values green_values = [] for i in range(len(images)): green_value = np.mean(images[i][:, :, 1]) green_values.append(green_value) # Check the distribution of blue values blue_values = [] for i in range(len(images)): blue_value = np.mean(images[i][:, :, 2]) blue_values.append(blue_value) # Plotting the histogram fig = ff.create_distplot([red_values, green_values, blue_values], group_labels=["R", "G", "B"], colors=['red', 'green', 'blue']) fig.update_layout(showlegend=True, template="simple_white") fig.update_layout(title_text='Distribution of channel values across images in RGB') fig.data[0].marker.line.color = 'rgb(0, 0, 0)' fig.data[0].marker.line.width = 0.5 fig.data[1].marker.line.color = 'rgb(0, 0, 0)' fig.data[1].marker.line.width = 0.5 fig.data[2].marker.line.color = 'rgb(0, 0, 0)' fig.data[2].marker.line.width = 0.5 fig
一旦我們已經(jīng)識(shí)別或探索了足夠多的圖像色彩空間,并確定我們只對(duì)單個(gè)通道感興趣,我們就可以使用*cv2.inRange()*來(lái)屏蔽不需要的像素。這在 HSV 顏色空間中尤其實(shí)用。
import cv2 from google.colab.patches import cv2_imshow # Reading the original image image_spot = cv2.imread(image_file) cv2_imshow(image_spot) # Converting it to HSV color space hsv_image_spot = cv2.cvtColor(image_spot, cv2.COLOR_BGR2HSV) cv2_imshow(hsv_image_spot) # Setting the black pixel mask and perform bitwise_and to get only the black pixels mask = cv2.inRange(hsv_image_spot, (0, 0, 0), (180, 255, 40)) masked = cv2.bitwise_and(hsv_image_spot, hsv_image_spot, mask=mask) cv2_imshow(masked)
RGB vs HSV vs Masked 圖像使用 cv2.inRange() 檢索黑點(diǎn)
有時(shí),我們甚至可以使用*cv2.kmeans()來(lái)量化圖像的顏色,從本質(zhì)上將顏色減少到幾個(gè)整潔的像素。根據(jù)我們的目標(biāo),我們可以使用cv2.inRange()*來(lái)檢索目標(biāo)像素。通常,這個(gè)函數(shù)在識(shí)別圖像的重要部分時(shí)很有魅力,我總是會(huì)在繼續(xù)使用其他顏色特征提取方法之前檢查這個(gè)函數(shù)。
import cv2 from google.colab.patches import cv2_imshow image_spot_reshaped = image_spot.reshape((image_spot.shape[0] * image_spot.shape[1], 3)) # convert to np.float32 Z = np.float32(image_spot_reshaped) # define criteria, number of clusters(K) and apply kmeans() criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) K = 2 ret, label, center = cv2.kmeans(Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) # Now convert back into uint8, and make original image center = np.uint8(center) res = center[label.flatten()] res2 = res.reshape((image_spot.shape)) cv2_imshow(res2)
使用 cv2.kmeans() 進(jìn)行顏色量化 (K=2)
2. 形狀
一旦我們充分探索了顏色特征,我們可能會(huì)在某個(gè)時(shí)候想要提取圖像中的形狀。
例如,你的任務(wù)是區(qū)分不同類型的酒杯。顏色在這里可能并不重要,但形狀可以告訴我們很多關(guān)于它們的信息。
同樣,我要做的是將圖像轉(zhuǎn)換為其他顏色空間,看看是否有任何顏色空間會(huì)使對(duì)象的邊緣或形狀更加突出。然后,我們可以使用*cv2.findContours()*來(lái)檢索圖像中的所有輪廓。從這里開(kāi)始,我們將檢查感興趣輪廓的所有屬性。
理想情況下,一旦我們能夠提取定義輪廓形狀的正確屬性,我們會(huì)將其應(yīng)用于數(shù)據(jù)集中的所有圖像,提取的數(shù)字將成為我們新的非圖像數(shù)據(jù)集??纯次覀?nèi)绾螌?shù)據(jù)量減少到只有一列形狀特征,仍然可以解釋我們的酒杯圖像嗎?
讓我們探索一下我們可以使用 OpenCV 從輪廓中提取的許多屬性。正如之前已經(jīng)展示過(guò)的,我將在此處提供鏈接以供參考
- 矩
- 輪廓面積
- 輪廓周長(zhǎng)
- 輪廓近似
- 凸包
- 凸性檢測(cè)
- 矩形邊界
- 最小外接圓
- 擬合橢圓
- 擬合直線
在很多情況下發(fā)現(xiàn) cv2.HoughCircles() 和 cv2.SimpleBlobDetector() 在檢測(cè)圓圈時(shí)都沒(méi)有給出準(zhǔn)確的結(jié)果,原因之一可能是預(yù)處理圖像中的圓圈不夠明顯。但是,cv2.SimpleBlobDetector() 仍然提供一些方便的內(nèi)置過(guò)濾器,如慣性、凸性、圓度和面積,以盡可能準(zhǔn)確地檢索圓。
3. 紋理
在某些時(shí)候,我們可能想要提取紋理特征,因?yàn)槲覀円呀?jīng)用盡了顏色和形狀特征。灰度共生矩陣(GLCM)和局部二值模式(LBP)都是我用過(guò)的紋理特征,不過(guò)大家常用的其他紋理特征也可以在下方評(píng)論,我很想知道!
a. GLCM
很難在圖像方面特別理解 GLCM 的概念。從統(tǒng)計(jì)學(xué)上講,GLCM 是一種考慮像素空間關(guān)系的紋理檢查方法。它的工作原理是計(jì)算具有特定值和特定空間關(guān)系的像素對(duì)在圖像中出現(xiàn)的頻率,創(chuàng)建 GLCM,然后從該矩陣中提取統(tǒng)計(jì)度量。
包含 GLCM 功能的一個(gè)易于使用的包是scikit-image包。在 GLCM 中,我們還可以推導(dǎo)出一些描述更多關(guān)于紋理的統(tǒng)計(jì)數(shù)據(jù),例如:
對(duì)比度:測(cè)量灰度共生矩陣的局部變化。
相關(guān)性:測(cè)量指定像素對(duì)的聯(lián)合概率出現(xiàn)。
平方:提供 GLCM 中元素的平方和。也稱為均勻性或角二階矩。
同質(zhì)性:測(cè)量 GLCM 中元素分布與 GLCM 對(duì)角線的接近程度。
import cv2 from google.colab.patches import cv2_imshow image_spot = cv2.imread(image_file) gray = cv2.cvtColor(image_spot, cv2.COLOR_BGR2GRAY) # Find the GLCM import skimage.feature as feature # Param: # source image # List of pixel pair distance offsets - here 1 in each direction # List of pixel pair angles in radians graycom = feature.greycomatrix(gray, [1], [0, np.pi/4, np.pi/2, 3*np.pi/4], levels=256) # Find the GLCM properties contrast = feature.greycoprops(graycom, 'contrast') dissimilarity = feature.greycoprops(graycom, 'dissimilarity') homogeneity = feature.greycoprops(graycom, 'homogeneity') energy = feature.greycoprops(graycom, 'energy') correlation = feature.greycoprops(graycom, 'correlation') ASM = feature.greycoprops(graycom, 'ASM') print("Contrast: {}".format(contrast)) print("Dissimilarity: {}".format(dissimilarity)) print("Homogeneity: {}".format(homogeneity)) print("Energy: {}".format(energy)) print("Correlation: {}".format(correlation)) print("ASM: {}".format(ASM))
從灰度共生矩陣 (GLCM) 獲得的特征
b. LBP
由于已經(jīng)有很多文章解釋了本地二進(jìn)制模式,在這里節(jié)省你的時(shí)間并在此處分享參考鏈接:
- https://www.pyimagesearch.com/2015/12/07/local-binary-patterns-with-python-opencv/
- https://towardsdatascience.com/face-recognition-how-lbph-works-90ec258c3d6b
簡(jiǎn)而言之,LBP 是一種紋理算子,它通過(guò)對(duì)周圍像素進(jìn)行閾值處理并以二進(jìn)制數(shù)表示它們來(lái)標(biāo)記圖像的像素。LBP 讓我們吃驚的是,該操作返回的灰度圖像清晰地顯示了圖像中的紋理。在這里,我們嘗試根據(jù)理解分解LBP內(nèi)部的操作:
對(duì)于每個(gè)中心像素,我們嘗試與周圍像素進(jìn)行比較,如果中心像素大于或小于周圍像素,則給它們一個(gè)標(biāo)簽。結(jié)果,我們周圍有 8 個(gè)標(biāo)簽,并且通過(guò)在整個(gè)圖像中保持順時(shí)針或逆時(shí)針?lè)较虻囊恢履J?,我們將它們布置?2d 數(shù)組中并將它們轉(zhuǎn)換為二進(jìn)制數(shù)。
在我們對(duì)整個(gè)圖像的每個(gè)像素執(zhí)行操作后會(huì)出現(xiàn)這樣的矩陣。
從這里,我們可以看到,生成的矩陣與我們的原始圖像具有相同的形狀,我們能夠像繪制圖像一樣繪制和顯示 LBP。
import cv2 from google.colab.patches import cv2_imshow class LocalBinaryPatterns: def __init__(self, numPoints, radius): self.numPoints = numPoints self.radius = radius def describe(self, image, eps = 1e-7): lbp = feature.local_binary_pattern(image, self.numPoints, self.radius, method="uniform") (hist, _) = np.histogram(lbp.ravel(), bins=np.arange(0, self.numPoints+3), range=(0, self.numPoints + 2)) # Normalize the histogram hist = hist.astype('float') hist /= (hist.sum() + eps) return hist, lbp image = cv2.imread(image_file) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) desc = LocalBinaryPatterns(24, 8) hist, lbp = desc.describe(gray) print("Histogram of Local Binary Pattern value: {}".format(hist)) contrast = contrast.flatten() dissimilarity = dissimilarity.flatten() homogeneity = homogeneity.flatten() energy = energy.flatten() correlation = correlation.flatten() ASM = ASM.flatten() hist = hist.flatten() features = np.concatenate((contrast, dissimilarity, homogeneity, energy, correlation, ASM, hist), axis=0) cv2_imshow(gray) cv2_imshow(lbp)
灰度圖像與 LBP 表示
類似地,我們可以將 LBP 存儲(chǔ)在直方圖中,并將其視為一個(gè)特征,我們可以將其輸入分類器以進(jìn)行分類。PyImageSearch 的 Adrian Rosebrock 在這方面做了一個(gè)驚人的例子!
我在紋理特征方面沒(méi)有太多經(jīng)驗(yàn),但是在收集更多信息并嘗試在項(xiàng)目中實(shí)現(xiàn)它們之后,我有興趣深入研究它。
結(jié)論
總而言之,在這篇文章中,分享了在之前的項(xiàng)目中使用過(guò)的三個(gè)特征的經(jīng)驗(yàn),主要是顏色、形狀和紋理特征。連同代碼和結(jié)果,試圖說(shuō)明我采取每一步的原因。
到此這篇關(guān)于詳解OpenCV實(shí)現(xiàn)特征提取的方法的文章就介紹到這了,更多相關(guān)OpenCV特征提取內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python對(duì)常見(jiàn)數(shù)據(jù)類型的遍歷解析
這篇文章主要介紹了python對(duì)常見(jiàn)數(shù)據(jù)類型的遍歷解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08Python Pandas數(shù)據(jù)分析之iloc和loc的用法詳解
Pandas 是一個(gè)開(kāi)放源碼、BSD 許可的庫(kù),提供高性能、易于使用的數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)分析工具,它是一個(gè)強(qiáng)大的分析結(jié)構(gòu)化數(shù)據(jù)的工具集,基礎(chǔ)是 Numpy2021-11-11Python完全識(shí)別驗(yàn)證碼自動(dòng)登錄實(shí)例詳解
今天小編就為大家分享一篇Python完全識(shí)別驗(yàn)證碼自動(dòng)登錄實(shí)例詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11使用IDLE的Python shell窗口實(shí)例詳解
在本篇文章里小編給各位整理的是關(guān)于使用IDLE的Python shell窗口實(shí)例詳解內(nèi)容,有興趣的朋友們學(xué)習(xí)下。2019-11-11pycharm自定義TODO類注釋以及高亮顏色的設(shè)置方法
這篇文章主要介紹了pycharm自定義TODO類注釋以及高亮顏色的設(shè)置方法,文中通過(guò)圖文結(jié)合的方式給大家介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2024-03-03