圖像識別之KNN算法的理解與應用

2021-02-15 萌萌噠程序猴

KNN是最經典的機器學習算法之一。該算法既可以用於數據分類,也可以用於數據回歸預測,其核心思路是在訓練樣本中尋找距離最接近待分類樣本的K個樣本。然後,如果目的是分類,則統計這K個樣本中的各個類別數量,數量最多的類別即認為是待分類樣本的類別;如果目的是回歸預測,則計算這K個樣本的平均值作為預測值。

圖像識別,本質上也是數據分類,也即把每一張圖像歸類,因此KNN算法可以應用於圖像識別。本文首先講解KNN算法的原理,接著講解Opencv中的KNN算法模塊,然後再使用Opencv中的KNN算法模塊對手寫數字圖像進行識別。

KNN算法主要包含以下幾個要素:

1. 訓練樣本。訓練樣本就是預先準備好的數據集,該數據集必須包含所有可能的數據類別,而且數據集中的每個數據都有一個唯一的標籤,用來標識該數據所屬的類別。比如,待分類的圖像有可能屬於的類別包括鳥、狗、馬、飛機、班車這5種類別,給5種類別依次編號0、1、2、3、4,那麼訓練樣本必須包含這5種類別的圖像,且訓練樣本中每一張圖像都有一個範圍在0~4之間的類別標籤。

2. 待分類樣本。也就是待分類的數據,比如一張圖像,把該圖像輸入KNN算法之中,KNN算法對其進行分類,然後輸出類別標籤。

3. 樣本距離。通常每一個樣本都是一維向量的形式(二維、三維、多維數據都可以轉換為一維向量)。衡量一維向量之間的距離,通常有歐式距離,餘弦距離、漢明距離等,其中歐式距離又是最常用的距離度量方法。

假設樣本A和樣本B:

A=[a0 a1 a2 ... an]

B=[b0 b1 b2 ... bn]

那麼樣本A與樣本B的歐式距離為:

4. K值。K值決定尋找訓練樣本中最接近待分類樣本的樣本個數,比如K值取5,那麼對於每一個待分類樣本,都從訓練樣本中尋找5個與其距離最接近的樣本,然後統計這5個樣本中各個類別的數量,數量最多的類別則認為是待分類樣本的類別。K值沒有固定的取值,通常在一開始取5~10,然後多嘗試幾次,根據識別的正確率來調整K值。

舉一個簡單的例子來說明KNN的分類思路,如下圖所示,樣本0為待分類樣本,其可能的分類為矩形、圓形、菱形,取K=6,然後在所有訓練樣本中尋找與樣本0最接近的6個樣本:樣本1、樣本2、樣本3、樣本4、樣本5、樣本6。然後對這6個樣本進行分類統計(每個訓練樣本是有標籤的,所以知道其類別):3個矩形、2個菱形、1個圓形。矩形的數量最多,因此判定樣本0為矩形。

講完原理,下面我們開始講Opencv3.4.1中KNN算法模塊的應用。Opencv3.4.1中已經實現了該算法,並封裝成類,我們只需要調用類的相關接口,並且把輸入參數傳入接口即可得到分類結果。調用接口的步驟如下:

1. 創建KNN類並設置參數。

  const int K = 3;       cv::Ptr<cv::ml::KNearest> knn = cv::ml::KNearest::create();  knn->setDefaultK(K);     knn->setIsClassifier(true);    knn->setAlgorithmType(cv::ml::KNearest::BRUTE_FORCE);   

2. 輸入訓練數據及其標籤:

Mat traindata;   //訓練數據的矩陣Mat trainlabel;  //訓練數據的標籤
traindata.push_back(srcimage);  //srcimage為Mat類型的1行n列的一維矩陣,將該矩陣保存到訓練矩陣中trainlabel.push_back(i);      //i為srcimage的標籤,同時將i保存到標籤矩陣中
traindata.convertTo(traindata, CV_32F); //重要:訓練矩陣必須是浮點型數據

3. 將訓練數據與標籤輸入KNN模塊中進行訓練:

knn->train(traindata, cv::ml::ROW_SAMPLE, trainlabel);

4. 訓練之後,開始對待分類圖像進行分類:

Mat result;//testdata為待分類圖像,被轉換為1行n列的浮點型數據//response為最終得到的分類標籤int  response = knn->findNearest(testdata, K, result); 

下面,我們將Opencv的KNN模塊應用於手寫數字識別。在Opencv3.4.1的samples/data目錄有一張1000*2000的手寫數字圖像,該圖像包含了5000個20*20的小圖像塊,每個小圖像塊就是一個手寫數字,如下圖所示:

首先,我們寫個程序把上圖分割成5000個20*20的圖像塊。把相同的數字保存到同名文件夾中,比如數字0的小圖像塊保存到文件夾0中、數字1的小圖像塊保存到文件夾1中、數字2的小圖像塊保存到文件夾2中。

分割圖像塊的代碼如下:

void read_digital_img(void){  char ad[128] = { 0 };  int  filename = 0, filenum = 0;  Mat img = imread("digits.png");  Mat gray;  cvtColor(img, gray, CV_BGR2GRAY);  int b = 20;  int m = gray.rows / b;     int n = gray.cols / b;   
for (int i = 0; i < m; i++) { int offsetRow = i*b;     if (i % 5 == 0 && i != 0)    {      filename++;    filenum = 0; }
for (int j = 0; j < n; j++) { int offsetCol = j*b; sprintf_s(ad, "%d/%d.jpg", filename, filenum++); Mat tmp; gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);      imwrite(ad, tmp);    } }}

運行上述代碼之後,從0~9的文件夾都保存有對應數字的小圖像塊啦~不同數字的小圖像塊如下圖所示。這時我們有0~9這10個文件夾,每個文件夾都有對應數字的500張小圖像塊,比如文件夾0中有500張不同手寫風格的0數字圖像。

下面我們使用每個文件夾下前400張圖像作為訓練圖像,對KNN模型進行訓練,然後使用該KNN模型對每個文件夾下後100張圖像進行分類,並統計分類結果的準確率。

上代碼:

void KNN_test(void){  char ad[128] = { 0 };  int testnum = 0, truenum = 0;  const int K = 3;     cv::Ptr<cv::ml::KNearest> knn = cv::ml::KNearest::create();    knn->setDefaultK(K);  knn->setIsClassifier(true);     knn->setAlgorithmType(cv::ml::KNearest::BRUTE_FORCE);   
Mat traindata, trainlabel;
for (int i = 0; i < 10; i++) { for (int j = 0; j < 400; j++) { sprintf_s(ad, "%d/%d.jpg", i, j); Mat srcimage = imread(ad);       srcimage = srcimage.reshape(1, 1); traindata.push_back(srcimage); trainlabel.push_back(i); } }
traindata.convertTo(traindata, CV_32F); knn->train(traindata, cv::ml::ROW_SAMPLE, trainlabel);
  for (int i = 0; i < 10; i++)    { for (int j = 400; j < 500; j++) { testnum++; sprintf_s(ad, "%d/%d.jpg", i, j); Mat testdata = imread(ad); testdata = testdata.reshape(1, 1); testdata.convertTo(testdata, CV_32F);
Mat result; int response = knn->findNearest(testdata, K, result); if (response == i) { truenum++;      } } } cout << "測試總數" << testnum << endl; cout << "正確分類數" << truenum << endl; cout << "準確率:" << (float)truenum / testnum * 100 << "%" << endl;}

運行上述代碼,得到結果如下,可以看到,KNN算法對手寫數字圖像的識別(分類)的準確率還是比較高的。

由於手寫數字圖像包含的特徵比較簡單,因此KNN的識別準確率很高。實際上,對於一些複雜的圖像,KNN的識別準確率是很低的。在下一篇文章中,我們將嘗試使用KNN算法來識別更複雜的圖像,並想辦法提高識別的準確率,敬請期待!

尊敬的讀者,您的關注是我繼續更新的強大動力,如果您對我寫的東西感興趣,請長按並識別以下二維碼,關注我的公眾號,多謝多謝!




相關焦點

  • 圖像識別之KNN算法的理解與應用(2)
    在上一篇文章中,我們介紹了KNN算法的原理,並詳細闡述了使用Opencv的KNN算法模塊對手寫數字圖像進行識別,發現識別的準確率還是比較高的,達到
  • 圖像識別之原理、過程、應用前景,精華篇
    隨著計算機技術的發展,人類對圖像識別技術的認識越來越深刻。圖像識別技術的過程分為信息的獲取、預處理、特徵抽取和選擇、分類器設計和分類決策。簡單分析了圖像識別技術的引入、其技術原理以及模式識別等,之後介紹了神經網絡的圖像識別技術和非線性降維的圖像識別技術及圖像識別技術的應用。從中可以總結出圖像處理技術的應用廣泛,人類的生活將無法離開圖像識別技術,研究圖像識別技術具有重大意義。
  • 【研究】圖像識別及應用
    2 圖像識別的應用場景有哪些?什麼是圖像識別圖像識別,是指利用計算機對圖像進行處理、分析和理解,以識別各種不同模式的目標和對像的技術。根據觀測到的圖像,對其中的物體分辨其類別,做出有意義的判斷。利用現代信息處理與計算技術來模擬和完成人類的認識、理解過程。
  • Sk-learn之KNN算法綜合實戰
    前面幾篇文章我們通過幾個小案例熟悉了在Python中使用sklearn模塊來用做機器學習項目的一般步驟,並通過機器學習中最簡單的KNN算法進行演示。但是想要更好的訓練模型,這就需要我們花一些精力來理解數據了,也就是常說的要深入理解業務。這樣才能明白數據指標間的相關性,做到更好的取捨。這些需要在工作慢慢的積累總結和思考。另外,現在我們使用的這些sklearn中自帶的數據集都是處理過的,但是在真實世界的項目中數據往往是混亂且不完整的,需要我們花很大部分精力來對數據進行清洗。
  • 圖像識別技術的行業應用
    ,今天,我們就一起來了解下什麼是圖像識別?圖像識別,是指利用計算機對圖像進行處理、分析和理解,以識別各種不同模式的目標和對象的技術,自動識別圖像中的對象,人物,位置和動作等。圖像識別用於執行任務,是應用深度學習算法的一種實踐應用。如何實現圖像識別?圖像識別對於人類和動物來說是很自然的,但是對於計算機來說卻是一項極其困難的任務。
  • KNN算法中的K有多重要
    K-最近鄰(KNN)是一種有監督的機器學習算法,可用於解決分類和回歸問題。它基於一個非常簡單的想法,數據點的值由它周圍的數據點決定。考慮的數據點數量由k值確定。因此,k值是算法的核心。KNN分類器根據多數表決原則確定數據點的類別。如果k設置為5,則檢查5個最近點的類別。也可以根據多數類進行回歸預測,同樣,KNN回歸取5個最近點的平均值。
  • 聚類(三):KNN算法(R語言)
    k最臨近(KNN)算法是最簡單的分類算法之一,屬於有監督的機器學習算法。
  • KNN學習之圖像分類與KNN原理
    簡介KNN算法,即K近鄰算法是一種監督學習算法,本質上是要在給定的訓練樣本中找到與某一個測試樣本A最近的K個實例,然後統計k個實例中所屬類別計數最多的那個類,就是A的類別。 從上面一句話中可以看出,KNN的原理非常簡單粗暴,而且是一種「在線」的學習方式,即每一次分類都需要遍歷所有的訓練樣本,此外KNN算法還有幾個要素:K,距離,分類決策規則。
  • 計算機視覺:從入門到精通,極限剖析圖像識別學習算法
    本次課程將圍繞著計算機視覺中最常見的RCNN圖像識別算法進行極限剖析,從數學理論, 模型框架到實踐實操,讓你在短時間內從理論到實踐,掌握深度學習的基本知識和學習方法。· 目的:掌握神經網絡的基本原理,知其然亦知其所以然(從數學實踐到代碼的熟練和精通); · 手段:科學的方法。
  • 速度數百倍之差!有人斷言KNN面臨淘汰,更快更強的ANN將取而代之
    重磅乾貨,第一時間送達作者:Marie Stephen Leo本文轉載自:機器之心在模式識別領域中,K - 近鄰算法(K-Nearest Neighbor, KNN)是一種用於分類和回歸的非參數統計方法。
  • 圖像識別技術落地 探索應用場景
    在兩周前的《最強大腦》中,百度首席科學家吳恩達帶著小度機器人和人類選手比拼,在人臉識別項目以 3:2取勝。但是,在聯想和常識理解的能力上,圖像識別遠未能和人類比肩,相關公司正在積極切入垂直行業應用中。       圖像識別落地       圖像識別背後的技術就是新的機器學習方式,即深度學習。
  • R語言--鄰近算法KNN
    ❝KNN(k鄰近算法)是機器學習算法中常見的用於分類或回歸的算法。它簡單,訓練數據快,對數據分布沒有要求,使它成為機器學習中使用頻率較高的算法,並且,在深度學習大行其道的今天,傳統可解釋的簡單模型在工業大數據領域的應用更為廣泛。本文介紹KNN算法的基本原理和用R代碼實現。
  • 人工智慧之K近鄰算法(KNN)
    前言:人工智慧機器學習有關算法內容,請參見公眾號「科技優化生活」之前相關文章。人工智慧之機器學習主要有三大類:1)分類;2)回歸;3)聚類。今天我們重點探討一下K近鄰(KNN)算法。在實際應用中,K 值一般選擇一個較小的數值,通常採用交叉驗證的方法來選擇最優的 K 值。隨著訓練實例數目趨向於無窮和 K=1 時,誤差率不會超過貝葉斯誤差率的2倍,如果K也趨向於無窮,則誤差率趨向於貝葉斯誤差率。
  • 圖像識別 | 基於Amazon Rekognition的圖像識別應用
    導語:隨著人工智慧在世界範圍內的大爆發,機器學習和深度學習算法不斷精進,在圖像識別和機器翻譯等方面的應用方面,各大巨頭也是使出了渾身解數。
  • 機器學習之KNN分類算法介紹: Stata和R同步實現(附數據和代碼)
    好比如我們討論一個學生是學霸還是學渣(只有兩種分類),我們觀察ta身邊最親密的k個朋友,裡面如果學霸比例最多,那麼我們就將這個同學歸類為學霸,反之學渣。這和常見的俗語「物以類聚,人以群分」表達的原理有點類似——距離最近的k個樣本的性質,決定了目標樣本的性質。1.2 回歸算法原理在KNN回歸中,輸出的是目標對象的K個最近鄰樣本的結果變量取值的平均值。
  • 人工智慧與圖像識別在醫療診斷中的應用
    最為常見的人工智慧,例如iPhone的Siri,特斯拉的自動駕駛,智能語音客服等,皆通過機器學習這類統計算法來實現。與傳統統計方法相比,機器學習的優勢在於它可以處理數量巨大、特徵繁多的數據;並基於學習過去的經驗與知識,在遇到新的問題時,通過歸納出的解決方法來處理問題。本文將探討人工智慧在關乎人類生老病死的醫療健康行業中的應用,重點講述醫療影像識別中的優劣勢及市場應用。
  • 數據驅動優化:如何利用 KNN 算法驅動產品優化?
    在網際網路行業中常常有利用數據分析或者數據挖掘的結論來應用到產品中,驅動產品的優化,提升產品的各項KPI 指標, 在數據挖掘和數據分析的背後會涉及到一些數據挖掘或者機器學習的算法。本文主要是knn算法原理的介紹,以及在它在網際網路行業中的具體應用,後續會介紹這個算法的具體實現(R 語言和python 語言)。
  • 速度數百倍之差,有人斷言KNN面臨淘汰,更快更強的ANN將取而代之
    選自towardsdatascience作者:Marie Stephen Leo機器之心編譯編輯:小舟、杜偉數據科學經典算法 KNN 已被嫌慢,ANN 比它快 380 倍。
  • 機器學習(二)-------KNN算法的sklearn KNN實踐
    一.Skelarn KNN參數概述要使用sklearnKNN算法進行分類,我們需要先了解sklearnKNN算法的一些基本參數,那麼這節就先介紹這些內容吧。前面說到過,通過調整 K 值,算法會有不同的效果。- weights(權重):最普遍的 KNN 算法無論距離如何,權重都一樣,但有時候我們想搞點特殊化,比如距離更近的點讓它更加重要。這時候就需要 weight 這個參數了,這個參數有三個可選參數的值,決定了如何分配權重。參數選項如下: • 'uniform':不管遠近權重都一樣,就是最普通的 KNN 算法的形式。
  • KNN算法(三)-sklearn實現
    上篇講到KNN算法的實例。在python中sklearn庫可直接實現KNN算法。本篇介紹運用sklearn庫實現KNN算法。