一 ,ml5.js是什么

ml5.js 它是基于Tensorflow.js的一个非常简便易用的接口,目的是让更广泛的受众更容易使用机器学习。(结合官网食用)

其他知识点索引点这里

KNNClassifier最邻近结点算法

KNN核心思想,它通过将每一个测试集样本点与训练集中每一个样本之间测算欧氏距离,然后取欧氏距离最近的K个点(k是可以人为划定的近邻取舍个数,K的确定会影响算法结果),并统计这K个训练集样本点所属类别频数,将其中频数最高的所属类别化为该测试样本点的预测类别。
“在模式识别中,k-最近邻算法 (k-NN) 是一种用于分类回归的非参数方法。在这两种情况下,输入都由特征空间中的 k 个最接近的训练示例组成。

下面是一个官方demo 预测A和B的身份
<html>

<head>
  <meta charset="UTF-8">
  <title>Image classification using MobileNet and p5.js</title>
  
  <script src="../p5.min.js"></script>
  <script src="../ml5.js"></script>
</head>

<body>
  <h2>人物识别</h2>
  <div id="videoContainer"></div>
  <p id="status">Loading Model...</p>
  <br /><p>
    <button id="addClassA">添加人物A</button>
    <button id="resetA">重置人物A</button>
    </p><p><span id="exampleA">0</span> A </p>
    <p>A的可信度<span id="confidenceA">0</span></p>

    <br /><button id="addClassB">添加人物B</button>
    <button id="resetB">重置人物B</button>
    <p><span id="exampleB">0</span> B examples</p>
    <p>B的可信度<span id="confidenceB">0</span></p>
  
  <br />
  <p>
    <button id="buttonPredict">开始预测</button><br />
    <button id="clearAll">清空所有预测结果</button><br />
  </p>
  <p>
    结果<span id="result">...</span>
    可信度<span id="confidence">...</span>
  </p>
  <script src="sketch.js"></script>
</body>

</html>
// sketch.js

let video;
// 创建KNN分类器
const knnClassifier = ml5.KNNClassifier();
let poseNet;// 位置捕捉
let poses = [];// 存位置

function setup() { // p 自动调用
  // 创建画布
  const canvas = createCanvas(640, 480);
  // 设置画布的父元素
  canvas.parent("videoContainer");
  // 打开摄像头
  video = createCapture(VIDEO);
  // 显示图像
  video.size(width, height);

  // 给按钮设置点击事件
  createButtons();

  // 身体捕捉 后面学习
  poseNet = ml5.poseNet(video, modelReady);
  //这会设置一个填充全局变量“poses”的事件
  // 每次检测到新姿势时使用一个数组
  poseNet.on("pose", function(results) {
    poses = results;
  });
  // 隐藏视频元素,只显示画布
  video.hide();
}
// p5.js会不断调用改函数
function draw() {
  // 创建图片
  image(video, 0, 0, width, height);

  // 我们可以调用这两个函数来绘制所有关键点和骨架
  drawKeypoints();
  drawSkeleton();
}

function modelReady() {
  select("#status").html("model Loaded");
}

// 将视频中的当前帧添加到分类器
function addExample(label) {
  // 将姿势结果转换为二维数组 [[score0, x0, y0],...,[score16, x16, y16]]
  const poseArray = poses[0].pose.keypoints.map(p => [p.score, p.position.x, p.position.y]);

  // 给分类器添加训练集
  knnClassifier.addExample(poseArray, label);
  updateCounts();
}

// 预测结果
function classify() {
  // 得到所有训练的标签(前面addExample)
  const numLabels = knnClassifier.getNumLabels();
  if (numLabels <= 0) {
    console.error("你还没添加训练集");
    return;
  }
  // 将(当前实时的)姿势结果转换为二维数组 [[score0, x0, y0],...,[score16, x16, y16]]
  const poseArray = poses[0].pose.keypoints.map(p => [p.score, p.position.x, p.position.y]);

  // 预测结果
  knnClassifier.classify(poseArray, gotResults);// addExample(‘添加到数据集的示例通常是来自另一个模型的激活’,"标识符")
}

// 给按钮设置点击事件
function createButtons() {
  // 当A按钮被按下时,添加当前帧
  // 从带有“A”标签的视频到分类器
  buttonA = select("#addClassA");
  buttonA.mousePressed(function() {
    addExample("A");
  });

  // 当B按钮被按下时,添加当前帧
  // 从带有“B”标签的视频到分类器
  buttonB = select("#addClassB");
  buttonB.mousePressed(function() {
    addExample("B");
  });

  // Reset buttons
  resetBtnA = select("#resetA");
  resetBtnA.mousePressed(function() {
    clearLabel("A");
  });

  resetBtnB = select("#resetB");
  resetBtnB.mousePressed(function() {
    clearLabel("B");
  });

  // Predict button
  buttonPredict = select("#buttonPredict");
  buttonPredict.mousePressed(classify);

  // Clear all classes button
  buttonClearAll = select("#clearAll");
  buttonClearAll.mousePressed(clearAllLabels);
}

// 预测结果回调函数
function gotResults(err, result) {
  // Display any error
  if (err) {
    console.error(err);
  }

  if (result.confidencesByLabel) {
    const confidences = result.confidencesByLabel;
    // 训练结果返回的可信度
    if (result.label) {
      select("#result").html(result.label);
      select("#confidence").html(`${confidences[result.label] * 100} %`);
    }

    select("#confidenceA").html(`${confidences.A ? confidences.A * 100 : 0} %`);
    select("#confidenceB").html(`${confidences.B ? confidences.B * 100 : 0} %`);
  }

  classify();
}

// 训练次数
function updateCounts() {
  const counts = knnClassifier.getCountByLabel();

  select("#exampleA").html(counts.A || 0);
  select("#exampleB").html(counts.B || 0);
}

// 清空单个训练集
function clearLabel(classLabel) {
  knnClassifier.clearLabel(classLabel);
  updateCounts();
}

// 清空所有训练集
function clearAllLabels() {
  knnClassifier.clearAllLabels();
  updateCounts();
}

// 在检测到的关键点上绘制椭圆的函数
function drawKeypoints() {
  // 循环所有pose
  for (let i = 0; i < poses.length; i += 1) {
    // 对于检测到的每个姿势,循环遍历所有关键点
    const pose = poses[i].pose;
    for (let j = 0; j < pose.keypoints.length; j += 1) {
      // 关键点是描述身体部位的对象(如右臂或左肩)
      const keypoint = pose.keypoints[j];
      // 只画一个椭圆是姿势概率大于0.2
      if (keypoint.score > 0.2) {
        fill(255, 0, 0);
        noStroke();
        ellipse(keypoint.position.x, keypoint.position.y, 10, 10);
      }
    }
  }
}

// 一个绘制骨架的函数
function drawSkeleton() {
  for (let i = 0; i < poses.length; i += 1) {
    const skeleton = poses[i].skeleton;
    // 对于每个骨架,循环遍历所有身体连接(把点连线)
    for (let j = 0; j < skeleton.length; j += 1) {
      const partA = skeleton[j][0];
      const partB = skeleton[j][1];
      stroke(255, 0, 0);
      line(partA.position.x, partA.position.y, partB.position.x, partB.position.y);
    }
  }
}

效果如下,识别效果不错,首先添加人物A(me)然后添加B(other people)
让然后训练,预测结果集

在这里插入图片描述

第一篇就先写到这里吧 下一篇 kmeansk均值聚类算法
需要源码找我就行了haha

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐