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);
相關推薦
opencv 學習之 基於K近鄰的數字識別
本文參考兩篇部落格,都對KNN思路做了詳細說明 (1) http://blog.csdn.net/wangyaninglm/article/details/17091901 (2) http://blog.csdn.net/xiaowei_cqu/article/detai
深度學習之mnist手寫數字識別入門
使用tensorflow框架和python,學習實現簡單的神經網路,並進行調參,程式碼如下: #! /usr/bin/python # -*- coding:utf-8 -*- """ a simple mnist classifier """ from __fut
【機器學習筆記】基於k-近鄰演算法的數字識別
更多詳細內容參考《機器學習實戰》 k-近鄰演算法簡介 簡單的說,k-近鄰演算法採用測量不同特徵值之間的距離方法進行分類。它的工作原理是:存在一個樣本資料集合,也稱作訓練樣本集,並且樣本集中每個資料都存在標籤,即我們知道樣本集中每個資料與所屬分類的對應關係。輸入沒
OpenCV手寫數字字元識別(基於k近鄰演算法)
公眾號: 老王和他的IT界朋友們 歡迎投稿: [email protected] QQ交流群: 593683975 QQ群提供技術交流,CSDN資源,百度文庫等資源共享 加群問題:拋硬幣正面上的期望? 我們想用一段音樂,幾張圖片, 些
基於k近鄰(KNN)的手寫數字識別
作者:faaronzheng 轉載請註明出處! 最近再看Machine Learning in Action. k近鄰演算法這一章節提供了不少例子,本著Talk is cheap的原則,我們用手寫數字識別來實際測試一下。 簡單的介紹一下k近鄰演算法(KNN):給定測試樣本
OpenCV學習之路——車牌識別之車牌定位
pla sim srand oval 模糊 fault .html swa ide 去年七月份因為學校項目需要開始接觸圖像處理,但那時候只是到網上找車牌識別代碼,然後加入到自己的項目中,不清楚細節原理。 現在自己重新一步步實現車牌識別。 高斯模糊: 1 Mat Ga
K 近鄰演算法識別手寫數字(Numpy寫法)
在 Kaggle 上面的 Notebook 給可愛的學弟學妹們用於參考... 程式碼這個東西一定要自己多寫,我一邊聽著林宥嘉的《想自由》,一邊寫出了大致的實現。K 近鄰演算法大概做的是一件什麼事情呢?你去商店買衣服的時候,突然忘記了自己要買的衣服多大尺碼比較合適(S/M/L/XL 這種)。這個時候你就要找幾個
opencv——基於SVM的數字識別(3)
前兩篇文章寫了基於兩種特徵提取的SVM數字識別 https://blog.csdn.net/weixin_41721222/article/details/84953788 https://blog.csdn.net/weixin_41721222/article/details/84978
【opencv學習之四十三】K均值聚類演算法
K均值聚類演算法,在opencv中通過kmeans()函式實現;k均值通俗講:就是從一堆樣本中,隨便挑出幾個,比如3個吧,然後用樣本中的和這挑出來的比較,比較後排序,誰和挑出的那個接近就把他劃到那個類裡,比如樣A和挑1、挑2、挑3中,挑2最接近,則把樣A劃到挑2裡,當然還沒完
iOS開發之opencv學習筆記四:使用feature2d識別圖片
使用過vuforia或者亮風臺的朋友應該知道,這兩個平臺對圖片的跟蹤的準備工作是很簡單的,只需要幾張樣本圖片就可以做了。 但是按照上篇的介紹,如果用CascadeClassifier進行物體跟蹤就需要非常非常多的樣本,那麼,要對圖片進行識別跟蹤就沒有像上面說的兩個平臺那樣
機器學習Tensorflow基於MNIST資料集識別自己的手寫數字(讀取和測試自己的模型)
更新: 以下為原博: 廢話不多說,先上效果圖 整體來看,效果是非常不錯的,模型的訓練,參照官方程式碼mnist_deep.py,準確率是高達99.2% 那麼,我是怎麼實現的呢? 一.讀懂卷積神經網路程式碼(至少得把程式跑通) 首先參照Tensorfl
opencv——基於SVM的數字識別(2)
上篇文章我們用的特徵是訓練樣本的所有畫素點值,雖然方便但不準確。 這篇文章主要介紹用SVM+HOG特徵對數字進行識別。 詳細請看上篇文章,它們主要區別在於訓練樣本HOG特徵的提取,其他基本一樣,所以我直接附上程式碼。 下面程式碼是opencv3和C++ 可以根據自己需要修改訓練樣本類
opencv——基於KNN的數字識別
KNN即K個最近鄰,網上有很多關於KNN的文章。我大概總結下核心:假設有A圖片,讓A與訓練樣本依次計算相似度(可用歐式距離),挑選出K個與A圖片相似度最大的圖片,這K個圖片中,哪種型別最多那麼定義A圖片也屬於該型別。 首先,需要有數字的訓練樣本 https://download.csdn.n
opencv——基於SVM的數字識別(1)
關於SVM的原理有很多優秀的視訊和資料,這裡我主要說下利用SVM對數字識別的具體應用 首先,需要有數字的訓練樣本 https://download.csdn.net/download/weixin_41721222/10784418 把0-9資料夾放入模版匹配樣本之中,自己可
opencv學習之聚類與k均值聚類
在無監督學習中,資料不帶任何標籤。能找出資料內在分類規則,並分成獨立的點集(蔟),演算法稱為聚類演算法。 K均值聚類(K-means) K-均值是最普及的聚類演算法,演算法接受一個未標記的資料集,然
機器學習 使用python+OpenCV實現knn演算法手寫數字識別
基本上照搬了http://lib.csdn.net/article/opencv/30167的程式碼,只是改了一點bug和增加了一點功能輸入就是直接在一個512*512大小的白色畫布上畫黑線,然後轉化為01矩陣,用knn演算法找訓練資料中最相近的k個,現在應該是可以對所有字元
k-近鄰演算法--使用k-近鄰演算法識別手寫數字
listdir函式: os.listdir() 方法用於返回指定的資料夾包含的檔案或資料夾的名字的列表。返回指定路徑下的檔案和資料夾列表。 python文件: listdir(path=None) Return a list containing the nam
【SVM理論到實踐4】基於OpenCv中的SVM的手寫體數字識別
//由於本人每天時間非常緊張,所以細節寫的不詳細,部落格僅供各位參考,裡面的程式碼都是執行過的,直接可以執行 本章的學習目標: 1)手寫體數字識別資料庫MNIST 2)基於SVM訓練的具體步驟 1)手寫體數字識別資料庫MNIST MNIST(Mixe
機器學習實戰精讀--------K-近鄰算法
機器學習 knn算法 k-近鄰算法對機器學習實戰的課本和代碼進行精讀,幫助自己進步。#coding:utf-8 from numpy import * import operator #運算符模塊 from os import listdir #os.listdir() 方法用於返回指定的文件夾包含的
機器學習實戰(一)k-近鄰算法
復雜 ssi bsp 體重 工具 等級 lap 問題 種類 轉載請註明源出處:http://www.cnblogs.com/lighten/p/7593656.html 1.原理 本章介紹機器學習實戰的第一個算法——k近鄰算法(k Nearest Neighbor