HarmonyOS 鸿蒙Next 人脸活体检测成功后返回的人脸图片使用PixelMap 转化 base64串后无法渲染

发布于 1周前 作者 sinazl 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 人脸活体检测成功后返回的人脸图片使用PixelMap 转化 base64串后无法渲染

cke_247.png人脸活体检测成功后返回的 人脸图片 PixelMap 转化 base64串 后,无法渲染

15 回复

代码没问题,console.log 把数据截断了,打印不全

看下log base64的前缀有没有 【data:image/png;base64,】没有的话自己拼接上试式

拼接上前缀也无法渲染,要么是渲染出白色图片,要么是渲染出灰色图片

请参考以下代码,我这获取到的base64是返回给前端渲染(前端页面上img标签显示正常),你可以试试。

代码没问题,console.log 把数据截断了,打印不全


import { interactiveLiveness } from '@kit.VisionKit';
import { faceDetector } from '@kit.CoreVisionKit';
import { common, abilityAccessCtrl, Permissions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';
import util from '@ohos.util';
import { buffer } from '@kit.ArkTS';

export class YXFaceInfo { base64?: string; image?: image.PixelMap; securedImageBuffer?: ArrayBuffer; certificate?:string[]; imageparsecomplete: (complete:(error?: BusinessError,info?:YXFaceInfo) => void) => void; constructor(img?: image.PixelMap,securedImageBuffer?: ArrayBuffer,certificate?:string[]) { this.securedImageBuffer = securedImageBuffer; this.certificate = certificate; this.image = img; this.imageparsecomplete = (complete:(error?: BusinessError,info?:YXFaceInfo) => void) => { this.parseImg(complete); } }

async parseImg(complete:(error?: BusinessError,info?:YXFaceInfo) => void) { if (this.image) { // let visionInfo: faceDetector.VisionInfo = { // pixelMap: this.image // }; // let data: faceDetector.Face[] = await faceDetector.detect(visionInfo); // let faceRect = data[0].rect; // console.log(“faceRect.left=====”,faceRect.left) // console.log(“faceRect.top=====”,faceRect.top) // console.log(“faceRect.width=====”,faceRect.width) // console.log(“faceRect.height=====”,faceRect.height) // // let imageRange: image.Region = { // size: { // width: faceRect.width + 60, // height: faceRect.height + 70 // }, // x: faceRect.left - 30, // y: faceRect.top - 50 // }; // this.image.cropSync(imageRange); // // this.image.scaleSync(0.6,0.6);

  <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> info: image.ImageInfo = <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.image.getImageInfoSync();
  console.log(<span class="hljs-string"><span class="hljs-string">"height===="</span></span>,info.size.height)
  console.log(<span class="hljs-string"><span class="hljs-string">"width===="</span></span>,+info.size.width)
  console.log(<span class="hljs-string"><span class="hljs-string">"mimeType===="</span></span>,info.mimeType)
  console.log(<span class="hljs-string"><span class="hljs-string">"pixelFormat===="</span></span>,info.pixelFormat + <span class="hljs-string"><span class="hljs-string">""</span></span>)
  console.log(<span class="hljs-string"><span class="hljs-string">"isHdr===="</span></span>,info.isHdr + <span class="hljs-string"><span class="hljs-string">""</span></span>)
  console.log(<span class="hljs-string"><span class="hljs-string">"alphaType===="</span></span>,info.alphaType + <span class="hljs-string"><span class="hljs-string">""</span></span>)
  console.log(<span class="hljs-string"><span class="hljs-string">"stride===="</span></span>,info.stride + <span class="hljs-string"><span class="hljs-string">""</span></span>)
  console.log(<span class="hljs-string"><span class="hljs-string">"density===="</span></span>,info.density + <span class="hljs-string"><span class="hljs-string">""</span></span>)


  console.log(<span class="hljs-string"><span class="hljs-string">"da========="</span></span>,<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.image.getPixelBytesNumber()/<span class="hljs-number"><span class="hljs-number">1024</span></span> + <span class="hljs-string"><span class="hljs-string">""</span></span>)


  <span class="hljs-keyword"><span class="hljs-keyword">const</span></span> imagePackerApi: image.ImagePacker = image.createImagePacker();
  <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> packOpts: image.PackingOption = { format: <span class="hljs-string"><span class="hljs-string">"image/jpeg"</span></span>, quality: <span class="hljs-number"><span class="hljs-number">98</span></span> };
  imagePackerApi.packing(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.image, packOpts).then((data: <span class="hljs-built_in"><span class="hljs-built_in">ArrayBuffer</span></span>) =&gt; {

    console.info(<span class="hljs-string"><span class="hljs-string">'Succeeded in packing the image.===='</span></span>,data.byteLength);

    <span class="hljs-comment"><span class="hljs-comment">// let u8Arr = new Uint8Array(data);</span></span>
    <span class="hljs-comment"><span class="hljs-comment">// let b64H = new util.Base64Helper();</span></span>
    <span class="hljs-comment"><span class="hljs-comment">// this.base64 = b64H.encodeToStringSync(u8Arr);</span></span>
    <span class="hljs-comment"><span class="hljs-comment">// console.log("b64=====",this.base64);</span></span>
    <span class="hljs-comment"><span class="hljs-comment">// console.log("lll====",this.base64.length);</span></span>


    <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> buf: buffer.Buffer = buffer.from(data);
    <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.base64 = buf.toString(<span class="hljs-string"><span class="hljs-string">'base64'</span></span>, <span class="hljs-number"><span class="hljs-number">0</span></span>, buf.length);
    console.info(<span class="hljs-string"><span class="hljs-string">'base64: '</span></span> + <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.base64);
    <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (complete) {
      complete(<span class="hljs-literal"><span class="hljs-literal">undefined</span></span>,<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>);
    }
  }).catch((err:BusinessError) =&gt; {
    console.log(<span class="hljs-string"><span class="hljs-string">"err===="</span></span>,err + <span class="hljs-string"><span class="hljs-string">""</span></span>);
    console.log(err.code + <span class="hljs-string"><span class="hljs-string">""</span></span>);
    <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (complete) {
      complete(err,<span class="hljs-literal"><span class="hljs-literal">undefined</span></span>);
    }
  });
}

} }

export interface YXFaceObject { face?: YXFaceInfo; error?: BusinessError; }

export class YXFaceManger {

private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; private array: Array<Permissions> = [“ohos.permission.CAMERA”]; private static _manger?: YXFaceManger;

private constructor() { } public static share(): YXFaceManger { if (!YXFaceManger._manger) { YXFaceManger._manger = new YXFaceManger(); } return YXFaceManger._manger; }

public sanFace(complete:(resp:YXFaceObject) => void) { this.systemPower((hasPower: boolean) => { if (hasPower) { this.privateStartDetection((hasCameraPower: boolean) => { if (hasCameraPower) { this.privateRouterLibrary(complete); }else { complete({ error: { code: -1, name: “没有相机权限”, message: “没有相机权限” } }); } }) }else { complete({ error: { code: -1, name: “系统无活体检测能力”, message: “系统无活体检测能力” } }); } }) }

// 检验系统能力是否可用 private systemPower(complete:(have: boolean) => void) { let canUse = canIUse(“SystemCapability.AI.Component.LivenessDetect”); complete(canUse); }

// 校验CAMERA权限 private privateStartDetection(complete:(have: boolean) => void) { abilityAccessCtrl.createAtManager().requestPermissionsFromUser(this.context, this.array).then((res) => { for (let i = 0; i < res.permissions.length; i++) { if (res.permissions[i] === “ohos.permission.CAMERA” && res.authResults[i] === 0) { complete(true); }else { complete(false); } } }) }

// 路由跳转到人脸活体验证控件 private privateRouterLibrary(complete:(resp:YXFaceObject) => void) {

<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> routerOptions: interactiveLiveness.InteractiveLivenessConfig = {
  <span class="hljs-string"><span class="hljs-string">"actionsNum"</span></span>: <span class="hljs-number"><span class="hljs-number">1</span></span>,
  <span class="hljs-string"><span class="hljs-string">"isSilentMode"</span></span>: <span class="hljs-string"><span class="hljs-string">"SILENT_MODE"</span></span> as interactiveLiveness.DetectionMode,
  <span class="hljs-string"><span class="hljs-string">"routeMode"</span></span>: <span class="hljs-string"><span class="hljs-string">"back"</span></span> as interactiveLiveness.RouteRedirectionMode,
  <span class="hljs-string"><span class="hljs-string">"speechSwitch"</span></span>: <span class="hljs-literal"><span class="hljs-literal">false</span></span>
};
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (canIUse(<span class="hljs-string"><span class="hljs-string">"SystemCapability.AI.Component.LivenessDetect"</span></span>)) {
  interactiveLiveness.startLivenessDetection(routerOptions, async (error: BusinessError,data: interactiveLiveness.InteractiveLivenessResult | <span class="hljs-literal"><span class="hljs-literal">undefined</span></span>) =&gt; {
    <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (error.code != <span class="hljs-number"><span class="hljs-number">0</span></span> &amp;&amp; !data) {
      complete({
        error: error
      });
      <span class="hljs-keyword"><span class="hljs-keyword">return</span></span>;
    }
    <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> result: interactiveLiveness.InteractiveLivenessResult = data as interactiveLiveness.InteractiveLivenessResult;
    <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> faceInfo: YXFaceInfo = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> YXFaceInfo(result.mPixelMap,result.securedImageBuffer,result.certificate);
    faceInfo.imageparsecomplete((err?: BusinessError, info?: YXFaceInfo) =&gt; {
      <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> faceObj: YXFaceObject = {
        face: info,
        error: err
      }
      complete(faceObj);
    });
  }).then((detectState: boolean) =&gt; {
    <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!detectState) {
      <span class="hljs-keyword"><span class="hljs-keyword">let</span></span> faceObj: YXFaceObject = {
        error: {
          name: <span class="hljs-string"><span class="hljs-string">"扫脸控件拉起失败"</span></span>,
          message: <span class="hljs-string"><span class="hljs-string">"扫脸控件拉起失败"</span></span>,
          code: -<span class="hljs-number"><span class="hljs-number">1</span></span>
        }
      }
      complete(faceObj);
    }
  }).catch((err: BusinessError) =&gt; {
    complete({
      error: err
    });
  })
}

} }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

这段代码我试了,没问题啊!

console.log 把数据截断了,只打印出了一部分

async function pixelMapToBase64(pixelMap: PixelMap): Promise<string> {
let imagePackerApi: image.ImagePacker = image.createImagePacker();
let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 100 };
let data = await imagePackerApi.packing(pixelMap, packOpts)
let buf: buffer.Buffer = buffer.from(data);
let resourceBase64: string = 'data:image/jpeg;base64,' + buf.toString('base64', 0, buf.length);
console.log("imagePackerApi...", resourceBase64)
return resourceBase64
}

无法渲染就是你的代码有问题,拿到base64数据用这个进行验证,不会有问题的!https://www.uutils.com/image/base64_to_image.htm

你这个方法也不行,依然是白色的图片

如果这个链接在线转换也不行,那就是你pixelMap有问题,pixelMap能正常显示吗, Image(src: PixelMap | ResourceStr | DrawableDescriptor)?

一步一步往前推吧

pixelMap 是扫脸组件返回的,可以用 image 组件显示,但是转化成 base64后,在浏览器上渲染不出来

试试显示PixelMap 是否正常

用系统组件 image 能正常渲染,其他应该怎么判断 PixelMap 是否正常?

在鸿蒙系统(HarmonyOS)中,若PixelMap转化为base64字符串后无法渲染,可能是因为转换过程中像素数据格式、编码方式或图像元数据(如DPI、尺寸等)未正确处理。确保在转换时采用正确的图像格式(如PNG或JPEG),并正确设置Base64编码参数。此外,检查渲染环境是否支持解析并正确显示该格式的图像。

如果问题依旧没法解决请加我微信,我的微信是itying888。

回到顶部