鸿蒙图片相似性对比

发布于:2025-06-29 ⋅ 阅读:(22) ⋅ 点赞:(0)

图片相似度对比方法概述

图片相似度对比是计算机视觉中的一个重要任务,主要用于判断两张图片在内容上的相似程度。以下是几种常见的图片相似度对比方法及其实现思路:

1. 基于像素的直接比较

最直接的方法是逐像素比较两张图片的差异,常用的指标有均方误差 (MSE) 和结构相似性指数 (SSIM)。

2. 基于特征提取的方法

使用图像特征描述符 (如 SIFT、SURF 或 ORB) 提取关键点和特征向量,然后比较特征向量的相似度.

3. 基于哈希的方法

通过计算图像的哈希值 (如感知哈希 pHash、平均哈希 aHash 等) 来快速比较图片相似度。

4. 基于深度学习的方法

使用预训练的卷积神经网络 (如 ResNet、VGG 等) 提取图像特征向量,然后计算向量间的余弦相似度。

选择合适的方法

  • 像素方法:简单直接,但对图像变换 (如旋转、缩放) 敏感。
  • 特征方法:对图像变换有较好的鲁棒性,计算量较大。
  • 哈希方法:计算速度快,适合快速筛选,但精度较低。
  • 深度学习方法:精度高,对各种变化都有很好的鲁棒性,但计算资源需求大。

鸿蒙基于Hash值相似性对比

图片压缩
async imageCompressionToSize(pixelMap: image.PixelMap, targetSize: number) {
    let infor = await pixelMap.getImageInfo()
    if (infor.size.height > 2000) {
      pixelMap.scaleSync(0.5, 0.5)
    }

    let value = await this.imageCompression(pixelMap, 90)
    // AmLog.debugOut("imageDataSize:" + value.buffer.byteLength)
    if (value.buffer.byteLength <= targetSize) {
      return value
    } else {
      while (value.buffer.byteLength/1024 > targetSize && value.quality > 10){
        try {
          value = await this.imageCompression(pixelMap, value.quality - 10)
        }catch (e) {
          break
        }
      }
    }
    let uint = new Uint8Array(value.buffer)
    let str = StrUtil.unit8ArrayToStr(uint)
    let md5 = await new Md5Util().doMd(str)
    value.md5 = md5
    return value
  }
  //压缩图片
  async imageCompression(pixelMap: image.PixelMap,quality:number) : Promise<ImageComValue>{
    let packOption: image.PackingOption = {
      format: "image/jpeg",
      quality: quality
    }
    let packer = image.createImagePacker()
    let buffer = await packer.packToData(pixelMap, packOption)

    // AmLog.debugOut(quality + "压缩imageDataSize:" + buffer.byteLength)
    let imageSource = image.createImageSource(buffer)
    const decodeOptions:image.DecodingOptions = {
      desiredPixelFormat: image.PixelMapFormat.RGBA_8888
    }
    let pixelMap1 = await imageSource.createPixelMap(decodeOptions)
    packer.release()

    return {pixMap: pixelMap1,quality,buffer}
  }
计算哈希值
 async getImageHash(imageSource: image.ImageSource): Promise<string> {

    


    let packOption: image.PackingOption = {
      format: "image/jpeg",
      quality: 80
    };
    const decodeOptions:image.DecodingOptions = {
      desiredSize: { width: this.imageSizeValue, height: this.imageSizeValue }, // 调整为像素大小
      desiredPixelFormat: image.PixelMapFormat.RGBA_8888
    }

    let pixelMap = await imageSource.createPixelMap(decodeOptions)
    this.imageSizeValue/imageLength)


    // 转换为灰度图并计算DCT变换(此处简化处理)
    // 创建图像打包器实例
    const imagePackerApi = image.createImagePacker();
    const pixelBuffer1:ArrayBuffer = await imagePackerApi.packToData(pixelMap,packOption)
    const pixels :Uint8Array = StrUtil.bufferToUint8Array(pixelBuffer1)

    //灰度计算
    let grayValues:number[] = []
    for (let i = 0; i < this.imageSizeValue * this.imageSizeValue; i++) {
      const idx = i * 4;
      if (idx + 2 >= pixels.byteLength) {
        grayValues.push(0)
        continue
      }
      // 简化的灰度计算
      grayValues.push( Math.floor((pixels[idx] * 0.299) + (pixels[idx + 1] * 0.587) + (pixels[idx + 2] * 0.114)))
    }
    //简化版DCT(离散余弦变换)这里使用简化版DCT实现,实际应用中应使用更高效的算法
    let dctPixels = this.simpleDCT(grayValues, this.imageSizeValue)

    // 计算均值
    const sum = dctPixels.reduce((acc, val,index) => {
      // 检查是否有NaN值
      if (isNaN(val)) {
        // AmLog.debugOut(`发现NaN值在位置:`+ index)
        return acc
      }
      return acc + val;
    }, 0);
    const mean = sum / dctPixels.length

    // 生成哈希值
    let hash = '';
    for (let i = 0; i < dctPixels.length; i++) {
      if (isNaN(dctPixels[i])) {
        continue
      }
      hash += dctPixels[i] >= mean ? '1' : '0';
    }

    return hash;
  }
哈希值对比
//比较图片相似度
   async compareImagesByHashPath(path1: string, path2: string): Promise<number> {
    const hash1 = await this.getImageHashByPath(path1);
    const hash2 = await this.getImageHashByPath(path2);

    // 计算汉明距离
    let diff = 0;
    for (let i = 0; i < hash1.length; i++) {
      if (hash1[i] !== hash2[i]) diff++;
    }

    // 计算相似度(汉明距离越小越相似)
    return (1 - diff / hash1.length) * 100;
  }
  //通过hash值对比图片相似度
   compareImagesByHash(hash1: string, hash2: string): number {
    // 计算汉明距离
    let diff = 0;
    for (let i = 0; i < hash1.length; i++) {
      if (hash1[i] === hash2[i]) diff++;
    }
    // 计算相似度(汉明距离越小越相似)
    return diff / hash1.length * 100;
  }
性能与精度平衡

imageSizeValue的选取

哈希尺寸 基础尺寸 内存占用 计算时间 适用场景
8×8 32×32 快速筛选
16×16 48×48 常规比较
16×64 96×96 高精度匹配

 


网站公告

今日签到

点亮在社区的每一天
去签到