如何使用 javascript 检测图像内图标的宽度?

How to detect the width of an icon inside an image using javascript?

我想检测图标的宽度(right-pointing手) 在下图中。

我想可能的解决方案可能涉及 color removal illustrated in this approach,在这种情况下可用于删除浅蓝色背景色。但是我不确定去色后的下一步。

我想通了!

这是我的做法:

  1. 使用 <img> 标签(通过普通 ole-html 或 js)将图像添加到文档中
  2. 创建一个 2D canvas 元素并使其大小与 img 相同
  3. 使用 context.drawImage
  4. 将图像绘制到 canvas
  5. 使用context.getImageData获取canvas
  6. 中像素的颜色
  7. 将这个原始数字数组转换为十六进制字符串颜色
  8. 按图像的行将颜色分组
  9. 抓取图像的第一种颜色作为 colorToFilter
  10. 创建 minXminYmaxXmaxY 变量以跟踪不是 colorToFilter[=53 的像素=]
  11. 遍历 pixelMatrix 中的每个像素,检查当前 rowcolumn 是否小于或大于非 colorToFilter[ 的颜色=53=]
  12. maxX - minXmaxY - minY 的差值,这就是您的尺寸!

仅供参考:由于跨源问题,我正在为图像使用数据 uri src

如果您需要更多解释,请告诉我。此解决方案可能不是最有效的,但它确实有效!

/**
 * converts a number from 0-255 to a hex number padded with a zero if necessary
 * @param {number} number 
 */
function toHex(number) {
  const numberAsString = Number(number).toString(16);
  return numberAsString.length === 1 ? '0' + numberAsString : numberAsString;
}

/**
 * Grabs the pixel colors from an image and stores it in a matrix
 * @param {HTMLImageElement} img 
 */
function convertImageToPixelData(img) {
  // credit for getting the color of pixel comes from here:
  // 
  const canvas = document.createElement('canvas');
  const imgWidth = img.clientWidth;
  const imgHeight = img.clientHeight;
  canvas.width = imgWidth;
  canvas.height = imgHeight;
  const context = canvas.getContext('2d');
  context.drawImage(img, 0, 0, imgWidth, imgHeight);

  const rawPixelData = context.getImageData(0, 0, imgWidth, imgHeight).data;

  // convert to hex string
  const pixelColors = rawPixelData.reduce((groups, pixelColor, index) => {
    if (index % 4 === 3) { // skip the alpha channel
      return groups;
    }
    if (groups[groups.length - 1].length === 6) {
      groups.push('');
    }
    groups[groups.length - 1] += toHex(pixelColor);
    return groups;
  }, ['']);

  // convert to matrix
  /**
   * @type {string[][]}
   */
  const pixelMatrix = pixelColors.reduce((matrix, pixel) => {
    const currentRow = matrix[matrix.length - 1];
    if (currentRow.length < imgWidth) {
      currentRow.push(pixel);
    } else {
      matrix.push([pixel]);
    }
    return matrix;
  }, [[]]);
  return pixelMatrix;
}

/**
 * finds the dimensions of an icon inside a single colored image
 * @param {HTMLImageElement} img 
 */
function findBox(img) {
  const pixelMatrix = convertImageToPixelData(img);
  const colorToFilter = pixelMatrix[0][0];

  const imgWidth = img.clientWidth;
  const imgHeight = img.clientHeight;

  let maxX = 0;
  let minX = imgWidth;
  let maxY = 0;
  let minY = imgHeight;

  // for each pixel calculate if the index of the pixel is greater than the current max or min
  for (let row = 0; row < imgHeight; row += 1) {
    for (let column = 0; column < imgWidth; column += 1) {
      const pixel = pixelMatrix[row][column];
      if (pixel !== colorToFilter) {
        if (column < minX) {
          minX = column;
        }
        if (column > maxX) {
          maxX = column;
        }
        if (row < minY) {
          minY = row;
        }
        if (row > maxY) {
          maxY = row;
        }
      }
    }
  }

  const width = maxX - minX + 1;
  const height = maxY - minY + 1;

  return { width, height };
}

const img = document.querySelector('#my-image');

const box = findBox(img);
console.log(box);
<img id="my-image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAABkCAIAAADrOV6nAAAFUklEQVR42u3caVPaXByG8X7/D+AuakXBBQVFgiRhJyAgCpElICSAJkFQcFdQLKCt6/NYW8LWe+Z6pTOO429O+J+TxG+6hIj6um/4E4AQgRCBEIT4K4AQgRCBEIQIhAiECIQgRCBEIEQgBCECIQIhAiEIEQgRCBEIQYhA2DvlyQglOqclSiV5LKE4CPuntVggtbUkUyMiMSSaJ4u+leskUdv3JTgQ9nLxfVfYnvcuyNRoU44Yke3q8o7xTqAfsk9VMwkQ9thSC5hEz4LsmJbJR7YhyTJ55NJUwut3/LPcc/weCHskjvPOSubGRXJUts+WGO1pSHcRJWpp6gO2F92kQNgLRd2ifay55kj1WfITs1cJ+mIgDsIuT5juHZ3cWHzEsOxcvhXor/gZK475HItxppvTSjTjUUnNCXOiFDLVs1/wqyd0JXpY8mytYlPRtcklapXo1g6Bnjv/ysXznls7dasan5qS3ezDvrBbF89AUNu6eI4UmNXq71w8+c0bVldmZgqPY6p5QmR8loH262HC+HbeOd5imDqJmP//4lkXTJd+TdE2JrV2Fw1yyarJMh579AAHbN3JtLsuk8PNrZ5Nc/m7F0/yLrpSdk1KxHjOG1mNZcyRpDkSdfo9ga1WXjLmWE+04pyGDD2VJ191QKoOP+rAsZx3PabPBax8nHVxhyD8bNvXXEljRz5D7SuTy9NHIG+5SxHVpOUyYihvr75rpbGPPPu8pTKjLrmbFe2TMjUubw6LT0u8saWZKYV3LCD8aHJxSrbW5GKZLrObD1/3UzbBUkuuXwS1ReuoaFYV2QwIX/uFjbKldU5mX7zm6Z7ze7PWo4ulLZsVhC+GF3vLb7jA/MnFsyvVUsw2CH+141U1159L1y9+rfwsCH/mlajGEpyqcH3k1/hoDLlB+FSMkBsjjGP5rp+WIH2b4TDO/CyibxAWfMY+8qsLARabiq4QVlndOWu+4R1V4VfWL/4Q2zUf8XDY2r9sz6g04T2nr7i+N+9yJFbLzgmJ1PBs/r9+Hz0nWJP8y/z7bCrdaC+UFEw4YPsoSilCfvM6vHhsG5cd2hcHddRt8LtE63dwRtq+giI9JLpW2rxviy6duNUlRnseJ999l7rwzIosCNt3U0lwDon2xWonRxLOUNgDYfsKN7b25PxVR6dKl5gCYRsPSIPzIjFzmv4Xz1YG5Yx0RycR48dsB084+ZgehG0/oCkGLR3xs1b5XR/u2rc7j0QOycyaAvuKjXPf/LFfX8vS19tzJe/6/sA9jdEjhKmco83HpPW08YyZkqmZ8vOjN1Q1ojmyzGR3QahAMc9424bStPHUqy6558rba++fe6vHtAUXvQbCtkf51Z0aSqmr4EYYhMoMpaPH4Y5MpPveXRAqNJQeBYhOEPIRAoQK5BfpIcmj78Cm4jSdwzijSBnXsGhduFXWz1lJp/XYVCg50cyeCcps5wW/mE7YB/GN+156mpvdkNs00bTu8aoKTu0FRz4IpnPfbIGalgKRtQQIlS2es/3VGc39/vpFaKn5ZgU9W3nzMo1gPnNNS7sgVPqFmKBGojRXf/XMPFFNbt5//F1DJZwGodLt5unRUphSaJyppA9BqHirYYNs1d7gNm9fv19oDy4UfMa6As9fMxhnOpYltHEUIdtK6DlMDeBVtLfftY/nHKmwzDM3gqOatf75Xaes8yLTWw/v/jv/LuFNh6bmg7mJeJrlM4ET3n/28ePY1lrr6zeCr5hhQ8mcPjGweH1HiEAIQgRCBEIEQhAiECIQIhCCEIEQgRCBEIQIhAiECIQgRCBEIEQgBCECIQIhAiEIUe/0A1MOqyYF+UAcAAAAAElFTkSuQmCC">