如何解决HarmonyOS鸿蒙Next中获取灰度化图片质量低的问题

如何解决HarmonyOS鸿蒙Next中获取灰度化图片质量低的问题

【问题现象】

在图像处理和识别任务中,灰度化可以简化图像矩阵,减少计算量。通过灰度化处理,可以更容易地识别和分割图像中的不同区域,提取有用的特征信息。此外,灰度化处理后的图片存储大小显著减少,有利于网络传输和持久化存储。

【背景知识】

灰度化处理是将一副彩色图像转化为灰色图像的过程。彩色图像由R(红色)、G(绿色)、B(蓝色)三个分量组成,分别显示红、绿、蓝三种颜色。灰度化就是将彩色图像转换为每个像素点R、G、B分量值相等的灰度图像。

当前,实现图片灰度化处理的方法主要有以下四种:

  1. 加权平均值法:

    根据人类的视觉特点,发现白色由大约0.299的红色、0.587的绿色、0.114的蓝色组成。最常用的灰度变换公式如下:

    D = 0.299 x R + 0.587 x G + 0.114 x B
    

    其中,D表示像素点(x,y)经过转换后的灰度值,R、G、B为该像素点三个通道的分量。

  2. 分量法:

    直接选取像素点的R、G、B三个分量中的一个作为灰度值。例如,可以选择R分量、G分量或者B分量作为灰度值。

  3. 最大值法:

    将彩色图像中三个分量亮度的最大值作为灰度图的灰度值。

  4. 平均值法:

    将R、G、B三个分量的颜色值平均值作为灰度值。

【定位思路】

针对以上的四种方案,对同一张图片进行处理,结果进行对比分析。

【解决方案】

(1)加权平均值法

import { image } from '@kit.ImageKit';
import { Position } from '@ohos.arkui.node';

@Entry
@Component
struct Index {
  @State pixelMap?:PixelMap = undefined;

  /**
   * 从url文件路径创建一个图片pixelMap
   * @param url
   * @returns
   */
  async createPixelMapFromFile(url :string){
    const fileData: Uint8Array=await getContext().resourceManager.getRawFileContent(url);
    // 创建一个可供编辑的图片复制品
    const buffer=fileData.buffer.slice(fileData.byteOffset,fileData.byteLength+fileData.byteOffset)
    let imageSource=image.createImageSource(buffer);
    const options:image.DecodingOptions = {
      editable:true,
      desiredPixelFormat:image.PixelMapFormat.RGBA_8888,
    }
    let pixelMap:PixelMap=await imageSource.createPixelMap(options);
    return pixelMap;
  }

  /**
   * 加权平均值方案
   * @param pixelMap
   */
  async method1(pixelMap :PixelMap){
    let info:image.ImageInfo=await pixelMap.getImageInfo();
    let height=info.size.height
    let width=info.size.width
    const bufferData = new ArrayBuffer(pixelMap.getPixelBytesNumber());
    await pixelMap.readPixelsToBuffer(bufferData);
    // 将像素数据转换为 Uint8Array 便于像素处理
    let dataArray = new Uint8Array(bufferData);
    for(let i=0;i<width;i++){
      for(let j=0;j<height;j++){
        let alpha = (j*width +i)*4;
        let R=  dataArray[alpha];
        let G = dataArray[alpha+1];
        let B = dataArray[alpha+2];
        let D = 0.299*R + 0.587*G + 0.114*B;
        dataArray[alpha]=D;
        dataArray[alpha+1]=D;
        dataArray[alpha+2]=D;
      }
    }
    // 写入
    pixelMap.writeBufferToPixelsSync(dataArray.buffer)
  }
  async compare() {
   let pixelMap= await this.createPixelMapFromFile("fruit.jpg");
    await this.method1(pixelMap);
    this.pixelMap=pixelMap;
  }
  build() {
    Column() {
      Text("原始图片")
      Image($rawfile("fruit.jpg"))
        .height(300)
        .objectFit(ImageFit.Cover)
      Row(){
        Button("对比")
          .onClick(()=>{
            this.compare();
          })
      }
      Text("修改后的图片")
      if(this.pixelMap){
        Image(this.pixelMap)
          .height(300)
          .objectFit(ImageFit.Cover)
      }
    }
    .height('100%')
    .width('100%')
  }
}

(2)分量法

替换以上代码的method1方法即可:

  async method2(pixelMap :PixelMap){
     let info:image.ImageInfo=await pixelMap.getImageInfo();
     let height=info.size.height
     let width=info.size.width
     const bufferData = new ArrayBuffer(pixelMap.getPixelBytesNumber());
     await pixelMap.readPixelsToBuffer(bufferData);
     // 将像素数据转换为Uint8Array便于像素处理
     let dataArray = new Uint8Array(bufferData);
     for(let i=0;i<width;i++){
       for(let j=0;j<height;j++){
         let alpha = (j*width +i)*4;
         let R=  dataArray[alpha];
         let G = dataArray[alpha+1];
         let B = dataArray[alpha+2];

         dataArray[alpha]=R;
         dataArray[alpha+1]=R;
         dataArray[alpha+2]=R;
       }
     }
     // 写入
     pixelMap.writeBufferToPixelsSync(dataArray.buffer)
  }

(3)最大值法

  async method3(pixelMap :PixelMap){
     let info:image.ImageInfo=await pixelMap.getImageInfo();
     let height=info.size.height
     let width=info.size.width
     const bufferData = new ArrayBuffer(pixelMap.getPixelBytesNumber());
     await pixelMap.readPixelsToBuffer(bufferData);
     // 将像素数据转换为Uint8Array便于像素处理
     let dataArray = new Uint8Array(bufferData);
     for(let i=0;i<width;i++){
       for(let j=0;j<height;j++){
         let alpha = (j*width +i)*4;
         let R=  dataArray[alpha];
         let G = dataArray[alpha+1];
         let B = dataArray[alpha+2];
         let maxValue=Math.max(R,G,B);
         dataArray[alpha]=maxValue;
         dataArray[alpha+1]=maxValue;
         dataArray[alpha+2]=maxValue;
       }
     }
     // 写入
     pixelMap.writeBufferToPixelsSync(dataArray.buffer)
  }

(4)平均值法

  async method4(pixelMap :PixelMap){
     let info:image.ImageInfo=await pixelMap.getImageInfo();
     let height=info.size.height
     let width=info.size.width
     const bufferData = new ArrayBuffer(pixelMap.getPixelBytesNumber());
     await pixelMap.readPixelsToBuffer(bufferData);
     // 将像素数据转换为Uint8Array便于像素处理
     let dataArray = new Uint8Array(bufferData);
     for(let i=0;i<width;i++){
       for(let j=0;j<height;j++){
         let alpha = (j*width +i)*4;
         let R=  dataArray[alpha];
         let G = dataArray[alpha+1];
         let B = dataArray[alpha+2];
         let average=(R+G+B)/3;
         dataArray[alpha]=average;
         dataArray[alpha+1]=average;
         dataArray[alpha+2]=average;
       }
     }
     // 写入
     pixelMap.writeBufferToPixelsSync(dataArray.buffer)
  }

效果图如下:

  • 加权平均法

加权平均法

  • 分量法

分量法

  • 最大值法

最大值法

  • 平均法

平均法

【总结】

通过以上分析,加权平均值法和平均值法转化后的效果较好。其中,加权平均法保留了更好的分辨率,分量法和最大值法的分辨率较低。因此,在实际应用中,加权平均值法常被推荐使用。


更多关于如何解决HarmonyOS鸿蒙Next中获取灰度化图片质量低的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于如何解决HarmonyOS鸿蒙Next中获取灰度化图片质量低的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,获取灰度化图片质量低的问题

在HarmonyOS鸿蒙Next中,获取灰度化图片质量低的问题可能与图像处理算法或API调用方式有关。首先,确保使用PixelMap类进行图像处理时,正确设置了图像的分辨率和色彩模式。可以通过ImageSource类加载图片,并使用createPixelMap方法生成PixelMap对象,确保传入的参数如InitializationOptions中的sizepixelFormat符合需求。

其次,检查灰度化处理算法。鸿蒙提供了ImagePackerImageReceiver等工具,可以在处理过程中保持图像质量。如果使用自定义算法进行灰度化,确保算法不会过度压缩或丢失图像细节。可以使用PixelMapgetPixelBytes方法获取像素数据,并在处理时保留足够的位深度。

最后,确认图像输出时的编码格式和压缩比。使用ImagePacker打包图像时,选择合适的编码格式(如JPEG或PNG)并调整压缩参数,以避免质量损失。通过以上步骤,可以有效提升灰度化图片的质量。

回到顶部