HarmonyOS 鸿蒙Next 人脸活体检测成功后返回的人脸图片使用PixelMap 转化 base64串后无法渲染
HarmonyOS 鸿蒙Next 人脸活体检测成功后返回的人脸图片使用PixelMap 转化 base64串后无法渲染
代码没问题,console.log 把数据截断了,打印不全
拼接上前缀也无法渲染,要么是渲染出白色图片,要么是渲染出灰色图片
请参考以下代码,我这获取到的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>) => {
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) => {
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>) => {
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (error.code != <span class="hljs-number"><span class="hljs-number">0</span></span> && !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) => {
<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> faceObj: YXFaceObject = {
face: info,
error: err
}
complete(faceObj);
});
}).then((detectState: boolean) => {
<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) => {
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 是扫脸组件返回的,可以用 image 组件显示,但是转化成 base64后,在浏览器上渲染不出来
用系统组件 image 能正常渲染,其他应该怎么判断 PixelMap 是否正常?
在鸿蒙系统(HarmonyOS)中,若PixelMap
转化为base64字符串后无法渲染,可能是因为转换过程中像素数据格式、编码方式或图像元数据(如DPI、尺寸等)未正确处理。确保在转换时采用正确的图像格式(如PNG或JPEG),并正确设置Base64编码参数。此外,检查渲染环境是否支持解析并正确显示该格式的图像。
如果问题依旧没法解决请加我微信,我的微信是itying888。