鸿蒙跨端智能皮肤检测系统开发指南 原创

进修的泡芙
发布于 2025-6-22 17:06
浏览
0收藏

鸿蒙跨端智能皮肤检测系统开发指南

一、系统架构设计

基于HarmonyOS的AI能力和分布式技术,构建皮肤状态检测与护理建议系统:
图像采集层:通过摄像头获取皮肤图像

皮肤分析层:使用AI模型分析皮肤状态

建议生成层:根据分析结果生成护理建议

跨端同步层:多设备间同步检测结果和护理方案

!https://example.com/harmony-skin-analysis-arch.png

二、核心代码实现
皮肤检测服务

// SkinAnalysisService.ets
import ai from ‘@ohos.ai’;
import camera from ‘@ohos.multimedia.camera’;
import distributedData from ‘@ohos.distributedData’;
import { SkinAnalysisResult, SkinCareAdvice } from ‘./SkinTypes’;

class SkinAnalysisService {
private static instance: SkinAnalysisService = null;
private modelManager: ai.ModelManager;
private dataManager: distributedData.DataManager;
private resultListeners: SkinAnalysisListener[] = [];

private constructor() {
this.initModelManager();
this.initDataManager();
public static getInstance(): SkinAnalysisService {

if (!SkinAnalysisService.instance) {
  SkinAnalysisService.instance = new SkinAnalysisService();

return SkinAnalysisService.instance;

private initModelManager(): void {

try {
  this.modelManager = ai.createModelManager(getContext());
  
  // 加载皮肤分析模型
  this.modelManager.loadModel({
    modelName: 'skin_analysis',
    modelPath: 'resources/rawfile/skin_analysis.model',
    callback: (err, data) => {
      if (err) {
        console.error('加载皮肤模型失败:', JSON.stringify(err));

}

  });
  
  // 加载护理建议模型
  this.modelManager.loadModel({
    modelName: 'skin_care_advice',
    modelPath: 'resources/rawfile/skin_care.model',
    callback: (err, data) => {
      if (err) {
        console.error('加载护理模型失败:', JSON.stringify(err));

}

  });

catch (err) {

  console.error('初始化模型管理器失败:', JSON.stringify(err));

}

private initDataManager(): void {
this.dataManager = distributedData.createDataManager({
bundleName: ‘com.example.skinanalysis’,
area: distributedData.Area.GLOBAL,
isEncrypted: true
});

this.dataManager.registerDataListener('skin_result_sync', (data) => {
  this.handleSyncData(data);
});

public async requestPermissions(): Promise<boolean> {

try {
  const permissions = [
    'ohos.permission.USE_AI',
    'ohos.permission.CAMERA',
    'ohos.permission.DISTRIBUTED_DATASYNC'
  ];
  
  const result = await abilityAccessCtrl.requestPermissionsFromUser(
    getContext(), 
    permissions
  );
  
  return result.grantedPermissions.length === permissions.length;

catch (err) {

  console.error('请求权限失败:', JSON.stringify(err));
  return false;

}

public async analyzeSkin(imageData: ArrayBuffer): Promise<SkinAnalysisResult> {
try {
const input = {
data: imageData,
width: 224,
height: 224,
format: ‘RGB’
};

  const analysisResult = await this.modelManager.runModel({
    modelName: 'skin_analysis',
    input: input
  });
  
  const advice = await this.generateAdvice(analysisResult.result);
  
  const result: SkinAnalysisResult = {
    id: Date.now().toString(),
    moistureLevel: analysisResult.result.moisture,
    oilinessLevel: analysisResult.result.oiliness,
    sensitivityLevel: analysisResult.result.sensitivity,
    acneLevel: analysisResult.result.acne,
    pigmentationLevel: analysisResult.result.pigmentation,
    advice: advice,
    timestamp: Date.now(),
    imageData: imageData
  };
  
  // 同步分析结果
  this.syncResult(result);
  
  return result;

catch (err) {

  console.error('皮肤分析失败:', JSON.stringify(err));
  throw err;

}

private async generateAdvice(analysis: any): Promise<SkinCareAdvice> {
const input = {
moisture: analysis.moisture,
oiliness: analysis.oiliness,
sensitivity: analysis.sensitivity,
acne: analysis.acne,
pigmentation: analysis.pigmentation
};

const output = await this.modelManager.runModel({
  modelName: 'skin_care_advice',
  input: input
});

return output.result;

private syncResult(result: SkinAnalysisResult): void {

this.dataManager.syncData('skin_result_sync', {
  type: 'skin_result',
  data: result,
  timestamp: Date.now()
});

private handleSyncData(data: any): void {

if (!data || data.type !== 'skin_result') return;

this.notifyResultListeners(data.data);

private notifyResultListeners(result: SkinAnalysisResult): void {

this.resultListeners.forEach(listener => {
  listener.onSkinAnalysisResult(result);
});

public addResultListener(listener: SkinAnalysisListener): void {

if (!this.resultListeners.includes(listener)) {
  this.resultListeners.push(listener);

}

public removeResultListener(listener: SkinAnalysisListener): void {
this.resultListeners = this.resultListeners.filter(l => l !== listener);
}

interface SkinAnalysisListener {
onSkinAnalysisResult(result: SkinAnalysisResult): void;
export const skinAnalysisService = SkinAnalysisService.getInstance();

相机服务封装

// CameraService.ets
import camera from ‘@ohos.multimedia.camera’;
import image from ‘@ohos.multimedia.image’;

class CameraService {
private static instance: CameraService = null;
private cameraManager: camera.CameraManager;
private cameraInput: camera.CameraInput;
private previewOutput: camera.PreviewOutput;
private captureSession: camera.CaptureSession;
private imageReceiver: image.ImageReceiver;

private constructor() {
this.initCamera();
public static getInstance(): CameraService {

if (!CameraService.instance) {
  CameraService.instance = new CameraService();

return CameraService.instance;

private initCamera(): void {

try {
  const context = getContext() as common.Context;
  this.cameraManager = camera.getCameraManager(context);
  
  // 获取前置摄像头
  const cameras = this.cameraManager.getSupportedCameras();
  const frontCamera = cameras.find(cam => cam.position === camera.CameraPosition.FRONT);
  
  if (!frontCamera) {
    throw new Error('未找到前置摄像头');

// 创建相机输入

  this.cameraInput = this.cameraManager.createCameraInput(frontCamera);
  
  // 创建预览输出
  const previewProfile = this.cameraManager.getSupportedOutputCapability(frontCamera)
    .previewProfiles[0];
  
  this.previewOutput = this.cameraManager.createPreviewOutput(previewProfile);
  
  // 创建图像接收器
  this.imageReceiver = image.createImageReceiver(
    224, 224, 
    image.ImageFormat.RGB_888, 

);

  // 创建捕获会话
  this.captureSession = this.cameraManager.createCaptureSession();
  this.captureSession.beginConfig();
  this.captureSession.addInput(this.cameraInput);
  this.captureSession.addOutput(this.previewOutput);
  this.captureSession.commitConfig();
  this.captureSession.start();

catch (err) {

  console.error('初始化相机失败:', JSON.stringify(err));

}

public async captureFrame(): Promise<ArrayBuffer> {
try {
const image = await this.imageReceiver.readNextImage();
const buffer = await image.getComponent(image.ComponentType.RGB);
image.release();

  return buffer.byteArray;

catch (err) {

  console.error('捕获帧失败:', JSON.stringify(err));
  throw err;

}

public startPreview(surfaceId: string): void {
this.previewOutput.start(surfaceId);
public stopPreview(): void {

this.previewOutput.stop();

public release(): void {

this.captureSession.stop();
this.cameraInput.release();
this.previewOutput.release();
this.captureSession.release();

}

export const cameraService = CameraService.getInstance();

主界面实现

// MainScreen.ets
import { skinAnalysisService } from ‘./SkinAnalysisService’;
import { cameraService } from ‘./CameraService’;
import { SkinAnalysisResult, SkinCareAdvice } from ‘./SkinTypes’;

@Component
export struct MainScreen {
@State hasPermission: boolean = false;
@State isAnalyzing: boolean = false;
@State currentResult: SkinAnalysisResult | null = null;
@State previewSurfaceId: string = ‘’;
@State showHistory: boolean = false;
@State analysisHistory: SkinAnalysisResult[] = [];

build() {
Column() {
// 标题栏
Row() {
Text(‘皮肤状态检测’)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)

    Button(this.hasPermission ? '历史记录' : '授权')
      .width(100)
      .onClick(() => {
        if (this.hasPermission) {
          this.showHistory = !this.showHistory;

else {

          this.requestPermissions();

})

.padding(10)

  .width('100%')
  
  // 历史记录面板
  if (this.showHistory) {
    Column() {
      Text('历史检测记录')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 10 })
      
      if (this.analysisHistory.length === 0) {
        Text('暂无历史记录')
          .fontSize(16)
          .fontColor('#666666')
          .margin({ top: 20 })

else {

        List({ space: 10 }) {
          ForEach(this.analysisHistory, (item) => {
            ListItem() {
              Column() {
                Row() {
                  Text(new Date(item.timestamp).toLocaleDateString())
                    .fontSize(16)
                    .fontWeight(FontWeight.Bold)
                    .layoutWeight(1)
                  
                  Text(水分: ${item.moistureLevel.toFixed(1)})
                    .fontSize(14)
                    .fontColor('#409EFF')
                    .margin({ right: 10 })

.margin({ bottom: 5 })

                Row() {
                  Progress({
                    value: item.moistureLevel,
                    total: 100,
                    style: ProgressStyle.Linear
                  })
                  .width('70%')
                  .height(10)

}

              .padding(10)
              .width('100%')
              .backgroundColor('#FFFFFF')
              .border({ width: 1, color: '#E0E0E0' })
              .borderRadius(8)
              .onClick(() => {
                this.currentResult = item;
                this.showHistory = false;
              })

})

.height(300)

}

    .padding(15)
    .width('90%')
    .backgroundColor('#FFFFFF')
    .border({ width: 1, color: '#E0E0E0' })
    .borderRadius(8)
    .margin({ bottom: 20 })

// 相机预览区域

  if (!this.showHistory) {
    Stack() {
      if (this.hasPermission) {
        // 相机预览Surface
        Surface({
          id: this.previewSurfaceId,
          type: SurfaceType.SURFACE_TEXTURE,
          width: '100%',
          height: 300
        })
        .onAppear(() => {
          this.previewSurfaceId = preview_${Date.now()};
          cameraService.startPreview(this.previewSurfaceId);
        })
        .onDisappear(() => {
          cameraService.stopPreview();
        })
        
        // 分析按钮
        if (!this.isAnalyzing) {
          Button('开始检测')
            .width(150)
            .height(50)
            .fontSize(20)
            .backgroundColor('#409EFF')
            .position({ x: '50%', y: '80%' })
            .margin({ left: -75 })
            .onClick(() => {
              this.startAnalysis();
            })

else {

          Column() {
            Progress({})
              .width(50)
              .height(50)
            
            Text('分析中...')
              .fontSize(16)
              .margin({ top: 10 })

.width(‘100%’)

          .height('100%')
          .justifyContent(FlexAlign.Center)
          .alignItems(HorizontalAlign.Center)

} else {

        Column() {
          Text('需要权限')
            .fontSize(18)
            .margin({ bottom: 10 })
          
          Text('请点击右上角"授权"按钮,允许应用访问相机和AI功能')
            .fontSize(16)
            .fontColor('#666666')

.padding(20)

        .width('90%')
        .backgroundColor('#F5F5F5')
        .borderRadius(8)
        .margin({ top: 50 })

}

    .width('100%')
    .height(300)
    .margin({ bottom: 20 })

// 分析结果

  if (this.currentResult && !this.showHistory) {
    Column() {
      Text('皮肤分析结果')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 15 })
      
      // 皮肤指标展示
      Grid() {
        GridItem() {
          this.buildIndicator('水分', this.currentResult.moistureLevel, '#409EFF')

GridItem() {

          this.buildIndicator('油分', this.currentResult.oilinessLevel, '#FF9800')

GridItem() {

          this.buildIndicator('敏感度', this.currentResult.sensitivityLevel, '#F44336')

GridItem() {

          this.buildIndicator('痘痘', this.currentResult.acneLevel, '#4CAF50')

GridItem() {

          this.buildIndicator('色素沉着', this.currentResult.pigmentationLevel, '#9C27B0')

}

      .columnsTemplate('1fr 1fr')
      .rowsTemplate('1fr 1fr 1fr')
      .columnsGap(10)
      .rowsGap(10)
      .height(200)
      .margin({ bottom: 20 })
      
      // 护理建议
      Column() {
        Text('护理建议')
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .margin({ bottom: 10 })
        
        ForEach(this.currentResult.advice.items, (item) => {
          Row() {
            Image(item.type === 'cleanser' ? $r('app.media.ic_cleanser') : 
                 item.type === 'moisturizer' ? $r('app.media.ic_moisturizer') :
                 item.type === 'sunscreen' ? $r('app.media.ic_sunscreen') :
                 $r('app.media.ic_treatment'))
              .width(24)
              .height(24)
              .margin({ right: 10 })
            
            Text(item.description)
              .fontSize(14)
              .layoutWeight(1)
              .textAlign(TextAlign.Start)

.margin({ bottom: 8 })

        })

.padding(15)

      .width('100%')
      .backgroundColor('#F5F5F5')
      .borderRadius(8)

.width(‘100%’)

}

.width('100%')
.height('100%')
.padding(20)
.onAppear(() => {
  this.checkPermissions();
  skinAnalysisService.addResultListener({
    onSkinAnalysisResult: (result) => {
      this.handleAnalysisResult(result);

});

})
.onDisappear(() => {
  skinAnalysisService.removeResultListener({
    onSkinAnalysisResult: (result) => {
      this.handleAnalysisResult(result);

});

  cameraService.release();
})

private buildIndicator(title: string, value: number, color: string): void {

Column() {
  Text(title)
    .fontSize(14)
    .fontColor('#666666')
  
  Text(${value.toFixed(1)})
    .fontSize(18)
    .fontWeight(FontWeight.Bold)
    .fontColor(color)
    .margin({ top: 5, bottom: 5 })
  
  Progress({
    value: value,
    total: 100,
    style: ProgressStyle.Linear
  })
  .width('100%')
  .height(6)

.padding(10)

.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#E0E0E0' })
.borderRadius(8)

private async checkPermissions(): Promise<void> {

try {
  const permissions = [
    'ohos.permission.USE_AI',
    'ohos.permission.CAMERA',
    'ohos.permission.DISTRIBUTED_DATASYNC'
  ];
  
  const result = await abilityAccessCtrl.verifyPermissions(
    getContext(),
    permissions
  );
  
  this.hasPermission = result.every(perm => perm.granted);

catch (err) {

  console.error('检查权限失败:', JSON.stringify(err));
  this.hasPermission = false;

}

private async requestPermissions(): Promise<void> {
this.hasPermission = await skinAnalysisService.requestPermissions();

if (!this.hasPermission) {
  prompt.showToast({ message: '授权失败,无法使用皮肤检测功能' });

}

private async startAnalysis(): Promise<void> {
try {
this.isAnalyzing = true;

  // 捕获当前帧
  const frame = await cameraService.captureFrame();
  
  // 分析皮肤状态
  const result = await skinAnalysisService.analyzeSkin(frame);
  
  this.currentResult = result;
  this.analysisHistory = [result, ...this.analysisHistory].slice(0, 10); // 保留最近10条记录

catch (err) {

  console.error('皮肤分析失败:', JSON.stringify(err));
  prompt.showToast({ message: '分析失败,请重试' });

finally {

  this.isAnalyzing = false;

}

private handleAnalysisResult(result: SkinAnalysisResult): void {
this.currentResult = result;
this.isAnalyzing = false;

// 添加到历史记录
this.analysisHistory = [result, ...this.analysisHistory].slice(0, 10);

}

类型定义

// SkinTypes.ets
export interface SkinAnalysisResult {
id: string;
moistureLevel: number; // 0-100
oilinessLevel: number; // 0-100
sensitivityLevel: number; // 0-100
acneLevel: number; // 0-100
pigmentationLevel: number; // 0-100
advice: SkinCareAdvice;
timestamp: number;
imageData: ArrayBuffer;
export interface SkinCareAdvice {

summary: string;
items: {
type: ‘cleanser’ ‘moisturizer’ ‘sunscreen’
‘treatment’;
description: string;
priority: number;
}[];

三、项目配置与权限
权限配置

// module.json5
“module”: {

"requestPermissions": [

“name”: “ohos.permission.USE_AI”,

    "reason": "使用AI模型分析皮肤状态"
  },

“name”: “ohos.permission.CAMERA”,

    "reason": "拍摄皮肤照片"
  },

“name”: “ohos.permission.DISTRIBUTED_DATASYNC”,

    "reason": "同步分析结果"

],

"abilities": [

“name”: “MainAbility”,

    "type": "page",
    "visible": true
  },

“name”: “CameraAbility”,

    "type": "service",
    "backgroundModes": ["camera"]

]

}

四、总结与扩展

本皮肤检测系统实现了以下核心功能:
皮肤状态分析:准确检测水分、油分、敏感度等关键指标

个性化建议:根据皮肤状态生成定制护理方案

历史记录:保存多次检测结果便于追踪变化

跨设备同步:多设备间共享检测结果和护理方案

扩展方向:
皮肤趋势分析:绘制皮肤指标变化曲线

产品推荐:对接电商平台推荐适合的护肤品

环境因素分析:结合天气、湿度等环境数据优化建议

皮肤类型测试:帮助用户确定皮肤类型

AR试妆:虚拟试用推荐产品

专业咨询:连接皮肤科医生提供专业建议

通过HarmonyOS的AI能力和分布式技术,我们构建了一个智能化的皮肤健康管理系统,帮助用户科学了解皮肤状态,并获得个性化的护理方案,同时支持多设备间的数据同步和共享。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐