feat: implement backend image classification with TensorFlow.js model

- Extend shared types for image classification, including PredictionProbability, UploaderMetadata, and ImageClassificationRecord.
- Create image_classifications table in the database with necessary fields and foreign key constraints.
- Implement disease mappers to convert database rows to shared disease records.
- Develop uploader client to handle image uploads to external service.
- Create image model service to load and classify images using TensorFlow.js.
- Add API routes for image classification, including GET for history and POST for new classifications.
- Implement frontend components for image classification form and display results.
- Update dashboard to integrate image classification functionality and display results.
- Document implementation plan for backend image classification.
This commit is contained in:
Asep Haryana Saputra
2026-05-22 15:13:22 +00:00
parent 229db82a08
commit 15c6be9e84
19 changed files with 1750 additions and 33 deletions
+15 -1
View File
@@ -1,4 +1,4 @@
import { pgTable, timestamp, uuid, varchar, text, integer } from 'drizzle-orm/pg-core';
import { pgTable, timestamp, uuid, varchar, text, integer, jsonb, real } from 'drizzle-orm/pg-core';
export const appEvents = pgTable('app_events', {
id: uuid('id').primaryKey().defaultRandom(),
@@ -30,3 +30,17 @@ export const manualClassifications = pgTable('manual_classifications', {
location: varchar('location', { length: 160 }).notNull(),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
});
export const imageClassifications = pgTable('image_classifications', {
id: uuid('id').primaryKey().defaultRandom(),
predictedDiseaseSlug: varchar('predicted_disease_slug', { length: 80 })
.notNull()
.references(() => diseaseCatalog.slug),
confidence: real('confidence').notNull(),
probabilities: jsonb('probabilities').notNull(),
imageUrl: text('image_url').notNull(),
originalFileName: varchar('original_file_name', { length: 240 }).notNull(),
uploaderPublicId: varchar('uploader_public_id', { length: 160 }).notNull(),
uploaderPayload: jsonb('uploader_payload').notNull(),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
});