二维码识别

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>OpenCV.js + QRCode 识别 + JS 耗时统计</title>
  <style>
    canvas, input {
      margin: 10px;
      border: 1px solid #ccc;
    }
    .slider-container {
      display: flex;
      align-items: center;
      gap: 10px;
    }
    #qrResults, #timeStats {
      white-space: pre-wrap;
      background-color: #f4f4f4;
      padding: 10px;
      margin-top: 10px;
      font-family: monospace;
    }
  </style>
</head>
<body>

<h2>上传图片并实时调节二值化阈值 + 识别二维码 + JS 耗时统计</h2>

<input type="file" id="imageInput" accept="image/*"><br><br>

<div class="slider-container">
  <label for="thresholdSlider">阈值 (0~255): </label>
  <input type="range" id="thresholdSlider" min="0" max="255" value="128">
  <span id="thresholdValue">128</span>
</div>

<canvas id="canvasOriginal"></canvas>
<canvas id="canvasGray"></canvas>
<canvas id="canvasBinary"></canvas>

<h3>识别到的二维码:</h3>
<div id="qrResults">暂无识别结果</div>

<h3>JS 耗时统计:</h3>
<div id="timeStats">等待图像处理...</div>

<!-- OpenCV.js -->
<script async src="https://docs.opencv.org/4.5.0/opencv.js"></script>
<!-- jsQR.js 用于识别二维码 -->
<script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.js"></script>

<script>
  let currentGray = null;
  let threshold = 128;

  // 等待 OpenCV 加载完成
  window.addEventListener("load", function () {
    if (typeof cv !== 'undefined' && typeof jsQR === 'function') {
      console.log("OpenCV 和 jsQR 已加载");

      const slider = document.getElementById('thresholdSlider');
      const thresholdLabel = document.getElementById('thresholdValue');

      // 监听滑动事件
      slider.addEventListener('input', function () {
        threshold = parseInt(slider.value);
        thresholdLabel.textContent = threshold;
        if (currentGray) {
          updateBinaryImage(currentGray, threshold);
        }
      });

      document.getElementById('imageInput').addEventListener('change', handleImageUpload);
    } else {
      alert("OpenCV 或 jsQR 加载失败,请检查网络!");
    }
  });

  function handleImageUpload(e) {
    let file = e.target.files[0];
    if (!file) return;

    let img = new Image();
    img.onload = function () {
      processImage(img);
    };
    img.src = URL.createObjectURL(file);
  }

  function processImage(img) {
    const timeStats = document.getElementById("timeStats");
    timeStats.innerText = "正在处理...";

    const tStart = performance.now();

    let src = cv.imread(img); // 原图
    const tRead = performance.now();

    let gray = new cv.Mat();
    cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY);
    const tGray = performance.now();

    // 保存灰度图用于后续处理
    if (currentGray) {
      currentGray.delete();
    }
    currentGray = gray.clone();
    const tClone = performance.now();

    // 初始显示原图和灰度图
    cv.imshow("canvasOriginal", src);
    const tShowOrig = performance.now();

    cv.imshow("canvasGray", gray);
    const tShowGray = performance.now();

    // 初始显示二值化图像
    updateBinaryImage(gray, threshold);
    const tEnd = performance.now();

    // 计算耗时
    const stats = `
【JS 耗时统计】
读取图像: ${(tRead - tStart).toFixed(2)} ms
灰度转换: ${(tGray - tRead).toFixed(2)} ms
克隆灰度图: ${(tClone - tGray).toFixed(2)} ms
显示原图: ${(tShowOrig - tClone).toFixed(2)} ms
显示灰度图: ${(tShowGray - tShowOrig).toFixed(2)} ms
初始化二值化: ${(tEnd - tShowGray).toFixed(2)} ms
总计: ${(tEnd - tStart).toFixed(2)} ms
    `.trim();

    timeStats.innerText = stats;

    // 释放资源
    src.delete();
  }

  function updateBinaryImage(gray, thresholdValue) {
    let binary = new cv.Mat();
    try {
      const tBinaryStart = performance.now();

      cv.threshold(gray, binary, thresholdValue, 255, cv.THRESH_BINARY);
      cv.imshow("canvasBinary", binary);

      const tBinaryEnd = performance.now();

      // 更新耗时统计
      const statsDiv = document.getElementById("timeStats");
      const existingText = statsDiv.innerText;
      const binaryTime = (tBinaryEnd - tBinaryStart).toFixed(2);
      statsDiv.innerText = existingText + `\n二值化耗时: ${binaryTime} ms`;

      // 调用二维码识别
      detectQRFromMat(binary);

    } catch (err) {
      console.error(err);
    } finally {
      binary.delete();
    }
  }

  function detectQRFromMat(mat) {
    const canvasBinary = document.getElementById("canvasBinary");
    const ctx = canvasBinary.getContext("2d");

    const imageData = ctx.getImageData(0, 0, canvasBinary.width, canvasBinary.height);

    const tQRStart = performance.now();
    const code = jsQR(imageData.data, imageData.width, imageData.height);
    const tQREnd = performance.now();

    const resultDiv = document.getElementById("qrResults");
    const timeStatsDiv = document.getElementById("timeStats");

    if (code) {
      resultDiv.innerHTML = `识别到二维码:\n${code.data}`;
      timeStatsDiv.innerText += `\n二维码识别耗时: ${(tQREnd - tQRStart).toFixed(2)} ms`;
    } else {
      resultDiv.innerText = "未识别到二维码。";
      timeStatsDiv.innerText += `\n二维码识别耗时: ${(tQREnd - tQRStart).toFixed(2)} ms`;
    }
  }
</script>

</body>
</html>

  

posted @ 2025-06-12 23:36  China Soft  阅读(27)  评论(0)    收藏  举报