opencv深入淺出了解機器學習和深度學習
機器學習
kNN算法
kNN算法將找出k個距離最近的鄰居作為目標的 同一類別
圖解kNN算法
使用OpenCV的ml模塊中的kNN算法的基本步驟如下。
(1)調用cv2.mL.KNearest_ create()函數創(chuàng)建kNN分類器。
(2)將訓練數據和標志作為輸入,調用kNN分類器的train()方法訓練模型。
(3)將待分類數據作為輸入,調用kNN分類器的findNearest()方法找出K個最近鄰居,返回 分類結果的相關信息。
下面的代碼在圖像中隨機選擇20個點,為每個點隨機分配標志( 0或1 );圖像中用矩形表示 標志0,用三角形表示標志1;再隨機新增一個點,用kNN算法找出其鄰居,并確定其標志(即完 成分類)。
import cv2 import numpy as np import matplotlib.pyplot as plt points = np. random. randint(0,100, (20,2)) #隨機選擇20個點 labels = np. random. randint(0,2,(20,1)) #為隨機點隨機分配標志 label0s = points[labels.ravel()==0] #分出標志為0的點 plt. scatter(label0s[:,0],label0s[:,1],80,'b','s') #將標志為0的點繪制為藍色矩形 label1s = points[labels.ravel()==1] #分出標志為1的點 plt. scatter(label1s[:,0],label1s[:,1],80,'r','^') #將標志為1的點繪制為紅色三角形 newpoint = np.random.randint(0,100,(1,2)) #隨機選擇一個點,下面確定其分類 plt.scatter(newpoint[:,0],newpoint[:,1],80,'g','o') #將待分類新點繪制為綠色圓點 plt.show() #進一步使用kNN算法確認待分類新點的類別、3個最近鄰居和距離 knn = cv2.ml.KNearest_create() #創(chuàng)建kNN分類器 knn.train(points.astype(np.float32).cv2.ml.ROW_SAMPLE,labels.astype(np. float32)) #訓練模型 ret,results,neighbours,dist = knn.findNearest(newpoint.astype(np.float32), 3) #找出3個最近鄰居 print("新點標志: %s" % results) print("鄰居: %s" % neighbours) print("距離: %s" % dist)
新點標志: [[1.]]
鄰居: [[0. 1. 1.]]
距離: [[ 80. 296. 424.]]
因為三個最近鄰居有兩個是紅色三角,所以他的標志為一
用kNN算法實現手寫數字識別
用下列圖片用來訓練。
先把下面分割為每個數字大小都是20*20的圖像,用于訓練模型。
然后將手寫的數字進行反二值化閾值處理轉換成黑白圖像,用像素值作為特征向量進行測試
import cv2 import numpy as np import matplotlib.pyplot as plt gray = cv2. imread('img/a.png',0) #讀入手寫數字的灰度圖像 digits = [np.hsplit(r,100) for r in np.vsplit(gray,50)] #分解數字: 50行、100 列 np_digits = np.array(digits ) #轉換為NumPy數組 #準備訓練數據,轉換為二維數組,每個圖像400個像素 train_data = np_digits.reshape(-1, 400). astype(np. float32) train_labels = np.repeat(np. arange(10),500)[:,np.newaxis] #定義標志 knn = cv2.ml.KNearest_create() #創(chuàng)建kNN分類器 knn.train(train_data, cv2.ml.ROW_SAMPLE,train_labels) #訓練模型 #用繪圖工具創(chuàng)建的手寫數字5圖像(大小為20x 20 )進行測試 test= cv2.imread('img/a5.png',0) #打開圖像 test_data=test.reshape(1,400).astype(np.float32) #轉換為測試數據 ret,result,neighbours,dist = knn. findNearest(test_data,k=3) #執(zhí)行測試 print(result.ravel()) #輸出測試結果 print(neighbours.ravel()) #將對手寫數字9拍攝所得圖像的大小轉換為20 x 20進行測試 img2=cv2. imread('img/d3.png',0) ret,img2=cv2. threshold(img2,150, 255, cv2. THRESH_BINARY_INV) #反二值化閾值處理 test_data=img2.reshape(1,400).astype(np. float32) #轉換為測試數據 ret,result,neighbours,dist = knn. findNearest(test_data,k=3) #執(zhí)行測試 print(result.ravel()) #輸出測試結果 print(neighbours .ravel())
用一張繪圖圖片和手寫圖片用來測試
輸出結果:
[5.]
[5. 5. 5.]
[3.]
[3. 5. 3.]
SVM算法
可使用一條直線將線性可分離的數據分為兩組,這條直線在SVM算法中稱為“決策邊界”; 非線性可分離的數據轉換為高維數據后可稱為線性可分離數據。這是SVM算法的理論基礎。
圖解SVM算法
下面的代碼在圖像中選擇了五個點,分為兩類,類別標志分別為0和1。將五個點和標志作為已知分類數據訓練SVM模型;然后用模型對圖像中的所有點進行分類,根據分類結果設置圖像顏色,從而直觀顯示圖像像素的分類結果。
import cv2 import numpy as np import matplotlib.pyplot as plt#準備訓練數據,假設圖像高240,寬320,在其中選擇5個點 traindata=np.matrix([[140,60],[80, 120],[16,10],[166,190],[248, 180]],dtype = np.float32) #5個點,前3個點為一類,標志為8;后2個點為一類,標志為1 labels = np.array([0,0,0,1,1]) svm = cv2.ml.SVM_create() #創(chuàng)建SVM分類器 svm. setGamma(0.50625) #設置相關參數 svm. setC(12.5) svm. setKernel(cv2.ml.SVM_LINEAR) svm.setType(cv2.ml.SVM_C_SVC) svm. setTermCriteria((cv2. TERM_CRITERIA_MAX_ITER, 100, 1e-6)) svm.train(traindata, cv2.ml. ROW_SAMPLE, labels) #訓練模型 img = np.zeros((240,320,3),dtype="uint8" ) #創(chuàng)建圖像 colors = {0:(102,255,204),1:(204,204,102)} #用SVM分類器對圖像像素進行分類,根據分類結果設置像素顏色 for i in range(240): for j in range(320): point = np.matrix([[j,i]], dtype=np.float32) #將像素坐標轉換為測試數據 label = svm.predict(point)[1].ravel() #執(zhí)行預測,返回結果 img[i,j] = colors[label[0]] #根據預測結果設置像素顏色 svm_vectors = svm. getUncompressedSupportVectors() #獲得SVM向量 for i in range(svm_vectors.shape[0]): #在圖像中繪制SVM向量(紅色圓) cv2.circle(img,(int(svm_vectors[i,0]),int(svm_vectors[i,1])),8,(0,0,255),2) #在圖像中繪制訓練數據點,類別標志0使用藍色,類別標志1使用綠色 cv2.circle(img, (140, 60),5,(255,0,0),-1) cv2.circle(img, (80,120),5,(255,0,0),-1) cv2.circle(img, (160,110),5,(255,0,0),-1) cv2.circle(img, (160,190),5,(0,255,0),-1) cv2.circle(img, (240,180),5,(0,255,0),-1) img = cv2. cvtColor(img, cv2.COLOR_BGR2RGB) #轉換為RGB格式 plt. imshow(img) plt. show() #顯示結果
如圖中三個藍點為一類,下面兩個訓練點為一類,兩顏色交界位置為決策邊界
使用SVM算法識別手寫數據
kMM算法使用了像素值作為特征向量。 svm算法可使用圖像的定向梯度直方圖作為特征向量來對圖像進行分類 梯度直方圖
用svm識別數字和knn的區(qū)別在于他會使用圖像的定向梯度直方圖作為特征向量來對圖像進行分類。
下面代碼步驟:
1.定義了HOG描述符的計算函數,用于將單個數字圖像計算HOG描述符,再轉換成一維數組(特征描述符就是通過提取圖像的有用信息,并且丟棄無關信息來簡化圖像的表示)
2.分解圖片,計算每張圖片對應的HOG描述符
3.創(chuàng)建svm分類器,用這些圖片進行訓練模型
4.用繪制的圖像測試
import cv2 import numpy as np def hog(img): #定義HOG描述符的計算函數 hog = cv2.HOGDescriptor((20,20),(8,8),(4,4),(8,8),9,1,-1,0,0.2,1,64,True) #定義HOGDescriptor對象 hog_descriptor=hog.compute(img) #計算HOG描述符 hog_descriptor=np.squeeze(hog_descriptor) #轉換為一維數組 return hog_descriptor #返回HOG描述符,144 位 img = cv2.imread('img/a.png',0) digits=[np.hsplit(row,100) for row in np.vsplit(img, 50)] #分解圖像,50行、100列 labels = np.repeat(np. arange(10),500)[:,np.newaxis] #定義對應的標記 hogdata = [list(map(hog,row)) for row in digits] #計算圖像的HOG描述符 trainData = np. float32(hogdata) . reshape(-1, 144) #轉換為測試數據 svm = cv2.ml.SVM_create( ) #創(chuàng)建SVM分類器 #設置相關參數 svm. setKernel(cv2.ml. SVM_LINEAR) svm. setType(cv2.ml.SVM_C_SVC) svm. setC(2.67) svm. setGamma(5.383) svm. train(trainData, cv2.ml. ROW_SAMPLE, labels) #訓練模型 #用繪圖工具創(chuàng)建的手寫數字5圖像(大小為20 x 20 )進行測試 test= cv2.imread('img/d5.jpg',0) #打開圖像 test_data=hog(test) test_data=test_data.reshape(1, 144) . astype(np. float32) #轉換為測試數據 result = svm. predict(test_data)[1] print( '識別結果: ',np. squeeze(result)) #用繪圖工具創(chuàng)建的手寫數字8圖像(大小為20 x20 )進行測試 test= cv2. imread('img/d7.jpg' ,0) test_data=hog(test) test_data=test_data.reshape(1,144).astype(np .float32) #轉換為測試數據 result = svm. predict(test_data)[1] print('識別結果:',np.squeeze(result))
k均值聚類算法
k均值聚類算法的基本原理是根據數據的密集程度尋找相對密集數據的質心,再根據質心完成數據分類
圖解k均值聚類算法
下面代碼在大小為240*320的圖像中選擇3組數據點,不同顏色顯示分類數據和質心
import cv2 import numpy as np from matplotlib import pyplot as plt #創(chuàng)建聚類數據,3個類別,每個類別包含20個點 data = np.vstack((np.random. randint(10,90, (20,2)),np. random. randint(80,170, (20, 2)),np.random.randint(160,250, (20, 2)))) data=data.astype(np.float32) #定義算法終止條件 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0) #使用k均值聚類算法執(zhí)行分類操作,k=3,返回結果中l(wèi)abel用于保存標志,center 用于保存質心 ret,label,center=cv2. kmeans(data,3,None, criteria,10,cv2.KMEANS_RANDOM_CENTERS) #根據運算結果返回的標志將數據分為3組,便于繪制圖像 data1 = data[label.ravel() == 0] data2 = data[label.ravel() == 1] data3 = data[label.ravel() == 2] plt. scatter(data1[:,0], data1[:,1], c='r') #繪制第1類數據點,紅色 #繪制第2類數據點,綠色 plt.scatter(data2[:,0],data2[:,1],c='g') #繪制第3類數據點,藍色 plt.scatter(data3[:,0], data3[:,1], c='b') plt.scatter(center[:,0],center[:,1],100,['#CC3399'],'s') #繪制質心,顏色為#CC3399 #顯示結果 plt. show()
使用k均值聚類算法量化圖像顏色
使用k均值聚類算法量化圖像顏色,即將質心作為圖像新的像素,從而減少圖像中的顏色值 K均值聚類步驟:
第一步:確定K值,聚類成K個類簇。
第二步:從數據中隨機選擇(或按照某種方式)K個數據點作為初始分類的中心。
第三步:分別計算數據中每個點到每個中心的距離,將每個點劃分到離中心最近的類中
第四步:當每個中心都劃分了一些點后,去每個類的均值,選出新的中心。
第五步:比較新的中心和之前的中心,如果新的中心和之前的中心之間的距離小于某閾值,或迭代次數超過某閾值,認為聚類已經收斂,終止。
第六步:否則繼續(xù)迭代執(zhí)行第三到五步,直到第五步滿足。
import cv2 import numpy as np img = cv2.imread('img/qwe.jpg') #打開圖像 #顯示原圖 img2 = img.reshape((-1,3)). astype(np. float32) #轉換為nx 3的浮點類型數組,n=圖像像素的總數一3 #定義算法終止條件 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) K=8 ret,label,center=cv2.kmeans(img2,K,None, criteria,10,cv2.KMEANS_RANDOM_CENTERS) center = np.uint8(center) #將質心轉換為整型 img3 = center[label.ravel()] #轉換為一維數組 img3 = img3.reshape((img.shape)) #恢復為原圖像數組形狀 cv2.imshow('K=8',img3) K=12 ret,label,center=cv2. kmeans(img2,K,None, criteria,10,cv2.KMEANS_RANDOM_CENTERS) center = np.uint8(center) #將質心轉換為整型 img3 = center[label.ravel()] #轉換為一維數組 img3 = img3.reshape((img.shape)) #恢復為原圖像數組形狀 cv2.imshow('K=12',img3) cv2.waitKey(0)
- 將原圖的二維(寬,高)三通道的圖片轉換成了一維(一列)三通道的數組
- 根據誤差和迭代次數定義算法終止的條件
- 將一維三通道的值根據K分成的類別替換為質心的值
- 將這個數組再轉換為原圖像的數組形狀
下圖分別是原圖、k=4、k=8、k=12的圖
深度學習
機器學習通常包含輸入、特征提取、分類和輸出四個步驟
深度學習通常分為輸入、特征提取與分類和輸出3個步驟,它將機器學習中的特征提取和分類和并在同一個步驟中完成
基于深度學習的圖像識別
圖像識別是將圖像內容作為一個對象來識別其類型。使用OpenCV中的深度學習預訓練模型進行圖像識別的基本步驟如下。
- 從配置文件和預訓練模型文件中加載模型。
- 將圖像文件處理為塊數據( blob )。
- 將圖像文件的塊數據設置為模型的輸入。
- 執(zhí)行預測。
- 處理預測結果。
基于AlexNet和Caffe模型進行圖像識別
1.從文本中獲取每個類別的名稱
2.載入Caffe模型
3.打開用于識別分類的圖像
4.創(chuàng)建圖像塊數據,將圖像塊數據作為神經網絡輸入
5.執(zhí)行預測,返回的是一個1*1000的數組,是按照順序對應1000種類別的可信度
6.輸出排名第一的預測結果
import cv2 import numpy as np from matplotlib import pyplot as plt from PIL import ImageFont,ImageDraw, Image #讀入文本文件中的類別名稱,共0種類到每行為一個類到,從第11個字符開始為名稱 #基本格式如下 # n01440764 tench, Tinca tinca # n01443537 goldfish, Carassius auratus file=open('classes.txt' ) names=[r.strip() for r in file.readlines()] file.close() classes = [r[10:] for r in names] #獲取每個類別的名稱 #從文件中載入Caffe模型 net = cv2.dnn.readNetFromCaffe("AlexNet_deploy.txt", "AlexNet_CaffeModel.dat") image = cv2. imread("img/qwe.jpg") #打開圖像,用于識別分類 #創(chuàng)建圖像塊數據,大小為(224,224),顏色通道的均值縮減比例因子為(104, 117, 123) blob = cv2.dnn. blobFromImage(image, 1, (224,224), (104, 117, 123)) net. setInput(blob) #將圖像塊數據作為神經網絡輸入 #執(zhí)行預測,返回結果是一個 1x 1000的數組,按順序對應1000種類別的可信度 result = net. forward() ptime, x = net. getPerfProfile() #獲得完成預測時間 print('完成預測時間: %.2f ms' % (ptime * 1000.0 / cv2.getTickFrequency(0))) sorted_ret = np. argsort(result[0]) #將預測結果按可信度由高到低排序 top5 = sorted. ret[::-1][:5] #獲得排名前5的預測結果 ctext = "類別: "+classes[top5[0]] ptext = "可信度: {:.2%}" . format(result[0][top5[0]]) #輸出排名前5的預測結果 for (index, idx) in enumerate(top5): print("t).類別: {},可信度: (:2%)" .format(index + 1, classes[idx], result[0][idx])) #在圖像中輸出排名第1的預測結果 fontpath = "STSONG. TTF" font = ImageFont . truetype( fontpath, 80) #載入中文字體,設置字號 img_pil = Image. fromarray(image) draw = ImageDraw.Draw(img_pil) draw.text((10, 10),ctext, font = font,fill=(0,0,255)) #繪制文字 draw.text((10,100),ptext, font = font, fill=(0,0,255)) img = np.array(img_pil) img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) plt.imshow(img) plt.axis('off') plt.show()
基于深度學習的對象檢測
對象檢測是指檢測出圖像中的所有對象。并識別對象的類型。使用OpenCV中的深度學習預訓練模型進行對象檢測的基本步驟如下。
- 從配置文件和預訓練模型文件中加載模型。
- 創(chuàng)建圖像文件的塊數據( blob )。
- 將圖像文件的塊數據設置為模型的輸入。
- 執(zhí)行預測。
- 處理預測結果。
基于YOLO和Darknet預訓練模型的對象檢測
1.從文本中獲取每個類別的名稱
2.載入預訓練的Darknet模型
3.打開用于對象檢測的圖像
4.創(chuàng)建圖像塊數據,將圖像塊數據作為神經網絡輸入
5.執(zhí)行預測,返回每層的預測結果
6.遍歷所有的輸出層,遍歷層的所有輸出預測結果,每個結果為一個邊框
7.篩選出概率大于50%的類別,獲取他們的坐標
8.用非最大值抑制獲得要繪制的box(為最大值一直是為了消除重復邊框)
9.繪制邊框
import cv2 import numpy as np from matplotlib import pyplot as plt import matplotlib from PIL import InageFont, Inagoraw, Image #加載字體,以便顯示漢字 fontpath = "STSONG.TTF” font = ImageFont.truetype(fontpath,20) #載入字體,設置字號 font2 = {'family': 'STSONG', "size": 22} matplotlib.rc('font', **font2) #設置plt字體 #從文件中加載已知的對象名稱,文件保存了80個類別的對象名稱,每行個 f=open(" object_names .txt",encoding=' utf-8') object. names = [r.strip() for r in f.readlines()] f.close() #從文件中加載預訓練的Darknet模型 mode = cv2. dnn. readNetFromDarknet("yolov3.cfg", "yolov3.weights") image = cv2. imread(" objects. jpg") #打開圖像文件 imgH, imgW = image . shape[ :2] ut_layers = mode. getLayerNames() #獲得輸出層 out_layers = [out_layers[i[0] - 1] for i in mode.getUnconnectedOutLayers()] blob = cv2.dnn. blobFromImage(image, 1/255.0, (416,416),swapRB=True, crop=False) #創(chuàng)建圖像塊數據 mode . setInput(blob) #將圖像塊數據設置為模型輸入 layer_results = mode . forward(out_layers) #執(zhí)行預測,返回每層的預測結果 ptime,_ = mode. getPerfProfile() tilte_text='完成預測時間: %.2f ms' % (ptime* 1000/cv2. getTickFrequency()) result_boxes = [] result_scores = [] result_name_id = [] for layer in layer_results: #遍歷所有輸出層 for box in layer: #遍歷層的所有輸出預測結果,每個結果為一個邊框 #預測結果結構: x, y, w, h, confidence, 80 個類別的概率 probs = box[5:] class_id = np.argmax(probs) #找到概率最大的類別名稱 prob = probs[class_id] #找到最大的概率 if prob > 0.5: #篩選出概率大于50%的類別 #計算每個box在原圖像中的絕對坐標 box = box[0:4]* np.array[imgW, imgH, imgW, imgH]) (centerx, centery, width, heignt) = box.astype("int") x = int(centerX - (width / 2)) y = int(centerY - (height / 2)) result_boxes.append([x, y, int(width),int(height)]) result_scores . append(float(prob)) result_name_id. append(class_id) #應用非最大值抑制消除重復邊框,獲得要繪制的box draw_boxes = cv2.dnn. NMSBoxes(result_boxes, result_scores, 0.6, 0.3) if len(draw_boxes) > 0: for i in draw_boxes.ravel(): #獲得邊框坐標 (x, y) = (result_boxes[i][0], result_boxes[i][1]) (w, h) = (result_boxes[i][2], result_boxes[i][3]) #繪制邊框 cv2.rectangle(image,(x,y), (x+w,y+h),(0,255,0),1) #輸出類別名稱和可信度 text=object_names[result_name_id[i]] +"\n{: .1%}". format(result_scores[i]) img_pil = Image.fromarray(image) draw = ImageDraw.Draw(img_pil) draw.text((x+5,y), text, font = font,fill=(0,0,255)) #繪制文字 image = np.array(img_pil) img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) plt. title(tilte_text) plt. imshow(img) plt.axis('off') plt. show()
到此這篇關于opencv深入淺出了解機器學習和深度學習的文章就介紹到這了,更多相關opencv 機器學習 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!