JavaScript中比较两个文本的相似度:OCR文字识别的巧妙应用

前言

OCR识别返回的中文,有时候个别文字是错误的。在字数基本相同的情况下,可以通过文本的相似度比较,来判断文本是否是我们需要查找的。

方法一

温馨提示:此处内容需要后才能查看!

下面是一个使用编辑距离(Levenshtein距离)来比较两个文本相似度的示例:

/**
 * 计算两个字符串的编辑距离(Levenshtein距离)
 * @param {string} str1 - 第一个字符串
 * @param {string} str2 - 第二个字符串
 * @returns {number} - 两个字符串之间的编辑距离
 * @author 飞云
 * @wechat imfeiyun
 * @link  http://www.feiyunjs.com
 */
function levenshteinDistance(str1, str2) {
    const len1 = str1.length;
    const len2 = str2.length;
    const dp = Array.from({ length: len1 + 1 }, () => Array(len2 + 1).fill(0));

    for (let i = 0; i <= len1; i++) {
        dp[i][0] = i;
    }
    for (let j = 0; j <= len2; j++) {
        dp[0][j] = j;
    }

    for (let i = 1; i <= len1; i++) {
        for (let j = 1; j <= len2; j++) {
            if (str1[i - 1] === str2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = Math.min(
                    dp[i - 1][j] + 1, // 删除
                    dp[i][j - 1] + 1, // 插入
                    dp[i - 1][j - 1] + 1 // 替换
                );
            }
        }
    }

    return dp[len1][len2];
}

/**
 * 计算两个字符串的相似度
 * @param {string} str1 - 第一个字符串
 * @param {string} str2 - 第二个字符串
 * @returns {number} - 两个字符串的相似度,范围在0到1之间
 * @author 飞云
 * @wechat imfeiyun
 * @link  http://www.feiyunjs.com
 */
function calculateSimilarity(str1, str2) {
    const distance = levenshteinDistance(str1, str2);
    const maxLength = Math.max(str1.length, str2.length);
    return 1 - distance / maxLength;
}

// 示例使用
const str1 = "无线局英语网";
const str2 = "无线局域语网";

const similarity = calculateSimilarity(str1, str2);

console.log(similarity); // 输出: 0.8

解释

  1. 编辑距离levenshteinDistance函数计算两个字符串之间的编辑距离,即通过插入、删除或替换字符将一个字符串转换为另一个字符串所需的最小操作次数。
  2. 相似度计算calculateSimilarity函数计算两个字符串的相似度,相似度定义为1减去编辑距离与两个字符串长度的最大值的比值。

方法二

可以使用Jaro-Winkler距离算法来计算两个字符串的相似度。
Jaro-Winkler是一种字符串相似度的度量方法,它在Jaro距离的基础上增加了对前缀的权重,使得相似度的计算更加准确。

以下是使用Jaro-Winkler算法计算两个文本相似度的函数,包含详细的注释:

/**
 * 计算两个字符串的Jaro-Winkler相似度
 * @param {string} s1 - 第一个字符串
 * @param {string} s2 - 第二个字符串
 * @param {number} [prefixWeight=0.1] - 前缀权重,默认为0.1
 * @returns {number} - 相似度值,范围在0到1之间
 * @author 飞云
 * @wechat imfeiyun
 * @link  http://www.feiyunjs.com
 */
function jaroWinklerDistance(s1, s2, prefixWeight = 0.1) {
  // 确保输入的字符串是字符串类型
  s1 = String(s1);
  s2 = String(s2);

  // 计算两个字符串的长度
  const len1 = s1.length;
  const len2 = s2.length;

  // 如果两个字符串长度为0,则返回0
  if (len1 === 0 && len2 === 0) return 1;

  // 定义匹配窗口大小
  const matchDistance = Math.floor(Math.max(len1, len2) / 2) - 1;

  // 初始化匹配数组
  const match1 = new Array(len1);
  const match2 = new Array(len2);
  let matches = 0;

  // 标记匹配项
  for (let i = 0; i < len1; i++) {
    let start = Math.max(0, i - matchDistance);
    let end = Math.min(i + matchDistance + 1, len2);

    for (let j = start; j < end; j++) {
      if (s1[i] === s2[j] && !match2[j]) {
        match1[i] = true;
        match2[j] = true;
        matches++;
        break;
      }
    }
  }

  // 如果没有匹配项,则返回0
  if (matches === 0) return 0;

  // 初始化转置匹配数组
  let transpositions = 0;
  let p1 = 0;
  let p2 = 0;

  while (p1 < len1 && p2 < len2) {
    while (p1 < len1 && !match1[p1]) p1++;
    while (p2 < len2 && !match2[p2]) p2++;

    if (p1 < len1 && p2 < len2 && s1[p1] !== s2[p2]) {
      transpositions++;
      p1++;
      p2++;
    } else {
      p1++;
      p2++;
    }
  }

  // 计算Jaro距离
  const jaro = ((matches / len1) + (matches / len2) + ((matches - transpositions / 2) / matches)) / 3;

  // 计算前缀长度
  let prefixLength = 0;
  while (p1 < len1 && p2 < len2 && s1[p1] === s2[p2]) {
    prefixLength++;
    p1++;
    p2++;
  }

  // 计算Jaro-Winkler距离
  const jaroWinkler = jaro + (prefixLength * prefixWeight * (1 - jaro));

  return jaroWinkler;
}

// 示例使用
console.log(jaroWinklerDistance('María', 'maria')); // 输出接近1,表示两个字符串非常相似
console.log(jaroWinklerDistance('Kimi', 'KimiAI')); // 输出小于1,表示两个字符串有一定相似度

解释

这个函数首先确保输入的两个字符串是字符串类型,然后计算它们的长度。接着,它使用匹配窗口来确定可能的匹配项,并标记它们。之后,它计算Jaro距离,这是基于匹配项的数量和转置匹配项的数量。最后,它计算Jaro-Winkler距离,这包括了前缀的权重。

请注意,这个函数对于中文、英文以及混合文本都是有效的,因为它是基于字符级别的比较。

更多算法

文本相似度计算是一个在自然语言处理和数据清洗等领域中非常重要的任务。有多种常用的文本相似度计算方法:

  1. Jaccard相似度:这是一种衡量集合相似度的方法,通过计算两个集合交集大小与并集大小的比例来确定相似度 。

  2. Levenshtein距离:也称为编辑距离,它计算将一个字符串转换为另一个字符串所需的最少单字符编辑(插入、删除或替换)次数 。

  3. Damerau-Levenshtein距离:这是Levenshtein距离的扩展,它考虑了字符的插入、删除、替换和邻位交换操作 。

  4. 汉明距离:衡量两个等长字符串对应位置上不同字符的个数,即需要替换的字符个数 。

  5. 余弦相似度:灵感来自于余弦定理,通过计算两个向量的夹角来衡量相似度,常用于文本向量表示后的相似度计算 。

  6. TF-IDF:通过统计方法评估单词在文档集中的重要性,可以将文本表示为向量,进而计算余弦相似度 。

  7. Word2Vec:将单词表示为向量,捕捉单词之间的语义关系,使用预训练的词向量模型计算文本之间的相似度 。

  8. Doc2Vec:类似于Word2Vec,但是将整个文档表示为向量,捕捉文档之间的语义关系 。

  9. BERT:基于Transformer的预训练模型,用于捕捉上下文相关的单词表示,可以将文本表示为向量,然后计算余弦相似度 。

这些方法各有优势和适用场景,可以根据具体需求选择合适的相似度计算方法。

例如,Jaccard相似度和余弦相似度适用于对文本的交集和频次敏感的场景,而Levenshtein距离和Damerau-Levenshtein距离适用于需要计算具体编辑步骤的场景。Word2Vec和BERT等基于深度学习的模型能够捕捉更深层次的语义信息。

1. 官方交流QQ群,添加多个不批。建议使用安卓手机或电脑申请。
飞云脚本圈: 586333520飞云脚本圈
Auto.js学习交流③群:286635606
Auto.js学习交流②群:712194666(满员)
IOS免越狱自动化测试群:691997586
2. 盗版,破解有损他人权益和违法作为,请各位会员支持正版。
3. 本站部分资源来源于用户上传和网络搜集,如有侵权请提供版权证明并联系站长删除。
4.如未特别申明,本站的技术性文章均为原创,未经授权,禁止转载/搬运等侵权行为。
5.全站所有付费服务均为虚拟商品,购买后自动发货。售出后概不接受任何理由的退、换。注册即为接受此条款。
6.如果站内内容侵犯了您的权益,请联系站长删除。
飞云脚本 » JavaScript中比较两个文本的相似度:OCR文字识别的巧妙应用

企业级大数据智能营销管理系统

了解详情