鸿蒙Electron框架下鸿蒙PC——命枢AI生命科学模拟器 - 图片分析AI模块实现与UI设计详解
欢迎加入开源鸿蒙PC社区:
https://harmonypc.csdn.net/
atomgit仓库地址:https://gitcode.com/feng8403000/mingshu_ai


一、功能概述
图片分析AI模块是命枢AI生命科学模拟器的核心功能之一,通过计算机视觉和大语言模型技术,实现基于面部照片的健康评估。该模块包含三个专业分析技能,能够综合评估用户的面部特征、健康状态和生活质量,为用户提供个性化的健康建议。
1.1 功能定位
图片分析AI模块在整体架构中的作用:
| 层级 | 功能 | 说明 |
|---|---|---|
| 输入层 | 图片上传 | 支持用户上传面部照片 |
| 处理层 | 多技能分析 | 并行调用三个AI技能进行综合分析 |
| 输出层 | 综合报告 | 生成详细的健康评估报告 |
| 应用层 | 健康建议 | 提供个性化健康指导 |
1.2 核心特性
- 多技能协同分析:同时调用三个AI技能进行综合诊断
- 视觉AI能力:支持图片输入,通过视觉模型进行分析
- 实时进度显示:展示各技能的分析进度和状态
- 综合评分系统:生成1-100分的生活质量评分
- 个性化建议:根据分析结果提供针对性健康建议
1.3 三大核心技能
| 技能 | 功能 | 分析内容 |
|---|---|---|
| ImageDiagnosisSkill | 图片诊断 | 年龄预估、表情分析、肤色气色、健康等级 |
| FaceFeatureSkill | 面部特征 | 脸型、眼睛状态、鼻型、嘴唇状态、皮肤类型等 |
| FaceHealthSkill | 面部健康 | 疲劳程度、水分状态、皮肤弹性、健康问题识别 |
二、UI设计详解
2.1 整体布局
AI图片问诊采用模态框设计,包含以下区域:
┌─────────────────────────────────────────────┐
│ 🖼️ AI图片问诊 │
├─────────────────────────────────────────────┤
│ [图片预览区域] │
│ ┌─────────────────────────────────────┐ │
│ │ │ │
│ │ 上传的面部照片 │ │
│ │ │ │
│ └─────────────────────────────────────┘ │
├─────────────────────────────────────────────┤
│ [分析进度区域] │
│ 🖼️ ImageDiagnosisSkill 正在分析... │
│ 👤 FaceFeatureSkill 正在分析... │
│ 💚 FaceHealthSkill 正在分析... │
├─────────────────────────────────────────────┤
│ [分析结果区域] │
│ 📊 综合分析报告 │
│ ┌─────────────────────────────────────┐ │
│ │ 👤 基本信息 │ │
│ │ 🎂 预估年龄: 25-30岁 │ │
│ │ 👥 性别: 未知 │ │
│ │ 🔷 脸型: 椭圆形 │ │
│ │ 😊 表情状态: 自信、平静、精神 │ │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ 🧬 面部特征 │ │
│ │ 👀 眼睛状态: 正常 │ │
│ │ 👃 鼻型: 中等 │ │
│ │ 👄 嘴唇状态: 红润 │ │
│ │ 🧴 皮肤类型: 中性 │ │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ 💚 健康评估 │ │
│ │ 综合健康评分: 85 │ │
│ │ 🎨 肤色气色: 均匀 │ │
│ │ 💧 水分状态: 适中 │ │
│ │ 😴 疲劳程度: 轻度 │ │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ ⚠️ 需要关注的问题 │ │
│ │ ⚡ 建议保证充足睡眠 │ │
│ │ ⚡ 注意补水保湿 │ │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ 💡 健康建议 │ │
│ │ 1. 每天保持7-8小时睡眠 │ │
│ │ 2. 多喝水补充水分 │ │
│ │ 3. 适当运动促进血液循环 │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
2.2 核心组件设计
2.2.1 图片上传区域
上传区域采用拖拽风格设计:
<div class="diagnosis-upload-area" id="diagnosisUploadArea">
<span style="font-size: 48px;">📷</span>
<span>点击上传面部照片</span>
</div>
<input type="file" id="diagnosisImageUpload" accept="image/*" style="display: none;">
样式设计:
.diagnosis-upload-area {
border: 2px dashed rgba(255, 255, 255, 0.2);
border-radius: 12px;
padding: 40px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
margin-bottom: 20px;
}
.diagnosis-upload-area:hover {
border-color: #4ecdc4;
background: rgba(78, 205, 196, 0.1);
}
2.2.2 图片预览
图片预览区域展示上传的照片:
<img id="diagnosisImagePreview" src="" alt="预览">
#diagnosisImagePreview {
width: 100%;
border-radius: 8px;
margin-bottom: 15px;
display: none;
}
2.2.3 分析进度显示
实时展示三个技能的分析状态:
<div id="imageSkillProgress">
<div class="skill-item" id="imageSkill1">
<span class="skill-icon">🖼️</span>
<span class="skill-name">ImageDiagnosisSkill</span>
<span class="skill-status" id="imageStatus1">等待中...</span>
</div>
<div class="skill-item" id="imageSkill2">
<span class="skill-icon">👤</span>
<span class="skill-name">FaceFeatureSkill</span>
<span class="skill-status" id="imageStatus2">等待中...</span>
</div>
<div class="skill-item" id="imageSkill3">
<span class="skill-icon">💚</span>
<span class="skill-name">FaceHealthSkill</span>
<span class="skill-status" id="imageStatus3">等待中...</span>
</div>
</div>
状态样式:
.skill-item {
display: flex;
align-items: center;
padding: 8px 10px;
margin: 5px 0;
background: rgba(255, 255, 255, 0.05);
border-radius: 6px;
}
.skill-status {
font-size: 12px;
padding: 3px 8px;
border-radius: 10px;
background: rgba(255, 255, 255, 0.1);
color: #ccc;
}
.skill-status.running {
background: #f39c12;
color: #1a1a2e;
}
.skill-status.completed {
background: #27ae60;
color: #fff;
}
.skill-status.failed {
background: #e74c3c;
color: #fff;
}
2.2.4 分析结果卡片
结果展示采用卡片式布局,分为多个区域:
.diagnosis-result-section {
background: rgba(255, 255, 255, 0.03);
border-radius: 10px;
padding: 12px;
margin-bottom: 12px;
}
.diagnosis-section-title {
color: #fdcb6e;
font-weight: bold;
margin-bottom: 10px;
font-size: 14px;
}
.diagnosis-result-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.diagnosis-result-item {
background: rgba(255, 255, 255, 0.05);
padding: 10px;
border-radius: 8px;
}
.diagnosis-result-label {
color: #888;
font-size: 11px;
margin-bottom: 4px;
}
.diagnosis-result-value {
color: #fff;
font-weight: bold;
font-size: 13px;
}
2.2.5 健康评分展示
综合健康评分采用大字体突出显示:
.diagnosis-health-score {
text-align: center;
padding: 15px;
background: rgba(78, 205, 196, 0.1);
border-radius: 10px;
margin-bottom: 10px;
}
.health-score-label {
color: #888;
font-size: 12px;
margin-bottom: 5px;
}
.health-score-value {
font-size: 32px;
font-weight: bold;
margin-bottom: 8px;
}
.health-score-bar {
width: 100%;
height: 8px;
background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
overflow: hidden;
}
.health-score-fill {
height: 100%;
border-radius: 4px;
transition: width 0.5s ease;
}
2.2.6 关注问题和建议区域
.diagnosis-concerns {
background: rgba(231, 76, 60, 0.1);
border-radius: 8px;
padding: 10px;
}
.diagnosis-concern-item {
color: #e74c3c;
padding: 5px 0;
font-size: 13px;
}
.diagnosis-suggestions {
background: rgba(78, 205, 196, 0.1);
border-radius: 8px;
padding: 10px;
}
.diagnosis-suggestion-item {
color: #4ecdc4;
padding: 5px 0;
font-size: 13px;
}
三、核心代码实现
3.1 ImageDiagnosisSkill - 图片诊断技能
图片诊断技能使用支持视觉输入的AI模型进行分析:
const ImageDiagnosisSkill = (function() {
const API_URL = "https://api-ai.gitcode.com/v1/chat/completions";
const API_KEY = "qBPRwKM_kHgbBjzzxvW9ws--";
async function queryAI(prompt, imageBase64) {
console.log('========== Image Diagnosis AI Request ==========');
console.log('Image size:', imageBase64 ? imageBase64.length : 0, 'bytes');
try {
const response = await fetch(API_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "Qwen/Qwen3.5-35B-A3B",
messages: [{
role: "user",
content: [
{ type: "image_url", image_url: { url: `data:image/jpeg;base64,${imageBase64}` } },
{ type: "text", text: prompt }
]
}],
stream: false,
max_tokens: 1024,
temperature: 0.7,
top_p: 0.95
})
});
console.log('HTTP Status:', response.status);
if (!response.ok) {
const errorText = await response.text();
console.error('HTTP Error:', errorText);
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Raw AI Response:', data);
if (data.choices && data.choices[0] && data.choices[0].message) {
return data.choices[0].message.content;
}
return null;
} catch (error) {
console.error('Image Diagnosis AI Error:', error.message);
throw error;
}
}
function parseResponse(response) {
try {
let jsonStr = response.trim();
const codeBlockMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
if (codeBlockMatch) {
jsonStr = codeBlockMatch[1];
}
const braceStart = jsonStr.indexOf('{');
const braceEnd = jsonStr.lastIndexOf('}');
if (braceStart === -1 || braceEnd === -1) {
throw new Error('No valid JSON found');
}
jsonStr = jsonStr.substring(braceStart, braceEnd + 1);
jsonStr = jsonStr.replace(/,\s*([}\]])/g, '$1');
return JSON.parse(jsonStr);
} catch (error) {
console.error('Parse Error:', error.message);
return generateFallbackResponse();
}
}
function generateFallbackResponse() {
return {
estimatedAge: '未知',
expression: '正常',
complexion: '一般',
healthLevel: '一般',
suggestions: ['保持良好作息', '注意饮食健康', '适当进行户外活动']
};
}
async function analyze(imageBase64) {
console.log('Image Diagnosis Skill - analyze called');
const prompt = "请分析这张面部照片,评估人物的健康状态。请以JSON格式返回,包含以下字段:estimatedAge(预估年龄)、expression(表情分析,如:疲劳、精神、焦虑等)、complexion(肤色气色评估)、healthLevel(健康等级:优秀、良好、一般、较差)、suggestions(健康建议数组)。";
const response = await queryAI(prompt, imageBase64);
if (!response) {
return generateFallbackResponse();
}
return parseResponse(response);
}
return {
analyze: analyze,
generateFallbackResponse: generateFallbackResponse
};
})();
关键技术点:
- 使用Qwen/Qwen3.5-35B-A3B模型支持图片输入
- 将图片转换为Base64格式发送
- 构造包含图片URL和文本提示的请求体
3.2 FaceFeatureSkill - 面部特征分析技能
面部特征分析技能提取详细的面部特征信息:
const FaceFeatureSkill = (function() {
const API_URL = "https://api-ai.gitcode.com/v1/chat/completions";
const API_KEY = "qBPRwKM_kHgbBjzzxvW9ws--";
async function queryAI(prompt, imageData) {
try {
const response = await fetch(API_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "deepseek-ai/DeepSeek-V3",
messages: [{
role: "user",
content: prompt
}],
stream: false,
max_tokens: 1024,
temperature: 0.5,
top_p: 0.95
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.choices && data.choices[0] && data.choices[0].message) {
return data.choices[0].message.content;
}
return null;
} catch (error) {
console.error('Face Feature AI Error:', error.message);
throw error;
}
}
function parseResponse(response) {
try {
let jsonStr = response.trim();
const codeBlockMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
if (codeBlockMatch) {
jsonStr = codeBlockMatch[1];
}
const braceStart = jsonStr.indexOf('{');
const braceEnd = jsonStr.lastIndexOf('}');
if (braceStart === -1 || braceEnd === -1) {
throw new Error('No valid JSON found');
}
jsonStr = jsonStr.substring(braceStart, braceEnd + 1);
jsonStr = jsonStr.replace(/,\s*([}\]])/g, '$1');
return JSON.parse(jsonStr);
} catch (error) {
console.error('Face Feature Parse Error:', error.message);
return generateFallbackResponse();
}
}
async function analyze(imageData) {
console.log('Face Feature Skill - analyzing image');
const prompt = `你是一位专业的面部特征分析专家。请分析用户上传的面部照片,提取详细的面部特征信息。\n\n图片数据已提供。\n\n请以JSON格式返回详细的分析结果,包含以下所有字段:\n- estimatedAge: 预估年龄范围(字符串,如"25-30岁")\n- gender: 性别(男/女/未知)\n- faceShape: 脸型描述(圆形/方形/长形/心形/菱形/椭圆形等)\n- foreheadSize: 额头大小(宽阔/中等/狭窄)\n- eyeState: 眼睛状态详细描述(正常/轻度疲劳/中度疲劳/严重疲劳/黑眼圈/眼袋/充血)\n- eyeDistance: 两眼间距(宽/中等/窄)\n- noseShape: 鼻型(高鼻梁/低鼻梁/中等/蒜头鼻/鹰钩鼻等)\n- lipState: 嘴唇状态(红润/干燥/苍白/发紫)\n- skinType: 皮肤类型(干性/油性/中性/混合性/T区油性)\n- skinTone: 肤色色调(白皙/自然/小麦色/古铜色/暗沉)\n- facialSymmetry: 面部对称性(良好/一般/偏差)\n\n请确保所有字段都是字符串类型,不要使用对象或数组作为字段值。`;
const response = await queryAI(prompt, imageData);
if (!response) {
return generateFallbackResponse();
}
try {
const parsed = parseResponse(response);
return sanitizeResponse(parsed);
} catch (error) {
console.error('Face Feature sanitize error:', error.message);
return generateFallbackResponse();
}
}
function sanitizeResponse(response) {
const fallback = generateFallbackResponse();
return {
estimatedAge: ensureString(response.estimatedAge, fallback.estimatedAge),
gender: ensureString(response.gender, fallback.gender),
faceShape: ensureString(response.faceShape, fallback.faceShape),
foreheadSize: ensureString(response.foreheadSize, fallback.foreheadSize),
eyeState: ensureString(response.eyeState, fallback.eyeState),
eyeDistance: ensureString(response.eyeDistance, fallback.eyeDistance),
noseShape: ensureString(response.noseShape, fallback.noseShape),
lipState: ensureString(response.lipState, fallback.lipState),
skinType: ensureString(response.skinType, fallback.skinType),
skinTone: ensureString(response.skinTone, fallback.skinTone),
facialSymmetry: ensureString(response.facialSymmetry, fallback.facialSymmetry)
};
}
function generateFallbackResponse() {
return {
estimatedAge: '未知',
gender: '未知',
faceShape: '椭圆形',
foreheadSize: '中等',
eyeState: '正常',
eyeDistance: '中等',
noseShape: '中等',
lipState: '红润',
skinType: '中性',
skinTone: '自然',
facialSymmetry: '良好'
};
}
function ensureString(value, fallback) {
if (value === null || value === undefined) return fallback;
if (typeof value === 'string') return value.trim() || fallback;
if (typeof value === 'object') {
try {
return JSON.stringify(value);
} catch {
return fallback;
}
}
return String(value).trim() || fallback;
}
return {
analyze: analyze
};
})();
分析字段说明:
| 字段 | 说明 | 示例值 |
|---|---|---|
| estimatedAge | 预估年龄范围 | “25-30岁” |
| gender | 性别 | “男”、“女”、“未知” |
| faceShape | 脸型 | “椭圆形”、“方形”、“心形” |
| foreheadSize | 额头大小 | “宽阔”、“中等”、“狭窄” |
| eyeState | 眼睛状态 | “正常”、“轻度疲劳”、“黑眼圈” |
| eyeDistance | 两眼间距 | “宽”、“中等”、“窄” |
| noseShape | 鼻型 | “高鼻梁”、“中等”、“蒜头鼻” |
| lipState | 嘴唇状态 | “红润”、“干燥”、“苍白” |
| skinType | 皮肤类型 | “干性”、“油性”、“中性” |
| skinTone | 肤色色调 | “白皙”、“自然”、“暗沉” |
| facialSymmetry | 面部对称性 | “良好”、“一般”、“偏差” |
3.3 FaceHealthSkill - 面部健康分析技能
面部健康分析技能评估整体健康状况:
const FaceHealthSkill = (function() {
const API_URL = "https://api-ai.gitcode.com/v1/chat/completions";
const API_KEY = "qBPRwKM_kHgbBjzzxvW9ws--";
async function queryAI(prompt, imageData) {
try {
const response = await fetch(API_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "deepseek-ai/DeepSeek-V3",
messages: [{
role: "user",
content: prompt
}],
stream: false,
max_tokens: 1024,
temperature: 0.5,
top_p: 0.95
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.choices && data.choices[0] && data.choices[0].message) {
return data.choices[0].message.content;
}
return null;
} catch (error) {
console.error('Face Health AI Error:', error.message);
throw error;
}
}
function parseResponse(response) {
try {
let jsonStr = response.trim();
const codeBlockMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
if (codeBlockMatch) {
jsonStr = codeBlockMatch[1];
}
const braceStart = jsonStr.indexOf('{');
const braceEnd = jsonStr.lastIndexOf('}');
if (braceStart === -1 || braceEnd === -1) {
throw new Error('No valid JSON found');
}
jsonStr = jsonStr.substring(braceStart, braceEnd + 1);
jsonStr = jsonStr.replace(/,\s*([}\]])/g, '$1');
return JSON.parse(jsonStr);
} catch (error) {
console.error('Face Health Parse Error:', error.message);
return generateFallbackResponse();
}
}
function generateFallbackResponse() {
return {
complexion: '正常',
signsOfFatigue: '否',
hydrationLevel: '适中',
overallHealth: '良好',
skinElasticity: '良好',
acneOrMarks: '无',
darkCircles: '无',
puffiness: '无',
concerns: [],
lifeQualityScore: 75,
healthTips: ['保持良好生活习惯', '注意营养均衡', '保证充足睡眠']
};
}
async function analyze(imageData) {
console.log('Face Health Skill - analyzing image');
const prompt = `你是一位专业的面部健康分析专家。请通过面部照片详细分析用户的健康状况,给出全面的健康评估。\n\n图片数据已提供。\n\n请以JSON格式返回详细的健康分析结果,包含以下所有字段:\n- complexion: 肤色气色详细描述(红润/苍白/暗沉/发黄/均匀/不均匀/潮红)\n- signsOfFatigue: 疲劳程度评估(是/否,以及轻度/中度/重度)\n- hydrationLevel: 皮肤水分状态评估(充足/适中/轻度缺水/中度缺水/严重缺水)\n- overallHealth: 整体健康评估(优秀/良好/一般/偏差/较差)\n- skinElasticity: 皮肤弹性(良好/一般/松弛)\n- acneOrMarks: 痘痘或痘印情况(有/无,以及轻微/中等/严重)\n- darkCircles: 黑眼圈情况(无/轻微/中等/严重)\n- puffiness: 面部浮肿情况(无/轻微/中等/明显)\n- concerns: 需要关注的健康问题列表(字符串数组)\n- lifeQualityScore: 生活质量评分(1-100的整数)\n- healthTips: 个性化健康提示(字符串数组)\n\n请确保所有字段类型正确,concerns和healthTips必须是字符串数组。`;
const response = await queryAI(prompt, imageData);
if (!response) {
return generateFallbackResponse();
}
try {
const parsed = parseResponse(response);
return sanitizeResponse(parsed);
} catch (error) {
console.error('Face Health sanitize error:', error.message);
return generateFallbackResponse();
}
}
function sanitizeResponse(response) {
const fallback = generateFallbackResponse();
return {
complexion: ensureString(response.complexion, fallback.complexion),
signsOfFatigue: ensureString(response.signsOfFatigue, fallback.signsOfFatigue),
hydrationLevel: ensureString(response.hydrationLevel, fallback.hydrationLevel),
overallHealth: ensureString(response.overallHealth, fallback.overallHealth),
skinElasticity: ensureString(response.skinElasticity, fallback.skinElasticity),
acneOrMarks: ensureString(response.acneOrMarks, fallback.acneOrMarks),
darkCircles: ensureString(response.darkCircles, fallback.darkCircles),
puffiness: ensureString(response.puffiness, fallback.puffiness),
concerns: ensureArray(response.concerns, fallback.concerns),
lifeQualityScore: ensureNumber(response.lifeQualityScore, fallback.lifeQualityScore),
healthTips: ensureArray(response.healthTips, fallback.healthTips)
};
}
function ensureNumber(value, fallback) {
if (value === null || value === undefined) return fallback;
const num = parseInt(value, 10);
if (isNaN(num)) return fallback;
return Math.max(1, Math.min(100, num));
}
function ensureString(value, fallback) {
if (value === null || value === undefined) return fallback;
if (typeof value === 'string') return value.trim() || fallback;
if (typeof value === 'object') {
try {
return JSON.stringify(value);
} catch {
return fallback;
}
}
return String(value).trim() || fallback;
}
function ensureArray(value, fallback) {
if (value === null || value === undefined) return fallback;
if (Array.isArray(value)) return value;
if (typeof value === 'string') {
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed) ? parsed : fallback;
} catch {
return [value];
}
}
return fallback;
}
return {
analyze: analyze
};
})();
健康评估字段说明:
| 字段 | 说明 | 示例值 |
|---|---|---|
| complexion | 肤色气色 | “红润”、“苍白”、“暗沉”、“均匀” |
| signsOfFatigue | 疲劳程度 | “是,轻度”、“否”、“是,中度” |
| hydrationLevel | 水分状态 | “充足”、“适中”、“轻度缺水” |
| overallHealth | 整体健康 | “优秀”、“良好”、“一般”、“偏差” |
| skinElasticity | 皮肤弹性 | “良好”、“一般”、“松弛” |
| acneOrMarks | 痘痘/痘印 | “无”、“轻微”、“中等”、“严重” |
| darkCircles | 黑眼圈 | “无”、“轻微”、“中等”、“严重” |
| puffiness | 面部浮肿 | “无”、“轻微”、“中等”、“明显” |
| concerns | 关注问题 | [“建议保证充足睡眠”, “注意补水保湿”] |
| lifeQualityScore | 生活质量评分 | 85 |
| healthTips | 健康提示 | [“每天保持7-8小时睡眠”, “多喝水补充水分”] |
3.4 图片上传处理
图片上传和Base64编码处理:
function handleImageUpload(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(e) {
selectedImageData = e.target.result.split(',')[1];
const preview = document.getElementById('diagnosisImagePreview');
const uploadArea = document.getElementById('diagnosisUploadArea');
const analyzeBtn = document.getElementById('diagnosisAnalyzeBtn');
if (preview) {
preview.src = e.target.result;
preview.style.display = 'block';
}
if (uploadArea) uploadArea.style.display = 'none';
if (analyzeBtn) analyzeBtn.style.display = 'block';
};
reader.readAsDataURL(file);
}
处理流程:
- 获取上传的文件
- 使用FileReader读取文件
- 将图片转换为Data URL格式
- 提取Base64编码部分(去掉"data:image/jpeg;base64,"前缀)
- 显示预览并隐藏上传区域
3.5 多技能并行分析
三个技能并行执行,实时更新进度:
async function analyzeImage() {
if (!selectedImageData) return;
const resultArea = document.getElementById('diagnosisImageResult');
const resultContent = document.getElementById('diagnosisImageContent');
const analyzeBtn = document.getElementById('diagnosisAnalyzeBtn');
if (analyzeBtn) analyzeBtn.style.display = 'none';
if (resultArea) resultArea.style.display = 'block';
if (resultContent) resultContent.innerHTML = `
<div class="diagnosis-loading">
<div style="margin-bottom: 15px;">🔍 正在进行面部综合分析...</div>
<div id="imageSkillProgress">
<div class="skill-item" id="imageSkill1">
<span class="skill-icon">🖼️</span>
<span class="skill-name">ImageDiagnosisSkill</span>
<span class="skill-status" id="imageStatus1">等待中...</span>
</div>
<div class="skill-item" id="imageSkill2">
<span class="skill-icon">👤</span>
<span class="skill-name">FaceFeatureSkill</span>
<span class="skill-status" id="imageStatus2">等待中...</span>
</div>
<div class="skill-item" id="imageSkill3">
<span class="skill-icon">💚</span>
<span class="skill-name">FaceHealthSkill</span>
<span class="skill-status" id="imageStatus3">等待中...</span>
</div>
</div>
</div>
<style>/* 样式省略 */</style>
`;
try {
console.log('========== 图片诊断开始 ==========');
const updateStatus = (skillId, status, className) => {
const statusEl = document.getElementById(status);
if (statusEl) {
statusEl.textContent = skillId;
statusEl.className = 'skill-status ' + className;
}
};
updateStatus('正在分析...', 'imageStatus1', 'running');
const imagePromise = ImageDiagnosisSkill.analyze(selectedImageData).then(result => {
updateStatus('✓ 完成', 'imageStatus1', 'completed');
return result;
}).catch(error => {
updateStatus('✗ 失败', 'imageStatus1', 'failed');
throw error;
});
updateStatus('正在分析...', 'imageStatus2', 'running');
const featurePromise = FaceFeatureSkill.analyze(selectedImageData).then(result => {
updateStatus('✓ 完成', 'imageStatus2', 'completed');
return result;
}).catch(error => {
updateStatus('✗ 失败', 'imageStatus2', 'failed');
throw error;
});
updateStatus('正在分析...', 'imageStatus3', 'running');
const healthPromise = FaceHealthSkill.analyze(selectedImageData).then(result => {
updateStatus('✓ 完成', 'imageStatus3', 'completed');
return result;
}).catch(error => {
updateStatus('✗ 失败', 'imageStatus3', 'failed');
throw error;
});
const [imageResult, featureResult, healthResult] = await Promise.all([
imagePromise,
featurePromise,
healthPromise
]);
console.log('图片诊断结果:', imageResult);
console.log('面部特征:', featureResult);
console.log('面部健康:', healthResult);
await new Promise(resolve => setTimeout(resolve, 500));
const combinedResult = combineImageResults(imageResult, featureResult, healthResult);
displayImageResult(combinedResult);
console.log('========== 图片诊断完成 ==========');
} catch (error) {
console.error('图片诊断错误:', error.message);
if (resultContent) {
resultContent.innerHTML = '<div style="color: #e74c3c;">❌ 分析失败:' + error.message + '</div>';
}
}
}
并行执行策略:
- 同时启动三个技能的分析请求
- 使用Promise.all等待所有请求完成
- 实时更新每个技能的状态(等待中→正在分析→完成/失败)
- 所有技能完成后合并结果
3.6 结果合并
合并三个技能的分析结果:
function combineImageResults(image, feature, health) {
return {
estimatedAge: feature.estimatedAge || '未知',
gender: feature.gender || '未知',
faceShape: feature.faceShape || '未知',
foreheadSize: feature.foreheadSize || '中等',
eyeState: feature.eyeState || '正常',
eyeDistance: feature.eyeDistance || '中等',
noseShape: feature.noseShape || '中等',
lipState: feature.lipState || '红润',
skinType: feature.skinType || '中性',
skinTone: feature.skinTone || '自然',
facialSymmetry: feature.facialSymmetry || '良好',
expression: image.expression || '未知',
complexion: health.complexion || image.complexion || '正常',
signsOfFatigue: health.signsOfFatigue || '否',
hydrationLevel: health.hydrationLevel || '适中',
skinElasticity: health.skinElasticity || '良好',
acneOrMarks: health.acneOrMarks || '无',
darkCircles: health.darkCircles || '无',
puffiness: health.puffiness || '无',
healthLevel: health.overallHealth || image.healthLevel || '良好',
lifeQualityScore: health.lifeQualityScore || 75,
concerns: health.concerns && health.concerns.length > 0 ? health.concerns : [],
suggestions: health.healthTips && health.healthTips.length > 0 ? health.healthTips : ['继续保持良好的生活习惯']
};
}
合并策略:
- 面部特征信息优先取FaceFeatureSkill的结果
- 健康状态信息优先取FaceHealthSkill的结果
- 年龄、表情等信息综合三个技能的结果
- 确保所有字段都有默认值
3.7 结果展示
渲染综合分析报告:
function displayImageResult(result) {
const resultContent = document.getElementById('diagnosisImageContent');
if (!resultContent) return;
function getHealthColor(level) {
const colors = {
'优秀': '#27ae60',
'良好': '#4ecdc4',
'一般': '#f39c12',
'偏差': '#e74c3c',
'较差': '#e74c3c',
'疲惫': '#e74c3c',
'正常': '#27ae60',
'干燥': '#f39c12',
'油腻': '#f39c12',
'红润': '#27ae60',
'苍白': '#e74c3c',
'暗沉': '#f39c12',
'发黄': '#f39c12',
'无': '#27ae60',
'轻微': '#f39c12',
'轻度': '#f39c12',
'中等': '#e67e22',
'严重': '#e74c3c',
'明显': '#e74c3c'
};
return colors[level] || '#fff';
}
function getScoreColor(score) {
if (score >= 80) return '#27ae60';
if (score >= 60) return '#4ecdc4';
if (score >= 40) return '#f39c12';
return '#e74c3c';
}
let html = `
<div class="diagnosis-section-header">📊 综合分析报告</div>
<div class="diagnosis-result-section">
<div class="diagnosis-section-title">👤 基本信息</div>
<div class="diagnosis-result-grid">
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">🎂 预估年龄</div>
<div class="diagnosis-result-value">${result.estimatedAge || '未知'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">👥 性别</div>
<div class="diagnosis-result-value">${result.gender || '未知'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">🔷 脸型</div>
<div class="diagnosis-result-value">${result.faceShape || '未知'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">😊 表情状态</div>
<div class="diagnosis-result-value">${result.expression || '未知'}</div>
</div>
</div>
</div>
<div class="diagnosis-result-section">
<div class="diagnosis-section-title">🧬 面部特征</div>
<div class="diagnosis-result-grid">
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">👀 眼睛状态</div>
<div class="diagnosis-result-value" style="color: ${getHealthColor(result.eyeState)}">${result.eyeState || '正常'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">📏 两眼间距</div>
<div class="diagnosis-result-value">${result.eyeDistance || '中等'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">👃 鼻型</div>
<div class="diagnosis-result-value">${result.noseShape || '中等'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">👄 嘴唇状态</div>
<div class="diagnosis-result-value" style="color: ${getHealthColor(result.lipState)}">${result.lipState || '红润'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">🧴 皮肤类型</div>
<div class="diagnosis-result-value">${result.skinType || '中性'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">🎨 肤色色调</div>
<div class="diagnosis-result-value">${result.skinTone || '自然'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">🖐️ 额头大小</div>
<div class="diagnosis-result-value">${result.foreheadSize || '中等'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">⚖️ 面部对称性</div>
<div class="diagnosis-result-value">${result.facialSymmetry || '良好'}</div>
</div>
</div>
</div>
<div class="diagnosis-result-section">
<div class="diagnosis-section-title">💚 健康评估</div>
<div class="diagnosis-health-score">
<div class="health-score-label">综合健康评分</div>
<div class="health-score-value" style="color: ${getScoreColor(result.lifeQualityScore)}">${result.lifeQualityScore || 75}</div>
<div class="health-score-bar">
<div class="health-score-fill" style="width: ${result.lifeQualityScore || 75}%; background: ${getScoreColor(result.lifeQualityScore)};"></div>
</div>
</div>
<div class="diagnosis-result-grid">
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">🎨 肤色气色</div>
<div class="diagnosis-result-value" style="color: ${getHealthColor(result.complexion)}">${result.complexion || '正常'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">💧 水分状态</div>
<div class="diagnosis-result-value" style="color: ${getHealthColor(result.hydrationLevel)}">${result.hydrationLevel || '适中'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">😴 疲劳程度</div>
<div class="diagnosis-result-value" style="color: ${getHealthColor(result.signsOfFatigue)}">${result.signsOfFatigue || '否'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">🧬 皮肤弹性</div>
<div class="diagnosis-result-value" style="color: ${getHealthColor(result.skinElasticity)}">${result.skinElasticity || '良好'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">🔴 痘痘/痘印</div>
<div class="diagnosis-result-value" style="color: ${getHealthColor(result.acneOrMarks)}">${result.acneOrMarks || '无'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">👁️ 黑眼圈</div>
<div class="diagnosis-result-value" style="color: ${getHealthColor(result.darkCircles)}">${result.darkCircles || '无'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">😮 面部浮肿</div>
<div class="diagnosis-result-value" style="color: ${getHealthColor(result.puffiness)}">${result.puffiness || '无'}</div>
</div>
<div class="diagnosis-result-item">
<div class="diagnosis-result-label">📈 健康等级</div>
<div class="diagnosis-result-value" style="color: ${getHealthColor(result.healthLevel)}">${result.healthLevel || '良好'}</div>
</div>
</div>
</div>
`;
if (result.concerns && result.concerns.length > 0) {
html += `
<div class="diagnosis-result-section">
<div class="diagnosis-section-title">⚠️ 需要关注的问题</div>
<div class="diagnosis-concerns">`;
result.concerns.forEach((concern, index) => {
html += `<div class="diagnosis-concern-item">⚡ ${concern}</div>`;
});
html += '</div></div>';
}
if (result.suggestions && result.suggestions.length > 0) {
html += `
<div class="diagnosis-result-section">
<div class="diagnosis-section-title">💡 健康建议</div>
<div class="diagnosis-suggestions">`;
result.suggestions.forEach((suggestion, index) => {
html += `<div class="diagnosis-suggestion-item">${index + 1}. ${suggestion}</div>`;
});
html += '</div></div>';
}
html += `
<style>/* 样式省略 */</style>
`;
resultContent.innerHTML = html;
}
颜色编码规则:
| 状态 | 颜色 | 说明 |
|---|---|---|
| 优秀/良好/正常/红润/无 | #27ae60 绿色 | 健康状态 |
| 一般/轻度/轻微/适中/中等 | #f39c12 橙色 | 中等状态 |
| 偏差/较差/严重/明显/苍白/暗沉 | #e74c3c 红色 | 不良状态 |
四、技术亮点
4.1 视觉AI集成
使用Qwen/Qwen3.5-35B-A3B模型支持图片输入,实现基于面部照片的智能分析:
messages: [{
role: "user",
content: [
{ type: "image_url", image_url: { url: `data:image/jpeg;base64,${imageBase64}` } },
{ type: "text", text: prompt }
]
}]
4.2 多技能并行执行
通过Promise.all实现三个技能的并行调用,提升分析效率:
const [imageResult, featureResult, healthResult] = await Promise.all([
imagePromise,
featurePromise,
healthPromise
]);
4.3 实时进度反馈
动态更新每个技能的分析状态,提升用户体验:
const updateStatus = (skillId, status, className) => {
const statusEl = document.getElementById(status);
if (statusEl) {
statusEl.textContent = skillId;
statusEl.className = 'skill-status ' + className;
}
};
4.4 数据规范化处理
每个技能都包含数据规范化逻辑,确保返回数据格式正确:
function sanitizeResponse(response) {
const fallback = generateFallbackResponse();
return {
complexion: ensureString(response.complexion, fallback.complexion),
signsOfFatigue: ensureString(response.signsOfFatigue, fallback.signsOfFatigue),
// ... 其他字段
};
}
4.5 容错机制
每个技能都有fallback响应,确保即使AI调用失败也能返回默认数据:
function generateFallbackResponse() {
return {
estimatedAge: '未知',
expression: '正常',
complexion: '一般',
healthLevel: '一般',
suggestions: ['保持良好作息', '注意饮食健康', '适当进行户外活动']
};
}
五、工作流程总结
5.1 图片分析流程
用户上传面部照片
↓
转换为Base64编码
↓
点击"开始分析"
↓
并行调用三个AI技能
↓
实时更新进度状态
↓
合并分析结果
↓
渲染综合报告
5.2 技能协作关系
┌───────────────────────────────────────────────────────────┐
│ 用户上传图片 │
└───────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ 并行执行三个技能 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ImageDiagnosis │ │FaceFeature │ │
│ │ Skill │ │ Skill │ │
│ │ - 年龄预估 │ │ - 脸型识别 │ │
│ │ - 表情分析 │ │ - 眼睛状态 │ │
│ │ - 肤色评估 │ │ - 鼻型分析 │ │
│ │ - 健康等级 │ │ - 嘴唇状态 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ FaceHealth Skill │ │
│ │ - 疲劳程度评估 │ │
│ │ - 水分状态分析 │ │
│ │ - 皮肤弹性评估 │ │
│ │ - 痘痘/黑眼圈检测 │ │
│ │ - 生活质量评分 │ │
│ └─────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ 合并分析结果 │
│ - 基本信息:年龄、性别、脸型、表情 │
│ - 面部特征:眼睛、鼻型、嘴唇、皮肤 │
│ - 健康评估:疲劳、水分、弹性、评分 │
│ - 关注问题:需要注意的健康问题 │
│ - 健康建议:个性化健康指导 │
└───────────────────────────────────────────────────────────┘
六、总结
图片分析AI模块是命枢AI生命科学模拟器的创新功能,通过计算机视觉技术实现面部健康评估。系统具有以下特点:
- 多模态输入:支持图片输入,结合视觉AI进行分析
- 多技能协同:三个专业技能并行分析,提供全面评估
- 实时反馈:动态展示分析进度,提升用户体验
- 智能数据处理:完善的数据规范化和容错机制
- 可视化报告:美观的分析报告展示,包含颜色编码
该模块为用户提供了一种新颖的健康评估方式,通过上传面部照片即可获得全面的健康分析报告和个性化建议,是AI技术在健康领域的创新应用。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)