opencv 學習之 基於K近鄰的數字識別
本文參考兩篇部落格,都對KNN思路做了詳細說明
(1) http://blog.csdn.net/wangyaninglm/article/details/17091901
(2) http://blog.csdn.net/xiaowei_cqu/article/details/23782561#
(3) http://download.csdn.net/download/hust_bochu_xuchao/9581796
個人對於K近鄰編碼實現的一點理解。主要基於第一篇,第三篇是將第一篇基於OpenCV2實現,可參考。
int trainsamples; 每類樣本數
int clesses; 樣本種類數
如數字識別,0-9計10個數字,則 clesses 為10,如果每個樣本庫中有100個樣本,如100個數字 0 樣本,則 trainsamples 為100.
Mat traindata; 儲存樣本資料
mat trainclass; 樣本標識
traindata = Mat(trainsamples*traincless, templet_w*templet_h);
trainclass = Mat(trainsamples*traincless, 1);
將所有樣本資料儲存在 traindata 中,每個樣本轉換為 1*(w*h) 型矩陣,且二值化處理成只有 0 和 1 兩種畫素值模式
trainclass 儲存每類樣本標識,在 traindata 賦值過程中 賦值。如例 trainclass 為 1000*1 矩陣,那麼其前100行為0,最後100行為9
訓練直接呼叫 train() 函式即可
train(traindata, trainclass, Mat(), false, K);
Mat testimg; 待測資料
float result = CvKNearest::find_nearest(testimg, K)
上述為規模樣本採用K近鄰訓練識別的理解。
網上有一篇基於K近鄰的手寫字元識別,樣本是方形,實際中數字多為矩形。
第二篇部落格也同理
for (int i = 0; i < image.rows; ++i)
{
for (int j = 0; j < image.cols; ++j)
{
const Mat sampleMat = (Mat_<float>(1,2) << i,j);
Mat response;
float result = knn.find_nearest(sampleMat,1);
if (result !=0)
{
image.at<Vec3b>(j, i) = green;
}
else
image.at<Vec3b>(j, i) = blue;
}
}
建立 512*512 大小的矩陣,生成10個樣本,實際為10對座標。
座標在0-256之間的,標籤為0,在256-512之間的,標籤為1.
將座標分類,非 0 類綠色,0 類藍色。
程式碼補充:
knnTest.h
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/ml/ml.hpp>
#include <iostream>
using namespace cv;
using namespace std;
class knnRec
{
public:
knnRec();
float digRec(Mat img); //數字識別
void samTest(); //樣本訓練
private:
char folder[255]; //模板路徑
int sampl_num; //每類樣本數
int class_num; //樣本種類數
Mat trainData; //樣本資料儲存矩陣
Mat trainClass; //樣本類別儲存矩陣
static const int K = 6; //最大鄰居個數
KNearest * knn;
void getData(); //獲取樣本資料
void knnTrain(); //訓練
};
knnTest.cpp
#include "knnTest.h"
knnRec::knnRec()//建構函式
{
sprintf(folder, "..\\pics\\Template\\");
sampl_num = 10; //訓練樣本,總共10個
class_num = 10; //暫時識別十個數字
int samp_w = 14; //模板的寬和高
int samp_h = 27;
trainData.create(sampl_num*class_num, samp_w*samp_h, CV_32FC1); //訓練資料的矩陣
trainClass.create(sampl_num*class_num, 1, CV_32FC1);
getData();
knnTrain();
}
void knnRec::getData()
{
char filepath[255];
for (int i=0; i<class_num; i++)
{
for (int j=0; j<sampl_num; j++)
{
sprintf(filepath, "%s%d\\%d%d.bmp", folder, i, i, j);
Mat sampl = imread(filepath, 0);
if (sampl.empty())
{
printf("Error: Cant load image %s\n", filepath);
return;
}
//將 MxN 矩陣 轉為 1x(MxN)
Mat templ = sampl.clone();
sampl.release();
sampl.create(1, templ.cols*templ.rows, CV_32FC1);
//sampl 當前為1行,未初始化,templ 儲存 sampl 源資料
float* data_sampl = sampl.ptr<float>(0);
//確保模板均為二值圖,否則進行二值化
for (int j = 0; j<templ.rows; j++)
{
uchar * data_templ = templ.ptr<uchar>(j);
for (int i = 0; i<templ.cols; i++)
{
if (data_templ[i] == 255)
{
data_sampl[j*templ.rows + i] = 1;
}
else
{
data_sampl[j*templ.rows + i] = 0;
}
}
}
//記錄模板資料
float * data1 = trainData.ptr<float>(i*sampl_num+j); //定位第 i 個類中第 j 個樣本
float * data2 = sampl.ptr<float>(0);
for (int k = 0; k < sampl.cols; k++)
{
data1[k] = data2[k];
}
//記錄模板標誌
trainClass.at<float>(i*sampl_num+j, 0) = i; //定位第 i 個類中第 j 個樣本,標為 i
}
}
}
void knnRec::knnTrain()
{
knn = new KNearest(trainData, trainClass, Mat(), false, K);
}
//數字識別,img 為數字區域
float knnRec::digRec(Mat src)
{
Mat knnImg;
knnImg.create(1, K, CV_32FC1);
//處理輸入的影像
Mat tmp = src.clone();
src.release();
src.create(1, tmp.cols*tmp.rows, CV_32FC1);
float* data_src = src.ptr<float>(0);
for (int j = 0; j<tmp.rows; j++)
{
uchar* data_tmp = tmp.ptr<uchar>(j);
for (int i = 0; i<tmp.cols; i++)
{
if (data_tmp[i] == 255)
{
data_src[j*tmp.rows + i] = 1;
}
else
{
data_src[j*tmp.rows + i] = 0;
}
}
}
float result = knn->find_nearest(src, K, Mat(), knnImg, Mat());
int checkNum = 0;
for (int i = 0; i<K; i++)
{
if (knnImg.at<float>(0, i) == result)
{
checkNum++;
}
}
float pre = 100 * ((float)checkNum / (float)K);
return result;
}
說明:
呼叫之前,數字區域需完成處理,即完成裁剪、二值化等。
knnRec rec;
double result = rec.digRec(img);
相關文章
- 深度學習例項之基於mnist的手寫數字識別深度學習
- 一看就懂的K近鄰演算法(KNN),K-D樹,並實現手寫數字識別!演算法KNN
- 第三篇:基於K-近鄰分類演算法的手寫識別系統演算法
- K近鄰模型模型
- 機器學習——KNN(K近鄰)機器學習KNN
- Opencv學習筆記(3)---紙牌數字識別練習實踐專案OpenCV筆記
- K - 近鄰演算法演算法
- K近鄰演算法演算法
- 統計學習筆記(3)——k近鄰法與kd樹筆記
- [OpenCV實戰]1 基於深度學習識別人臉性別和年齡OpenCV深度學習
- opencv學習之基礎OpenCV
- 機器學習演算法之K近鄰演算法機器學習演算法
- 基於OPENCV的手勢識別技術OpenCV
- 機器學習——K近鄰演算法機器學習演算法
- k-近鄰演算法演算法
- 基於深度學習的人臉識別系統系列(Caffe+OpenCV+Dlib)——【六】設計人臉識別的識別類深度學習OpenCV
- K-鄰近均值演算法演算法
- K近鄰法(KNN)原理小結KNN
- 機器學習-K近鄰演算法-KNN機器學習演算法KNN
- 【實戰】基於OpenCV的水錶字元識別(OCR)OpenCV字元
- opencv python 基於KNN的手寫體識別OpenCVPythonKNN
- opencv python 基於SVM的手寫體識別OpenCVPython
- 基於OpenCV的車牌識別(Sobel、顏色定位)OpenCV
- 【Get】用深度學習識別手寫數字深度學習
- Spark學習筆記——手寫數字識別Spark筆記
- K近鄰演算法:機器學習萌新必學演算法演算法機器學習
- 機器學習-11-k近鄰演算法機器學習演算法
- Python:K-近鄰演算法Python演算法
- 2.1 k鄰近演算法之二演算法
- 2.1 k鄰近演算法之一演算法
- 用定租問題學透機器學習的K近鄰演算法機器學習演算法
- OpenCV + sklearnSVM 實現手寫數字分割和識別OpenCV
- k近鄰演算法的實現:kd樹演算法
- 基於 OpenCv 和 Python 的手指識別及追蹤OpenCVPython
- 機器學習_K近鄰Python程式碼詳解機器學習Python
- 第二篇:基於K-近鄰分類演算法的約會物件智慧匹配系統演算法物件
- 機器學習演算法(三):K近鄰(k-nearest neighbors)初探機器學習演算法REST
- 分類演算法-k 鄰近演算法演算法