An end-to-end MLOps pipeline for detecting concrete structural cracks using deep learning (ResNet and MobileNet) with PyTorch, Airflow for orchestration, and MLflow for experiment tracking. In addition, we support
As the recent earthquake in Thailand caused significant structural damage, particularly to high-rise buildings which led to widespread concrete cracking and breakage. Therefore, the need for efficient and reliable damage assessment has become more critical than ever. Structural defects such as cracks and spalling not only undermine the integrity of infrastructure but also pose serious risks to public safety if not detected and repaired promptly
This project proposes an AI-powered defect detection system that leverages deep learning to automate the identification and localization of structural damage from images. By utilizing pre-trained models such as ResNet, EfficientNet and MobileNetV3. The system classifies images as either cracked or non-cracked and applies object detection techniques for precise localization. This approach not only improves the speed and accuracy of structural assessments but also supports engineers and decision-makers in prioritizing repairs, ultimately enhancing infrastructure resilience after natural disasters.
In order to implement this project, we use the dataset from Kaggle (URL: https://www.kaggle.com/datasets/aniruddhsharmastructural-defects-network-concrete-crack-images). This dataset is called "Structural Defects Network (SDNET) 2018".
- Python >= 3.10
- Docker + Docker Compose
- Optional: Virtualenv or conda
Windows
python -m venv env
.\env\Scripts\activatemacOS/Linux
python -m venv env
source env/bin/activatepip install -r requirements.txtRun the preprocessing script before training or evaluation:
python src/preprocess_set_seed.pyAfter running the preprocessing script: The train, test, and validation datasets will be saved inside the artifact_folder/ directory. The artifact_folder/ is excluded from version control and will not be uploaded to Git (as specified in .gitignore).
Structural-Defects-Network-MLOps/
βββ Dataset/ # Raw Data (Decks, Walls, Pavements)
βββ airflow/
β βββ dags/ # Airflow DAGs and Python callables
β β βββ main_dag.py
β β βββ callables/ # All python callables function in main dag
β βββ config/ # airflow.cfg and other configs
β βββ plugins/ # Airflow plugins (if needed)
| βββ mlflow/ # MLflow artifacts folder (will be created after run)
| βββ model/ # local shared volume for saving models
β βββ logs/ # Airflow logs
β βββ Dockerfile # Custom Image for this project
β βββ docker-compose.yaml # Docker Compose for Airflow stack
βββ artifact_folder/ # Preprocessed datasets (train/val/test) β auto-generated after preprocessing
βββ src/ # CLI scripts for local training or upload
β βββ scripts/ # All extra python scripts
β βββ preprocess_set_seed.py # preprocessing scripts to run before using jupyter notebooks
β βββ MobileNetV3.ipynb # MobileNetv3 training steps
β βββ resnet.ipynb # ResNet18 training steps
β βββ docker-compose.yaml # Docker Compose for Airflow stack
βββ model/ # Saved PyTorch model files # Airflow and pipeline logs
βββ requirements.txt
βββ README.mdRun this step before training:
python src/preprocess_set_seed.pyThis will generate train/, val/, and test/ image folders + CSVs under artifact_folder/.
Create a .env in the airflow folder root airflow/:
AIRFLOW_UID=50000
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_key
CLOUDINARY_API_SECRET=your_secret
DATASET_PATH=<path>/<to>/your/projectStructural-Defects-Network-MLOps\Dataset
MLFLOW_TRACKING_URI=http://mlflow:5000| Reminder: this dataset path should be absolute path.
cd airflow
docker compose up -d --buildAirflow UI β http://localhost:8080 MLFlow UI -> http://localhost:5000
Username / Password: airflow / airflow
With this airflow and mlflow, you can run whole our Structural Defect Machine Learning Pipeline in our airflow and monitor model performance and parameters in MLFlow instantly.
docker compose down --volumes --rmi allYou can trigger the DAG manually from the Airflow UI, or let it run based on the monthly schedule (@weekly).
It checks:
- If new images have been uploaded to Cloudinary (e.g. under
Users/Cracked/,Users/Non-cracked/) - If >=10 new images are found β preprocess β train β log to MLflow
- Otherwise β skip training
-
The dataset must follow this structure:
Dataset/ βββ Decks/ βββ Pavements/ βββ Walls/ -
Preprocessing includes augmentation, resizing, and denoising filters.
-
Models are saved to
/opt/airflow/model/and registered via MLflow. -
Metrics are saved using XCom and optionally pushed to Airflow Variables.
This project includes a simple React-based frontend web app that enables:
- π Uploading images for real-time prediction (Cracked / Non-cracked)
- π§ Model inference using the latest trained model (ResNet or MobileNet)
- π€ Submitting images with labels for continuous learning
app/
βββ templates/
βββ demo_run.ipynb # Contains REACT_APP_API_URL
βββ Dockerfile
βββ main.py
βββ requirements.txt- Navigate to the frontend directory:
cd app- Build the docker image
docker build . --tag 'structure_prediction_ui'- Run the docker image and access the web
docker run -p 8000:8000 structure_prediction_uior use docker compose up --build
- Setup the virtual environment
python -m venv .venv
source .venv/bin/activate- Install the dependencies
pip install -r requirements.txt- Access the website:
mkdir static
fastapi dev main.py
localhost:8000-
Drag-and-Drop Upload or file selector
-
Calls backend API (
/predict) to return:- Predicted label
- Confidence score
-
Option to submit the image to Cloudinary under:
-
Users/Cracked/ -
Users/Non-cracked/ -
Those images will later be retrained during the next Airflow pipeline run
-
The frontend sends an image to a FastAPI
-
The backend:
- Loads the latest model checkpoint
- Applies preprocessing
- Performs a forward pass
- Returns prediction + confidence
-
Optionally, the backend can upload the labeled image to Cloudinary for future training
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
Predicts the class of a user image |
| POST | / |
Predict the class of a user image |
- Navigate to the frontend directory:
cd app- Build the docker image
docker build . --tag 'structure_prediction_ui'- Run the docker image and access the web
docker run -p 8000:8000 structure_prediction_uiAccess the website:
mkdir static
fastapi dev main.py
localhost:8000- Add a history view of past predictions
- Display class probabilities in a bar chart
- Show model version info
