The NOMA AI App: From Python Code to Clinical Device
- Anie Etor-Udofia
- Apr 1
- 3 min read
The User Experience Flow
When a user launches NOMA AI, here's what happens:
Camera Feed: Live preview of the skin lesion (640×480 RGB)
Capture & Analyze: User positions lesion in center, taps the large button
AI Inference: Model processes the 224×224 image (0.3-0.5 seconds on Pi 4)
Clinical Assessment: 7-step ABCDE wizard with swipe navigation
Risk Fusion: Combines AI + ABCDE + patient factors
Result Display: Diagnosis, recommendations, and Grad-CAM heatmap
LED Feedback: Red/Yellow/Green physical indicator
Health Passport: Assessment saved with timestamp
Critical Design Decisions
Why Yellow LED Blinks During Analysis?Users need immediate feedback that the system is working. The yellow blinking pattern (500ms intervals for up to 10 seconds) indicates processing without making them stare at a frozen screen.
Why Swipe Navigation?The clinical assessment wizard has 7 steps. Swipe gestures (with a 100px threshold) let users navigate naturally while preserving touch targets for buttons. The SwipeableWidget class checks whether the touch started on an interactive element (radio button, checkbox) before triggering navigation.
Why Grad-CAM Heatmaps?Trust is critical in medical AI. Grad-CAM highlights which image regions influenced the diagnosis. Red areas = high influence, blue = low influence. This turns the AI from a "black box" into an explainable tool.
Handling Camera Color Formats
The Pi camera can output various formats. The code automatically detects and corrects:
python
# Sample center pixel to detect color order
h, w, _ = frame.shape
sample = frame[h//2, w//2]
if sample[2] > sample[0] + 30: # Blue > Red by threshold
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)This ensures colors display correctly on the touchscreen.
GPIO LED Control with Fallback
The SimpleLED class handles both real hardware and mock mode:
python
def set_led(self, color, state):
if self.gpio_available:
self.GPIO.output(self.led_pins[color], self.GPIO.HIGH if state else self.GPIO.LOW)
else:
print(f"Mock LED {color}: {'ON' if state else 'OFF'}")This allows development without hardware and prevents crashes if GPIO fails.
The Clinical Assessment Wizard
The 7-step wizard walks users through ABCDE criteria:
A - Asymmetry: Is the lesion asymmetrical?
B - Border: Irregular, ragged, or notched?
C - Color: Single color, 2-3 colors, or many?
D - Diameter: Small (<6mm), Medium (6-10mm), Large (>10mm)
E - Evolution: No change, slow change, rapid change?
Patient Information: Age, skin type, risk factors, clinical context
Summary: Review all answers before calculation
Each step includes:
Visual diagrams (drawn with QPainter)
Clear descriptions
Large touch targets (radio buttons with 20px text)
Scroll areas for longer content
Risk Calculation Formula
The final risk score combines three components:
text
Total Risk = (ABCDE_Score / 8.0) × 40
+ (Patient_Score / 4.0) × 20
+ (CNN_Weight × Confidence) × 40Where:
ABCDE_Score: 0-8 points based on responses
Patient_Score: Age (>50 = 1), Skin Type (I/II = 1), Family History (1), Sunburn History (1)
CNN_Weight: 3 for malignant, 1 for benign, 0 for normal
LED Color Mapping:
Red (≥70): High risk - Urgent dermatology referral
Yellow (40-69): Moderate risk - Schedule follow-up within 4-6 weeks
Green (<40): Low risk - Continue self-checks
Health Passport: Longitudinal Tracking
Every assessment saves to health_passport.json:
json
{
"timestamp": "2026-03-28T14:30:00",
"ai_prediction": "Melanoma",
"confidence": 0.87,
"abcde_score": 6,
"patient_score": 3,
"total_risk": 72.5,
"led_color": "RED",
"image_path": null
}This enables trend analysis—users can see if risk scores are improving or worsening over time.
Educational Tip Banner
After each analysis, a random dermatology fact appears:
text
💡 Did you know? Sunscreen with SPF 30+ reduces skin cancer risk by 40-50%.The banner auto-hides after 10 seconds, reinforcing education without cluttering the interface.
Error Handling and Resilience
The app includes several layers of error protection:
Global Exception Handler: All crashes logged to crash_log.txt for debugging
Camera Fallback: If camera fails, dummy frames keep the app running
GPIO Fallback: Mock LED mode if hardware unavailable
Low Confidence Warning: If confidence < 60% or uncertainty > 80%, prompts retake
Service Auto-Restart: Systemd restarts the app if it crashes




Comments