diff --git a/01.train_ODC.ipynb b/01.train_ODC.ipynb index 13dcec7..56176b0 100644 --- a/01.train_ODC.ipynb +++ b/01.train_ODC.ipynb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:549bf41a29b39a583c9ac1a2f08283b7494bcd521f8b6b5aff1fa7f5f0ca1cab -size 919988 +oid sha256:dd3fecbef4c80ff1bd20922e6b2250d94ac05e55c3a2efbff4da20fcea3d739f +size 39812 diff --git a/01.train_ODC_local_with_Mic_supplyer.ipynb b/01.train_ODC_local_with_Mic_supplyer.ipynb new file mode 100644 index 0000000..dd99e43 --- /dev/null +++ b/01.train_ODC_local_with_Mic_supplyer.ipynb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89c347e98288e77ddb7579d4cfa2b49924a993f7173a2d12155ef7a1893082b1 +size 163627 diff --git a/api_server.py b/api_server.py new file mode 100644 index 0000000..44e5dd2 --- /dev/null +++ b/api_server.py @@ -0,0 +1,256 @@ +""" +API Server for Land Classification Model Training +Cho phép chọn dữ liệu và cấu hình training qua giao diện web +""" + +from fastapi import FastAPI, BackgroundTasks, HTTPException +from fastapi.middleware.cors import CORSMiddleware +from fastapi.staticfiles import StaticFiles +from fastapi.responses import HTMLResponse, FileResponse +from pydantic import BaseModel +from typing import Optional, List +import uvicorn +import joblib +import json +from datetime import datetime +from pathlib import Path +import sys + +app = FastAPI(title="Land Classification Training API", version="1.0.0") + +# Enable CORS +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +# Global training status +training_status = { + "is_training": False, + "progress": "", + "error": None, + "result": None, + "start_time": None, + "end_time": None +} + + +class TrainingConfig(BaseModel): + """Cấu hình training""" + # Khu vực (bbox) + min_lon: float = 105.6 + min_lat: float = 9.3 + max_lon: float = 106.2 + max_lat: float = 9.8 + + # Thời gian + start_date: str = "2023-03-01" + end_date: str = "2023-05-31" + + # Dữ liệu + max_scenes: int = 12 + cloud_cover: int = 30 + resolution: int = 20 # 10m hoặc 20m + + # Model parameters + n_estimators: int = 100 + max_depth: int = 20 + learning_rate: float = 0.1 + use_gpu: bool = True + + # Training data + training_shapefile: str = "train/ST_training data_updated_1130points_new.shp" + + +class TrainingStatus(BaseModel): + """Trạng thái training""" + is_training: bool + progress: str + error: Optional[str] + result: Optional[dict] + start_time: Optional[str] + end_time: Optional[str] + + +@app.get("/", response_class=HTMLResponse) +async def root(): + """Serve giao diện web""" + html_file = Path(__file__).parent / "training_interface.html" + if html_file.exists(): + return FileResponse(html_file) + else: + return HTMLResponse(""" + +
API Documentation: /docs
+Training Interface: Tạo file training_interface.html
+ + + """) + + +@app.get("/api/config/presets") +async def get_presets(): + """Lấy các preset cấu hình sẵn""" + return { + "presets": [ + { + "name": "PC - Nhỏ (3 tháng, 20m, 12 scenes)", + "config": { + "min_lon": 105.6, "min_lat": 9.3, "max_lon": 106.2, "max_lat": 9.8, + "start_date": "2023-03-01", "end_date": "2023-05-31", + "max_scenes": 12, "cloud_cover": 30, "resolution": 20 + } + }, + { + "name": "Server - Trung bình (6 tháng, 10m, 30 scenes)", + "config": { + "min_lon": 105.5, "min_lat": 9.2, "max_lon": 106.4, "max_lat": 10.0, + "start_date": "2023-01-01", "end_date": "2023-06-30", + "max_scenes": 30, "cloud_cover": 30, "resolution": 10 + } + }, + { + "name": "Full - Lớn (1 năm, 10m, 60 scenes)", + "config": { + "min_lon": 105.5, "min_lat": 9.2, "max_lon": 106.4, "max_lat": 10.0, + "start_date": "2022-09-01", "end_date": "2023-10-01", + "max_scenes": 60, "cloud_cover": 50, "resolution": 10 + } + } + ] + } + + +@app.get("/api/training/status", response_model=TrainingStatus) +async def get_training_status(): + """Kiểm tra trạng thái training""" + return training_status + + +@app.post("/api/training/start") +async def start_training(config: TrainingConfig, background_tasks: BackgroundTasks): + """Bắt đầu training với config đã chọn""" + global training_status + + if training_status["is_training"]: + raise HTTPException(status_code=400, detail="Training đang chạy, vui lòng đợi") + + # Reset status + training_status = { + "is_training": True, + "progress": "Đang khởi tạo...", + "error": None, + "result": None, + "start_time": datetime.now().isoformat(), + "end_time": None + } + + # Run training in background + background_tasks.add_task(run_training, config) + + return {"message": "Training đã bắt đầu", "status": training_status} + + +@app.post("/api/training/stop") +async def stop_training(): + """Dừng training (nếu đang chạy)""" + global training_status + training_status["is_training"] = False + training_status["error"] = "Đã dừng bởi người dùng" + training_status["end_time"] = datetime.now().isoformat() + return {"message": "Training đã dừng"} + + +@app.get("/api/models/list") +async def list_models(): + """Liệt kê các model đã train""" + model_dir = Path("model_train") + if not model_dir.exists(): + return {"models": []} + + models = [] + for model_file in model_dir.glob("*.joblib"): + info_file = model_file.with_suffix('.json') + info = {} + if info_file.exists(): + with open(info_file) as f: + info = json.load(f) + + models.append({ + "filename": model_file.name, + "created": datetime.fromtimestamp(model_file.stat().st_mtime).isoformat(), + "size_mb": round(model_file.stat().st_size / 1024 / 1024, 2), + "info": info + }) + + # Sort by creation time (newest first) + models.sort(key=lambda x: x["created"], reverse=True) + return {"models": models} + + +async def run_training(config: TrainingConfig): + """Chạy training process""" + global training_status + + try: + training_status["progress"] = "Đang import thư viện..." + + # Import training module + from train_module import train_model + + training_status["progress"] = "Đang load dữ liệu Sentinel-2..." + + # Run training + result = train_model( + bbox=[config.min_lon, config.min_lat, config.max_lon, config.max_lat], + time_range=f"{config.start_date}/{config.end_date}", + max_scenes=config.max_scenes, + cloud_cover=config.cloud_cover, + resolution=config.resolution, + training_shapefile=config.training_shapefile, + n_estimators=config.n_estimators, + max_depth=config.max_depth, + learning_rate=config.learning_rate, + use_gpu=config.use_gpu, + status_callback=lambda msg: update_progress(msg) + ) + + training_status["is_training"] = False + training_status["progress"] = "Hoàn thành!" + training_status["result"] = result + training_status["end_time"] = datetime.now().isoformat() + + except Exception as e: + training_status["is_training"] = False + training_status["error"] = str(e) + training_status["progress"] = f"Lỗi: {str(e)}" + training_status["end_time"] = datetime.now().isoformat() + import traceback + print(traceback.format_exc()) + + +def update_progress(message: str): + """Cập nhật progress message""" + global training_status + training_status["progress"] = message + print(f"[PROGRESS] {message}") + + +if __name__ == "__main__": + print("=" * 70) + print("🚀 LAND CLASSIFICATION TRAINING API SERVER") + print("=" * 70) + print("\n📍 Endpoints:") + print(" - Web Interface: http://localhost:8000") + print(" - API Docs: http://localhost:8000/docs") + print(" - Start Training: POST http://localhost:8000/api/training/start") + print(" - Check Status: GET http://localhost:8000/api/training/status") + print("\n" + "=" * 70) + + uvicorn.run(app, host="0.0.0.0", port=8000, log_level="info") diff --git a/new_train.ipynb b/new_train.ipynb index 6b2b9f6..b69b7e4 100644 --- a/new_train.ipynb +++ b/new_train.ipynb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c05fa531f6c5e9a79b645bacea70e88e4edce5d1a80f09559e8ee1baec93082 -size 208484 +oid sha256:eb89e36fa4f4c740d5a079baf53b02bec2ef1120ac770bed6b6be4aa9fc99a1b +size 208470 diff --git a/requirements_api.txt b/requirements_api.txt new file mode 100644 index 0000000..c9b6004 --- /dev/null +++ b/requirements_api.txt @@ -0,0 +1,3 @@ +fastapi +uvicorn +pydantic