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:
@@ -0,0 +1,17 @@
|
||||
CREATE TABLE IF NOT EXISTS "image_classifications" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"predicted_disease_slug" varchar(80) NOT NULL,
|
||||
"confidence" real NOT NULL,
|
||||
"probabilities" jsonb NOT NULL,
|
||||
"image_url" text NOT NULL,
|
||||
"original_file_name" varchar(240) NOT NULL,
|
||||
"uploader_public_id" varchar(160) NOT NULL,
|
||||
"uploader_payload" jsonb NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "image_classifications" ADD CONSTRAINT "image_classifications_predicted_disease_slug_disease_catalog_slug_fk" FOREIGN KEY ("predicted_disease_slug") REFERENCES "public"."disease_catalog"("slug") ON DELETE no action ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
@@ -0,0 +1,281 @@
|
||||
{
|
||||
"id": "16700e2c-ff8f-4864-a71a-6f4b98a1313a",
|
||||
"prevId": "71e2eeba-4f8f-48bc-8bcf-63201334aa65",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"public.app_events": {
|
||||
"name": "app_events",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar(120)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.disease_catalog": {
|
||||
"name": "disease_catalog",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"slug": {
|
||||
"name": "slug",
|
||||
"type": "varchar(80)",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"label": {
|
||||
"name": "label",
|
||||
"type": "varchar(80)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"common_name": {
|
||||
"name": "common_name",
|
||||
"type": "varchar(120)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"summary": {
|
||||
"name": "summary",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"symptoms": {
|
||||
"name": "symptoms",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"recommendations": {
|
||||
"name": "recommendations",
|
||||
"type": "text[]",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"risk_level": {
|
||||
"name": "risk_level",
|
||||
"type": "varchar(20)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"accent_color": {
|
||||
"name": "accent_color",
|
||||
"type": "varchar(40)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"display_order": {
|
||||
"name": "display_order",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.image_classifications": {
|
||||
"name": "image_classifications",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"predicted_disease_slug": {
|
||||
"name": "predicted_disease_slug",
|
||||
"type": "varchar(80)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"confidence": {
|
||||
"name": "confidence",
|
||||
"type": "real",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"probabilities": {
|
||||
"name": "probabilities",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"image_url": {
|
||||
"name": "image_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"original_file_name": {
|
||||
"name": "original_file_name",
|
||||
"type": "varchar(240)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"uploader_public_id": {
|
||||
"name": "uploader_public_id",
|
||||
"type": "varchar(160)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"uploader_payload": {
|
||||
"name": "uploader_payload",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"image_classifications_predicted_disease_slug_disease_catalog_slug_fk": {
|
||||
"name": "image_classifications_predicted_disease_slug_disease_catalog_slug_fk",
|
||||
"tableFrom": "image_classifications",
|
||||
"tableTo": "disease_catalog",
|
||||
"columnsFrom": [
|
||||
"predicted_disease_slug"
|
||||
],
|
||||
"columnsTo": [
|
||||
"slug"
|
||||
],
|
||||
"onDelete": "no action",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.manual_classifications": {
|
||||
"name": "manual_classifications",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"disease_slug": {
|
||||
"name": "disease_slug",
|
||||
"type": "varchar(80)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"observation": {
|
||||
"name": "observation",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"location": {
|
||||
"name": "location",
|
||||
"type": "varchar(160)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"manual_classifications_disease_slug_disease_catalog_slug_fk": {
|
||||
"name": "manual_classifications_disease_slug_disease_catalog_slug_fk",
|
||||
"tableFrom": "manual_classifications",
|
||||
"tableTo": "disease_catalog",
|
||||
"columnsFrom": [
|
||||
"disease_slug"
|
||||
],
|
||||
"columnsTo": [
|
||||
"slug"
|
||||
],
|
||||
"onDelete": "no action",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {},
|
||||
"schemas": {},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,13 @@
|
||||
"when": 1779458573080,
|
||||
"tag": "0000_harsh_arachne",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "7",
|
||||
"when": 1779461286348,
|
||||
"tag": "0001_cute_lyja",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user