UzumakiItachi
首页
  • JavaSript
  • Vue

    • Vue2
    • Vue3
  • React

    • React_18
  • WebPack
  • 浏览器相关
  • 工程化相关
  • 工作中遇到的问题以及解决方案
  • Git
  • 面试
  • 学习
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 个人产出
  • 实用工具
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

UzumakiItachi

起风了,唯有努力生存。
首页
  • JavaSript
  • Vue

    • Vue2
    • Vue3
  • React

    • React_18
  • WebPack
  • 浏览器相关
  • 工程化相关
  • 工作中遇到的问题以及解决方案
  • Git
  • 面试
  • 学习
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 个人产出
  • 实用工具
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • WebPack

  • 浏览器相关

  • 工程化相关

  • 工作中遇到的问题以及解决方案

    • 解决浏览器返回页面不刷新的问题
    • 前端如何下载文件流
    • uniapp APP端实现更新最新安装包
    • GitHub Actions Process completed with exit code 128 的解决方案
    • 保留文字输入的空格和换行
    • 缩放适配大屏页
    • 一次性加载n多张图片的性能优化方案
    • NOT-Cool 低代码页面架构思路
    • h5下载vcard快捷保存联系人信息
    • 结合elementui实现的动态主题
    • 解决monorepo场景下子包作为依赖项在开发和生产暴露文件的问题
    • 给npm配置github令牌
    • 移动端电子印章解决方案
      • 前言
      • 手机如何识别印章
      • 如果进行触控点之间的对比
        • 证明余弦相似
        • 计算点之间的距离
      • 结语
    • 小程序canvas绘制海报中遇到的一些坑
    • 超详细的虚拟列表实现过程
    • 小程序实现一个事件中心
    • 请求超时后如何优雅的重新请求
    • 超详细的大文件上传实现方案
    • 仿抖音短视频组件实现方案
    • swiper渲染大量数据的优化方案
    • 前端检测更新,自动刷新网页
  • Git

  • Vite

  • 一些小工具

  • 算法

  • 服务器

  • HTTP

  • 技术
  • 工作中遇到的问题以及解决方案
hanhanbuku
2023-10-16
目录

移动端电子印章解决方案

# 前言

电子印章这个概念的出现极大的方便了线下活动的进行,传统印章需要用印章粘上印泥在纸上面盖章。特别的费事,而电子印章则是通过印章在手机上盖一下,然后手机去识别完成这么一个步骤。下面来介绍一下在移动端该如何去实现这一需求

# 手机如何识别印章

其实这一步很简单,准备一个带有电容触控点的印章。将他盖在手机上,即可通过捕获touch事件来拿到这些触控点。剩下要做的就是根据这些触控点来识别是否是符合要求的图案

# 如果进行触控点之间的对比

这里提供两种方案

# 证明余弦相似

关于余弦相似度 GPT是这样解释的

余弦相似性(Cosine Similarity)是一种用于测量两个非零向量在多维空间中的夹角的相似性度量方法。这个方法常用于信息检索、自然语言处理和机器学习等领域,用于衡量文本文档、向量空间模型或特征之间的相似性。

余弦相似性的计算基于向量的内积和模的概念。对于两个非零向量A和B,它的计算公式如下:

Cosine Similarity(A, B) = (A·B) / (||A|| * ||B||)

其中:

A·B表示向量A和向量B的点积(内积)。 ||A||表示向量A的模(长度),也称为L2范数,计算方法是每个元素的平方和的平方根。 余弦相似性的结果是一个介于-1到1之间的值。具体来说:

如果余弦相似性等于1,表示两个向量的方向完全一致,相似度最高。 如果余弦相似性等于0,表示两个向量之间不存在相似性,夹角为90度。 如果余弦相似性小于0,表示两个向量之间有一定的反向相似性,夹角大于90度。

具体实现代码如下

// 计算两个向量的点积
function dotProduct(vector1, vector2) {
    let dot = 0;
    for (let i = 0; i < vector1.length; i++) {
        dot += vector1[i] * vector2[i];
    }
    return dot;
}

// 计算向量的模长(范数)
function vectorLength(vector) {
    let sum = 0;
    for (let i = 0; i < vector.length; i++) {
        sum += vector[i] * vector[i];
    }
    return Math.sqrt(sum);
}

// 计算余弦相似度
function cosineSimilarity(vector1, vector2) {
    const dot = dotProduct(vector1, vector2);
    const length1 = vectorLength(vector1);
    const length2 = vectorLength(vector2);
    return dot / (length1 * length2);
}

// 两个二维数组
const array1 = [[1, 2], [3, 4]];
const array2 = [[1, 2], [5, 6]];

// 将二维数组转换为一维向量
const vector1 = array1.flat();
const vector2 = array2.flat();

// 计算相似度
const similarity = cosineSimilarity(vector1, vector2);

console.log(`余弦相似度:${similarity}`);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

此方法经过实测,在点位较密集的情况下准确率比较高,点位分散的情况下准确率不是很可靠。

# 计算点之间的距离

这是后面自己瞎捣鼓推测出来的方法,大概就是记录下每个点位之间的距离,通过距离判断两个二维数组是否相似。我认为在这些点里面做一个排列组合,计算出每个组合的距离基本就可以确定一个图形。所以有了如下代码

// 计算二维数组内所有坐标点之间的距离
handleCalculatedDistance(pointsArray) {
    // 计算两点之间的距离
    function calculateDistance(point1, point2) {
        const deltaX = point1[0] - point2[0];
        const deltaY = point1[1] - point2[1];
        return Math.hypot(deltaX, deltaY);
    }
    const reslut = []
    // 遍历数组并计算每对点之间的距离
    for (let i = 0; i < pointsArray.length; i++) {
        for (let j = i + 1; j < pointsArray.length; j++) {
            const point1 = pointsArray[i];
            const point2 = pointsArray[j];
            const distance = calculateDistance(point1, point2);
            reslut.push(distance)
        }
    }
    return reslut
}

// 计算两组坐标的相似度
handleSimilarity(vector1, vector2) {
    if (vector1.length !== vector2.length) return
    // 升序排列数组
    const sortVector1 = vector1.sort((a, b) => {
        return a[0] - b[0];
    });
    const sortVector2 = vector2.sort((a, b) => {
        return a[0] - b[0];
    });
    const reslut1 = this.handleCalculatedDistance(sortVector1).sort()
    const reslut2 = this.handleCalculatedDistance(sortVector2).sort()
    let exceedNum = 0 //超出接受范围外的边数量
    for (let i = 0; i < reslut1.length; i++) {
        console.log(Math.abs(reslut1[i] - reslut2[i]) > 10, `边距${i+1}`)
        if (Math.abs(reslut1[i] - reslut2[i]) > 10) {
            exceedNum++
        }
    }
    return exceedNum === 0
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

提前准备一个二维数组作为对照组,然后拿到touch的触控点数组后计算出两个数组自己的排列组合,将这两个组合进行升序排列,然后进行比对。也就是用最长的和最长的比以此类推。最终如果每一条边距和对照组的误差都保持在10以内则算通过

# 结语

以上两种方案的话我各人感觉都不是太靠谱,但第二种经过本人测试基本可以解决问题并且不受方向影响,但是没法比对相似图形,如果相似的两个图形一大一小就没法比对了。

编辑 (opens new window)
上次更新: 2023/10/24, 09:31:42
给npm配置github令牌
小程序canvas绘制海报中遇到的一些坑

← 给npm配置github令牌 小程序canvas绘制海报中遇到的一些坑→

最近更新
01
前端检测更新,自动刷新网页
06-09
02
swiper渲染大量数据的优化方案
06-06
03
仿抖音短视频组件实现方案
02-28
更多文章>
Theme by Vdoing | Copyright © 2023-2025 UzumakiItachi | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式