牙叔教程 簡單易懂javascript
上面這張圖片網上說是opencv自帶的, 我下載的4.5.2的opencv的安卓版本, 就沒找到java
百科簡介git
鄰近算法,或者說K最近鄰(KNN,K-NearestNeighbor)分類算法是數據挖掘分類技術中最簡單的方法之一。所謂K最近鄰,就是K個最近的鄰居的意思,說的是每一個樣本均可以用它最接近的K個鄰近值來表明。近鄰算法就是將數據集合中每個記錄進行分類的方法 。算法
網友大奸貓對knn的算法描述markdown
S1 算距離網絡
給定未知樣本點A,計算它與訓練集中的每一個樣本點的距離 S2 找鄰居 將S1計算好的距離升序排列,取前k個最近的樣本點做爲A的鄰居 S3 肯定分類 這k個鄰居中,包含鄰居數最多的類別做爲A的類別學習
目標是黃色多邊形, 距離黃色多邊形最近的3個鄰居, 有兩個是紅色, 一個是藍色,測試
按照近朱者赤近墨者黑, 少數服從多數來推斷, 就認爲黃色多邊形是紅色ui
也能夠說是, 你身邊那種人多, 你就會成爲那種人 spa
曼哈頓距離(城市街區距離)
歐式距離
馬氏距離(閔可夫斯基距離)
餘弦距離
切比雪夫距離
海明距離
8.8.16-0
本版本自帶3.4.3的opencv
訓練就是把特徵和標籤一一對應起來, 再對數據作一些處理,
這裏主要說一下特徵提取,
特徵: 取圖片每一個像素點的數值, 一張圖片是20X20, 就是400個像素, 而且圖片是一個通道
關鍵代碼:
let tempData = Imgcodecs.imread(filePath, 0); // 一個通道
tempData = tempData.reshape(0, 1); // 矩陣變爲一行
tempData.convertTo(tempData, CvType.CV_32F); // 數據變爲浮點數
tempData.copyTo(tmp); // 保存特徵
trainlabel.put(0, 0, trainClasses); // 打標籤
knn.train(trainData, Ml.ROW_SAMPLE, trainlabel); // 訓練
複製代碼
預測就是拿一小部分數據測試,
訓練的時候留一小部分數據, 不參加訓練, 而是用於預測
預測, 和訓練同樣,
提取圖片特徵, 拿去和訓練好的數據計算距離,
而後返回匹配度最高的值
關鍵代碼
let tempData = Imgcodecs.imread(filePath, 0); // 一個通道
tempData = tempData.reshape(0, 1); // 矩陣變爲一行
tempData.convertTo(tempData, CvType.CV_32F); // 數據變爲浮點數
let response = knn.findNearest(tempData, k, nearests); // 計算最佳匹配
複製代碼
log("測試總數: " + testNum);
log("正確分類數: --> " + trueNum);
log("準確率:" + (trueNum / testNum) * 100 + "%");
複製代碼
mat是opencv經常使用的數據類型, 理解Mat的格式後, 對理解opencv代碼頗有幫助
autojs的Mat沒有at方法, 那麼修改數據就用get和put
runtime.images.initOpenCvIfNeeded();
log(new org.opencv.core.Mat().getClass());
delete org.opencv.core.Mat;
log(new org.opencv.core.Mat().getClass());
importClass(org.opencv.core.Mat);
importClass(org.opencv.core.CvType);
//32位浮點數 1個channel
let trainlabel = Mat.ones(100, 1, CvType.CV_32FC1);
for (var i = 0; i < 100; i++) {
log("修改前" + i + ": ", trainlabel.get(i, 0));
let item = util.java.array("float", 1);
item[0] = i;
log(trainlabel.put(i, 0, item));
log("修改後" + i + ": ", trainlabel.get(i, 0));
}
複製代碼
let trainlabel = Mat.ones(100, 1, CvType.CV_32FC1);
let infoList = [
"\n",
"row: " + trainlabel.rows(),
"col: " + trainlabel.cols(),
"height: " + trainlabel.height(),
"width: " + trainlabel.width(),
];
log(infoList.join("\n"));
// row: 100
// col: 1
// height: 100
// width: 1
複製代碼
把Mat想象成一堵牆就能夠了,
橫着的是row, 豎着的是col,
有多少row, 就有多height,
有多少col, 就有多width
Mat參數通常是row前, col後
先看數據在第幾行, 再看數據在第幾列
也符合人的思惟
咱們讀書也是從左往右, 從上往下
古人的話估計是先看第幾列, 再看第幾行,
由於古人的書是豎着寫的
runtime.images.initOpenCvIfNeeded();
importClass(org.opencv.core.Mat);
importClass(org.opencv.core.CvType);
// 3行2列
let trainlabel = Mat.ones(3, 2, CvType.CV_32FC1);
let width = trainlabel.width();
let height = trainlabel.height();
let arr = [];
// height和行數 數值同樣
// 能夠認爲 hegith ⇔ 行數
for (var i = 0; i < height; i++) {
let childArr = [];
for (var j = 0; j < width; j++) {
let item = trainlabel.get(i, j);
childArr.push(item);
}
arr.push(childArr);
}
log(JSON.stringify(arr, null, " "));
// [
// [[1.0], [1.0]],
// [[1.0], [1.0]],
// [[1.0], [1.0]]
// ]
複製代碼
部份內容來自網絡 本教程僅用於學習, 禁止用於其餘用途