計算機視覺是當前行業中比較熱門的領域之一。由于技術和研究的飛速發展,它正在蓬勃發展。但這對于新來者來說仍是個艱巨的任務。XR開發者或數據科學家在過渡到計算機視覺時面臨著一些常見的挑戰,包括:
1.我們如何清理圖像數據集?圖像有不同的形狀和大小
2.數據獲取中一直存在的問題。在建立計算機視覺模型之前,我們應該收集更多圖像嗎?
3.學習深度學習對建立計算機視覺模型是否必不可少?我們可以不使用機器學習技術嗎?
4.我們可以在自己的機器上建立計算機vsiion模型嗎?并非每個人都可以使用GPU和TPU!
什么是CV
在進入OpenCV之前,讓我快速解釋一下什么是計算機視覺。對本文其余部分將要討論的內容有一個直觀的了解。人類能夠自然地看到和感知世界。通過視覺和感知的天賦從周圍環境收集信息是我們的第二天性。
快速瀏覽上圖。我們花了不到一秒鐘的時間發現其中有一只貓,一條狗和一條人的腿。對于機器,這種學習過程變得很復雜。解析圖像和檢測對象的過程涉及多個復雜步驟,包括特征提?。ㄟ吘墮z測,形狀等),特征分類等。
計算機視覺是當前行業中最熱門的領域之一??梢灶A計,未來2-4年將會有大量的職位空缺。那么問題是你準備好利用這些機會了嗎?請花點時間考慮一下–當你想到計算機視覺時,會想到哪些應用程序或產品?我們每天都使用其中一些,使用面部識別功能解鎖手機,智能手機攝像頭,自動駕駛汽車等功能,無處不在。
關于OpenCV
OpenCV庫最初是英特爾的一項研究項目。就其擁有的功能而言,它是目前最大的計算機視覺庫。OpenCV包含2500多種算法的實現!它可免費用于商業和學術目的。該庫具有適用于多種語言的接口,包括Python,Java和C ++。
OpenCV的第一個版本1.0于2006年發布,此后OpenCV社區發展迅猛。
現在,讓我們將注意力轉移到本文背后的思想上-OpenCV提供的眾多功能!我們將從數據科學家的角度研究OpenCV,并了解一些使開發和理解計算機視覺模型的任務變得更加容易的功能。
讀取,寫入和顯示圖像
機器使用數字來查看和處理一切,包括圖像和文本。你如何把圖像轉換成數字?沒錯,像素!
每個數字表示該特定位置的像素強度。在上面的圖像中,我展示了灰度圖像的像素值,其中每個像素只包含一個值,即該位置的黑色強度。
注意,彩色圖像對于單個像素有多個值。這些值表示各自通道的強度——例如,RGB圖像的紅色、綠色和藍色通道。
讀和寫圖像是必不可少的任何計算機視覺項目。OpenCV庫使這個函數變得非常簡單。
#import the libraries
import numpy as np
import matplotlib.pyplot as plt
import cv2
%matplotlibinline
#readingtheimage
image = cv2.imread('index.png')
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
#plotting the image
plt.imshow(image)
#saving image
cv2.imwrite('test_write.jpg',image)
默認情況下,imread函數以BGR(藍綠色紅色)格式讀取圖像。我們可以使用imread函數中的額外標志來讀取不同格式的圖像:
-
cv2.IMREAD_COLOR: 加載彩色圖像的默認標志
-
cv2.IMREAD_GRAYSCALE: 以灰度格式加載圖像
-
cv2.IMREAD_UNCHANGED: 以給定格式(包括Alpha通道)加載圖像。Alpha通道存儲透明度信息,Alpha通道的值越高,像素越不透明。
改變色彩空間
顏色空間是一種協議,用于以一種使顏色易于復制的方式表示顏色。我們知道灰度圖像有單個像素值,而彩色圖像每個像素包含3個值——紅、綠、藍通道的強度。
大多數計算機視覺用例處理RGB格式的圖像。然而,像視頻壓縮和設備獨立存儲這樣的應用程序嚴重依賴于其他顏色空間,比如顏色-飽和度-值或HSV顏色空間。
正如你所理解的,RGB圖像是由不同顏色通道的顏色強度組成的,即強度和顏色信息混合在RGB顏色空間中,而在HSV顏色空間中,顏色和強度信息是相互分離的。這使得HSV顏色空間對光線變化更加健壯。OpenCV默認以BGR格式讀取給定的圖像。因此,在使用OpenCV讀取圖像時,需要將圖像的顏色空間從BGR更改為RGB。讓我們看看怎么做:
#import the required libraries
import numpy as np
import matplotlib.pyplot as plt
import cv2
%matplotlib inline
image = cv2.imread('index.jpg')
#converting image to Gray scale
gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
#plotting the grayscale image
plt.imshow(gray_image)
#converting image to HSV format
hsv_image = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
#plotting the HSV image
plt.imshow(hsv_image)
調整圖像大小
機器學習模型在固定大小的輸入下工作。同樣的想法也適用于計算機視覺模型。我們用于訓練模型的圖像必須具有相同的尺寸。
現在,如果我們通過從各種來源抓取圖像來創建自己的數據集,這可能會成為問題。這就是調整圖像大小的功能。
使用OpenCV可以輕松地放大和縮小圖像。當我們需要將圖像轉換為模型的輸入形狀時,此操作對于訓練深度學習模型很有用。OpenCV支持不同的插值和下采樣方法,這些參數可以由以下參數使用:
1.INTER_NEAREST: 最近鄰居插值
2.INTER_LINEAR: 雙線性插值
3.INTER_AREA: 使用像素面積關系進行重采樣
4.INTER_CUBIC: 在4×4像素鄰域上的雙三次插值
5.INTER_LANCZOS4:在8×8鄰域內進行Lanczos插值
OpenCV的調整大小功能默認情況下使用雙線性插值。
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#reading the image
image = cv2.imread('index.jpg')
#converting image to size (100,100,3)
smaller_image = cv2.resize(image,(100,100),inerpolation='linear')
#plot the resized image
plt.imshow(smaller_image)
影像旋轉
“你需要大量數據來訓練深度學習模型”。大多數深度學習算法在很大程度上取決于數據的質量和數量。但是,如果你沒有足夠大的數據集怎么辦?并非所有人都能負擔得起手動收集和標記圖像的費用。
假設我們正在建立一個圖像分類模型來識別圖像中存在的動物。因此,下面顯示的兩個圖像都應歸類為“狗”:
但是,如果沒有對第二幅圖像進行訓練,該模型可能會發現很難將其歸類為狗。那么我們應該怎么做呢?
讓我來介紹一下數據擴充技術。該方法允許我們生成更多的樣本來訓練我們的深度學習模型。數據擴充利用現有的數據樣本,通過應用旋轉、縮放、平移等圖像操作來生成新的數據樣本。這使我們的模型對輸入的變化具有魯棒性,并導致更好的泛化。
旋轉是最常用和最容易實現的數據擴充技術之一。顧名思義,它包括以任意角度旋轉圖像,并為其提供與原始圖像相同的標簽。想想你在手機中旋轉圖像以達到一定角度的次數——這基本上就是這個功能的作用。
#importing the required libraries
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
image = cv2.imread('index.png')
rows,cols = image.shape[:2]
#(col/2,rows/2) is the center of rotation for the image
# M is the cordinates of the center
M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(image,M,(cols,rows))
plt.imshow(dst)
圖片翻譯
圖像平移是一種幾何變換,它將圖像中每個對象的位置映射到最終輸出圖像中的新位置。平移操作之后,輸入圖像中位置(x,y)處的對象將移動到新位置(X,Y):
X = x + dx
Y = y + dy
在此,dx和dy是沿不同維度的各自平移。圖像平移可用于為模型增加平移不變性,因為通過翻譯,我們可以更改圖像中對象的位置,從而使模型具有更多多樣性,從而導致更好的泛化性。
以下面的圖片為例。即使圖像中沒有完整的鞋子,模型也應該能夠將其歸類為鞋子。
此轉換功能通常在圖像預處理階段使用。查看下面的代碼,看看它在實際情況下如何工作:
#importing the required libraries
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
#reading the image
image = cv2.imread('index.png')
#shifting the image 100 pixels in both dimensions
M = np.float32([[1,0,-100],[0,1,-100]])
dst = cv2.warpAffine(image,M,(cols,rows))
plt.imshow(dst)
簡單圖像閾值
閾值化是一種圖像分割方法。它將像素值與閾值進行比較,并相應地進行更新。OpenCV支持閾值的多種變化??梢赃@樣定義一個簡單的閾值函數:
如果Image(x,y)> threshold,則Image(x,y)= 1
否則,Image(x,y)= 0
閾值只能應用于灰度圖像。圖像閾值化的一個簡單應用就是將圖像分為前景和背景。
#importing the required libraries
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
#here 0 means that the image is loaded in gray scale format
gray_image = cv2.imread('index.png',0)
ret,thresh_binary = cv2.threshold(gray_image,127,255,cv2.THRESH_BINARY)
ret,thresh_binary_inv = cv2.threshold(gray_image,127,255,cv2.THRESH_BINARY_INV)
ret,thresh_trunc = cv2.threshold(gray_image,127,255,cv2.THRESH_TRUNC)
ret,thresh_tozero = cv2.threshold(gray_image,127,255,cv2.THRESH_TOZERO)
ret,thresh_tozero_inv = cv2.threshold(gray_image,127,255,cv2.THRESH_TOZERO_INV)
#DISPLAYING THE DIFFERENT THRESHOLDING STYLES
names = ['Oiriginal Image','BINARY','THRESH_BINARY_INV','THRESH_TRUNC','THRESH_TOZERO','THRESH_TOZERO_INV']
images = gray_image,thresh_binary,thresh_binary_inv,thresh_trunc,thresh_tozero,thresh_tozero_inv
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(names[i])
plt.xticks([]),plt.yticks([])
plt.show()
自適應閾值
在自適應閾值的情況下,對于圖像的不同部分使用不同的閾值。此功能可為光照條件變化的圖像提供更好的結果,因此稱為“自適應”。Otsu的二值化方法為整個圖像找到最佳閾值。它適用于雙峰圖像(直方圖中具有2個峰的圖像)。
#import the libraries
import numpy as np
import matplotlib.pyplot as plt
import cv2
%matplotlib inline
#ADAPTIVE THRESHOLDING
gray_image = cv2.imread('index.png',0)
ret,thresh_global = cv2.threshold(gray_image,127,255,cv2.THRESH_BINARY)
#here 11 is the pixel neighbourhood that is used to calculate the threshold value
thresh_mean = cv2.adaptiveThreshold(gray_image,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
thresh_gaussian = cv2.adaptiveThreshold(gray_image,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
names = ['Original Image','Global Thresholding','Adaptive Mean Threshold','Adaptive Gaussian Thresholding']
images = [gray_image,thresh_global,thresh_mean,thresh_gaussian]
for i in range(4):
plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
plt.title(names[i])
plt.xticks([]),plt.yticks([])
plt.show()
圖像分割(分水嶺算法)
圖像分割是將圖像中的每個像素分類為某個類的任務。例如,將每個像素分類為前景或背景。圖像分割對于從圖像中提取相關部分非常重要。
分水嶺算法是一種經典的圖像分割算法。它將圖像中的像素值視為地形。為了找到對象邊界,它以初始標記作為輸入。然后,該算法開始從標記中泛洪盆地,直到標記在對象邊界處相遇。
假設我們有多個盆地?,F在,如果我們用不同顏色的水填充不同的盆地,那么不同顏色的交點將為我們提供對象邊界。
#importing required libraries
import numpy as np
import cv2
import matplotlib.pyplot as plt
#reading the image
image = cv2.imread('coins.jpg')
#converting image to grayscale format
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
#apply thresholding
ret,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
#get a kernel
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,iterations = 2)
#extract the background from image
sure_bg = cv2.dilate(opening,kernel,iterations = 3)
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret,sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_bg)
ret,markers = cv2.connectedComponents(sure_fg)
markers = markers+1
markers[unknown==255] = 0
markers = cv2.watershed(image,markers)
image[markers==-1] = [255,0,0]
plt.imshow(sure_fg)
換位運算
按位運算包括AND,OR,NOT和XOR。你可能在編程課上還記得它們!在計算機視覺中,當我們有一個遮罩圖像并且想要將該遮罩應用于另一個圖像以提取感興趣區域時,這些操作非常有用。
#import required libraries
import numpy as np
import matplotlib.pyplot as plt
import cv2
%matplotlib inline
#read the image
image = cv2.imread('coins.jpg')
#apply thresholdin
ret,mask = cv2.threshold(sure_fg,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
#apply AND operation on image and mask generated by thrresholding
final = cv2.bitwise_and(image,image,mask = mask)
#plot the result
plt.imshow(final)
在上圖中,我們可以看到使用分水嶺算法計算的輸入圖像及其分割蒙版。此外,我們應用了按位“與”運算以從圖像中刪除背景并從圖像中提取相關部分。
邊緣檢測
邊緣是圖像中圖像亮度急劇變化或不連續的點。這種不連續通常對應于:
-
深度不連續
-
表面取向不連續
-
材料特性的變化
-
場景照明的變化
邊緣是圖像的非常有用的功能,可以用于不同的應用程序,例如圖像中的對象分類和定位。甚至深度學習模型也會計算邊緣特征,以提取有關圖像中存在的對象的信息。
邊緣與輪廓不同,因為它們與對象無關,而是表示圖像像素值的變化。邊緣檢測可用于圖像分割甚至圖像銳化。
#import the required libraries
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
#read the image
image = cv2.imread('coins.jpg')
#calculate the edges using Canny edge algorithm
edges = cv2.Canny(image,100,200)
#plot the edges
plt.imshow(edges)
圖像過濾
在圖像過濾中,使用像素的鄰近值更新像素值。但是這些值首先如何更新?
嗯,有多種更新像素值的方法,例如從鄰居中選擇最大值,使用鄰居的平均值等。每種方法都有其自己的用途。例如,將鄰域中的像素值平均用于圖像模糊。
高斯濾波還用于圖像模糊,該模糊基于相鄰像素與所考慮像素的距離為它們賦予不同的權重。
對于圖像過濾,我們使用內核。內核是具有不同形狀的數字矩陣,例如3 x 3、5 x 5等。內核用于計算帶有圖像一部分的點積。在計算像素的新值時,內核中心與像素重疊。相鄰像素值與內核中的相應值相乘。將計算出的值分配給與內核中心一致的像素。
#importing the required libraries
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
image = cv2.imread('index.png')
#using the averaging kernel for image smoothening
averaging_kernel = np.ones((3,3),np.float32)/9
filtered_image = cv2.filter2D(image,-1,kernel)
plt.imshow(dst)
#get a one dimensional Gaussian Kernel
gaussian_kernel_x = cv2.getGaussianKernel(5,1)
gaussian_kernel_y = cv2.getGaussianKernel(5,1)
#converting to two dimensional kernel using matrix multiplication
gaussian_kernel = gaussian_kernel_x * gaussian_kernel_y.T
#you can also use cv2.GaussianBLurring(image,(shape of kernel),standard deviation) instead of cv2.filter2D
filtered_image = cv2.filter2D(image,-1,gaussian_kernel)
plt.imshow()
在上面的輸出中,右側的圖像顯示了在輸入圖像上應用高斯核的結果。我們可以看到原始圖像的邊緣被抑制了。具有不同sigma值的高斯核被廣泛用于計算我們圖像的高斯差。這是特征提取過程中的重要步驟,因為它可以減少圖像中存在的噪點。
影像輪廓
輪廓是點或線段的閉合曲線,代表圖像中對象的邊界。輪廓實質上是圖像中對象的形狀。
與邊緣不同,輪廓不是圖像的一部分。相反,它們是與圖像中對象形狀相對應的點和線段的抽象集合。
我們可以使用輪廓來計算圖像中對象的數量,根據對象的形狀對對象進行分類,或者從圖像中選擇特定形狀的對象。
#importing the required libraries
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
image = cv2.imread('shapes.png')
#converting RGB image to Binary
gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray_image,127,255,0)
#calculate the contours from binary image
im,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
with_contours = cv2.drawContours(image,contours,-1,(0,255,0),3)
plt.imshow(with_contours)
尺度不變特征變換(SIFT)
關鍵點是在處理圖像時應注意的概念。這些基本上是圖像中的關注點。關鍵點類似于給定圖像的特征。
它們是定義圖像中有趣內容的位置。關鍵點很重要,因為無論如何修改圖像(旋轉,縮小,擴展,變形),我們始終會為圖像找到相同的關鍵點。
尺度不變特征變換(SIFT)是一種非常流行的關鍵點檢測算法。它包括以下步驟:
-
尺度空間極值檢測
-
關鍵點本地化
-
方向分配
-
關鍵點描述符
-
關鍵點匹配
從SIFT提取的特征可用于圖像拼接,物體檢測等應用。以下代碼和輸出顯示了關鍵點及其使用SIFT計算得出的方向。
#import required libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#show OpenCV version
print(cv2.__version__)
#read the iamge and convert to grayscale
image = cv2.imread('index.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
#create sift object
sift = cv2.xfeatures2d.SIFT_create()
#calculate keypoints and their orientation
keypoints,descriptors = sift.detectAndCompute(gray,None)
#plot keypoints on the image
with_keypoints = cv2.drawKeypoints(gray,keypoints)
#plot the image
plt.imshow(with_keypoints)
SURF
SURF是SIFT的增強版本。它的工作速度更快,并且對圖像轉換更健壯。在SIFT中,比例空間使用高斯的拉普拉斯算子近似。什么是高斯的拉普拉斯算子?
拉普拉斯算子是用于計算圖像邊緣的內核。拉普拉斯核通過近似圖像的二階導數來工作。因此,它對噪聲非常敏感。我們通常將高斯核應用于拉普拉斯核之前的圖像,因此將其命名為高斯拉普拉斯。
在SURF中,高斯的拉普拉斯算子是使用盒式濾波器(核)來計算的。盒式濾波器的卷積可以針對不同的比例并行進行,這是SURF速度提高的根本原因(與SIFT相比)。
#import required libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#show OpenCV version
print(cv2.__version__)
#read image and convert to grayscale
image = cv2.imread('index.png')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
#instantiate surf object
surf = cv2.xfeatures2d.SURF_create(400)
#calculate keypoints and their orientation
keypoints,descriptors = surf.detectAndCompute(gray,None)
with_keypoints = cv2.drawKeypoints(gray,keypoints)
plt.imshow(with_keypoints)
特征匹配
可以匹配使用SIFT或SURF從不同圖像中提取的特征,以找到存在于不同圖像中的相似對象/圖案。OpenCV庫支持多種功能匹配算法,例如蠻力匹配,knn特征匹配等。
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
#reading images in grayscale format
image1 = cv2.imread('messi.jpg',0)
image2 = cv2.imread('team.jpg',0)
#finding out the keypoints and their descriptors
keypoints1,descriptors1 = cv2.detectAndCompute(image1,None)
keypoints2,descriptors2 = cv2.detectAndCompute(image2,None)
#matching the descriptors from both the images
bf = cv2.BFMatcher()
matches = bf.knnMatch(ds1,ds2,k = 2)
#selecting only the good features
good_matches = []
for m,n in matches:
if m.distance < 0.75*n.distance:
good.append([m])
image3 = cv2.drawMatchesKnn(image1,kp1,image2,kp2,good,flags = 2)
在上圖中,我們可以看到從原始圖像(左側)提取的關鍵點與其旋轉版本的關鍵點匹配。這是因為特征是使用SIFT提取的,而SIFT對于此類變換是不變的。
人臉檢測
OpenCV支持基于haar級聯的對象檢測。Haar級聯是基于機器學習的分類器,可計算圖像中的不同特征(如邊緣,線條等)。然后,這些分類器使用多個正樣本和負樣本進行訓練。
OpenCV Github存儲庫中提供了針對不同對象(如面部,眼睛等)的訓練分類器,你還可以針對任何對象訓練自己的haar級聯。
#import required libraries
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
%matplotlib inline
#load the classifiers downloaded
face_cascade = cv.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv.CascadeClassifier('haarcascade_eye.xml')
#read the image and convert to grayscale format
img = cv.imread('rotated_face.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
#calculate coordinates
faces = face_cascade.detectMultiScale(gray, 1.1, 4)
for (x,y,w,h) in faces:
cv.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
#draw bounding boxes around detected features
for (ex,ey,ew,eh) in eyes:
cv.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
#plot the image
plt.imshow(img)
#write image
cv2.imwrite('face_detection.jpg',img)
-
計算機視覺
+關注
關注
8文章
1698瀏覽量
46033 -
機器學習
+關注
關注
66文章
8425瀏覽量
132774 -
OpenCV
+關注
關注
31文章
635瀏覽量
41388
原文標題:【建議收藏】16個OpenCV函數開始你的計算機視覺之旅
文章出處:【微信號:vision263com,微信公眾號:新機器視覺】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論