Upload 9 files
Browse files- .gitattributes +0 -34
- README.md +81 -0
- example_inference.py +40 -0
- labels.json +11 -0
- model_config.json +26 -0
- preprocessor_config.json +18 -0
- push_to_hub.py +43 -0
- requirements.txt +4 -0
- resnet50-corrosion-classifier-v1.pth +3 -0
.gitattributes
CHANGED
|
@@ -1,35 +1 @@
|
|
| 1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
*.pth filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
language: en
|
| 3 |
+
license: mit
|
| 4 |
+
tags:
|
| 5 |
+
- image-classification
|
| 6 |
+
- resnet
|
| 7 |
+
- corrosion
|
| 8 |
+
library_name: pytorch
|
| 9 |
+
pipeline_tag: image-classification
|
| 10 |
+
task_categories:
|
| 11 |
+
- image-classification
|
| 12 |
+
dataset: custom
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
# Corrosion Classifier (ResNet50)
|
| 16 |
+
|
| 17 |
+
This repository contains a ResNet50 image classifier trained to detect corrosion types.
|
| 18 |
+
|
| 19 |
+
## Labels
|
| 20 |
+
- crevice_corrosion
|
| 21 |
+
- erosion_corrosion
|
| 22 |
+
- galvanic_corrosion
|
| 23 |
+
- mic_corrosion
|
| 24 |
+
- no_corrosion
|
| 25 |
+
- pitting_corrosion
|
| 26 |
+
- stress_corrosion
|
| 27 |
+
- under_insulation_corrosion
|
| 28 |
+
- uniform_corrosion
|
| 29 |
+
|
| 30 |
+
## Usage (PyTorch)
|
| 31 |
+
|
| 32 |
+
```python
|
| 33 |
+
import torch, json
|
| 34 |
+
from PIL import Image
|
| 35 |
+
from torchvision import transforms
|
| 36 |
+
import timm
|
| 37 |
+
|
| 38 |
+
# Load labels
|
| 39 |
+
labels = ['crevice_corrosion', 'erosion_corrosion', 'galvanic_corrosion', 'mic_corrosion', 'no_corrosion', 'pitting_corrosion', 'stress_corrosion', 'under_insulation_corrosion', 'uniform_corrosion']
|
| 40 |
+
|
| 41 |
+
# Create model
|
| 42 |
+
model = timm.create_model('resnet50', pretrained=False, num_classes=len(labels))
|
| 43 |
+
state = torch.load('resnet50-corrosion-classifier-v1.pth', map_location='cpu')
|
| 44 |
+
missing, unexpected = model.load_state_dict(state, strict=False)
|
| 45 |
+
model.eval()
|
| 46 |
+
|
| 47 |
+
# Preprocess (ImageNet)
|
| 48 |
+
transform = transforms.Compose([
|
| 49 |
+
transforms.Resize(256, interpolation=transforms.InterpolationMode.BICUBIC),
|
| 50 |
+
transforms.CenterCrop(224),
|
| 51 |
+
transforms.ToTensor(),
|
| 52 |
+
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
|
| 53 |
+
])
|
| 54 |
+
|
| 55 |
+
img = Image.open('test.jpg').convert('RGB')
|
| 56 |
+
x = transform(img).unsqueeze(0)
|
| 57 |
+
|
| 58 |
+
with torch.no_grad():
|
| 59 |
+
logits = model(x)
|
| 60 |
+
probs = logits.softmax(dim=1).squeeze().tolist()
|
| 61 |
+
|
| 62 |
+
idx = int(torch.tensor(probs).argmax())
|
| 63 |
+
print(labels[idx], probs[idx])
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
> Note: This is a **generic PyTorch checkpoint** (`.pth`). The public Inference API on the Hub does **not** execute arbitrary PyTorch code. If you want to call this model via the **Inference API**, you must convert it to a supported library format (e.g. `transformers` image-classification) or use your existing **Space** and call it via the Gradio API. See below.
|
| 67 |
+
|
| 68 |
+
## Call via your existing Space (recommended now)
|
| 69 |
+
If your Space works, you can call it programmatically using the Gradio JS Client from Node:
|
| 70 |
+
```js
|
| 71 |
+
import { Client, handle_file } from "@gradio/client";
|
| 72 |
+
|
| 73 |
+
const app = await Client.connect("jacopo22295/RESNET50-CORROSION_CLASSIFIER_V1"); // your Space id
|
| 74 |
+
const res = await fetch("https://example.com/image.jpg");
|
| 75 |
+
const blob = await res.blob();
|
| 76 |
+
const out = await app.predict("/predict", [handle_file(blob)]);
|
| 77 |
+
console.log(out.data);
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
## Convert to Transformers (optional, to use Inference API)
|
| 81 |
+
If you later want to enable the one-click Inference API, consider exporting to a `transformers` ImageClassification model (e.g. `ResNetForImageClassification`) and pushing weights + `preprocessor_config.json`. This requires a small conversion script.
|
example_inference.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from PIL import Image
|
| 3 |
+
from torchvision import transforms
|
| 4 |
+
import timm, json
|
| 5 |
+
|
| 6 |
+
labels = [
|
| 7 |
+
'crevice_corrosion',
|
| 8 |
+
'erosion_corrosion',
|
| 9 |
+
'galvanic_corrosion',
|
| 10 |
+
'mic_corrosion',
|
| 11 |
+
'no_corrosion',
|
| 12 |
+
'pitting_corrosion',
|
| 13 |
+
'stress_corrosion',
|
| 14 |
+
'under_insulation_corrosion',
|
| 15 |
+
'uniform_corrosion'
|
| 16 |
+
]
|
| 17 |
+
|
| 18 |
+
model = timm.create_model('resnet50', pretrained=False, num_classes=len(labels))
|
| 19 |
+
state = torch.load('resnet50-corrosion-classifier-v1.pth', map_location='cpu')
|
| 20 |
+
model.load_state_dict(state, strict=False)
|
| 21 |
+
model.eval()
|
| 22 |
+
|
| 23 |
+
transform = transforms.Compose([
|
| 24 |
+
transforms.Resize(256, interpolation=transforms.InterpolationMode.BICUBIC),
|
| 25 |
+
transforms.CenterCrop(224),
|
| 26 |
+
transforms.ToTensor(),
|
| 27 |
+
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
|
| 28 |
+
])
|
| 29 |
+
|
| 30 |
+
def predict(path):
|
| 31 |
+
img = Image.open(path).convert('RGB')
|
| 32 |
+
x = transform(img).unsqueeze(0)
|
| 33 |
+
with torch.no_grad():
|
| 34 |
+
probs = model(x).softmax(dim=1).squeeze().tolist()
|
| 35 |
+
idx = int(torch.tensor(probs).argmax())
|
| 36 |
+
return labels[idx], probs[idx]
|
| 37 |
+
|
| 38 |
+
if __name__ == "__main__":
|
| 39 |
+
import sys
|
| 40 |
+
print(predict(sys.argv[1] if len(sys.argv)>1 else "test.jpg"))
|
labels.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
"crevice_corrosion",
|
| 3 |
+
"erosion_corrosion",
|
| 4 |
+
"galvanic_corrosion",
|
| 5 |
+
"mic_corrosion",
|
| 6 |
+
"no_corrosion",
|
| 7 |
+
"pitting_corrosion",
|
| 8 |
+
"stress_corrosion",
|
| 9 |
+
"under_insulation_corrosion",
|
| 10 |
+
"uniform_corrosion"
|
| 11 |
+
]
|
model_config.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"arch": "resnet50",
|
| 3 |
+
"num_labels": 9,
|
| 4 |
+
"labels": {
|
| 5 |
+
"0": "crevice_corrosion",
|
| 6 |
+
"1": "erosion_corrosion",
|
| 7 |
+
"2": "galvanic_corrosion",
|
| 8 |
+
"3": "mic_corrosion",
|
| 9 |
+
"4": "no_corrosion",
|
| 10 |
+
"5": "pitting_corrosion",
|
| 11 |
+
"6": "stress_corrosion",
|
| 12 |
+
"7": "under_insulation_corrosion",
|
| 13 |
+
"8": "uniform_corrosion"
|
| 14 |
+
},
|
| 15 |
+
"image_size": 224,
|
| 16 |
+
"mean": [
|
| 17 |
+
0.485,
|
| 18 |
+
0.456,
|
| 19 |
+
0.406
|
| 20 |
+
],
|
| 21 |
+
"std": [
|
| 22 |
+
0.229,
|
| 23 |
+
0.224,
|
| 24 |
+
0.225
|
| 25 |
+
]
|
| 26 |
+
}
|
preprocessor_config.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"do_resize": true,
|
| 3 |
+
"size": 256,
|
| 4 |
+
"resample": "bicubic",
|
| 5 |
+
"do_center_crop": true,
|
| 6 |
+
"crop_size": 224,
|
| 7 |
+
"do_normalize": true,
|
| 8 |
+
"image_mean": [
|
| 9 |
+
0.485,
|
| 10 |
+
0.456,
|
| 11 |
+
0.406
|
| 12 |
+
],
|
| 13 |
+
"image_std": [
|
| 14 |
+
0.229,
|
| 15 |
+
0.224,
|
| 16 |
+
0.225
|
| 17 |
+
]
|
| 18 |
+
}
|
push_to_hub.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Push this folder to the Hugging Face Model Hub
|
| 2 |
+
# Usage:
|
| 3 |
+
# pip install huggingface_hub
|
| 4 |
+
# export HF_TOKEN=hf_xxx # or run `huggingface-cli login`
|
| 5 |
+
# python push_to_hub.py --repo jacopo22295/RESNET50-CORROSION_CLASSIFIER_V1
|
| 6 |
+
|
| 7 |
+
import argparse, os
|
| 8 |
+
from huggingface_hub import HfApi, create_repo, upload_file
|
| 9 |
+
|
| 10 |
+
def main():
|
| 11 |
+
ap = argparse.ArgumentParser()
|
| 12 |
+
ap.add_argument("--repo", required=True, help="repo id like user/name")
|
| 13 |
+
ap.add_argument("--private", action="store_true", help="create as private")
|
| 14 |
+
args = ap.parse_args()
|
| 15 |
+
|
| 16 |
+
api = HfApi()
|
| 17 |
+
create_repo(args.repo, repo_type="model", exist_ok=True, private=args.private)
|
| 18 |
+
|
| 19 |
+
base = os.path.dirname(__file__)
|
| 20 |
+
files = [
|
| 21 |
+
"resnet50-corrosion-classifier-v1.pth",
|
| 22 |
+
"README.md",
|
| 23 |
+
"model_config.json",
|
| 24 |
+
"preprocessor_config.json",
|
| 25 |
+
"requirements.txt",
|
| 26 |
+
"labels.json"
|
| 27 |
+
]
|
| 28 |
+
|
| 29 |
+
for f in files:
|
| 30 |
+
path = os.path.join(base, f)
|
| 31 |
+
if not os.path.exists(path):
|
| 32 |
+
raise FileNotFoundError(path)
|
| 33 |
+
print("Uploading", f)
|
| 34 |
+
upload_file(
|
| 35 |
+
path_or_fileobj=path,
|
| 36 |
+
path_in_repo=f,
|
| 37 |
+
repo_id=args.repo,
|
| 38 |
+
repo_type="model"
|
| 39 |
+
)
|
| 40 |
+
print("Done. Visit https://huggingface.co/" + args.repo)
|
| 41 |
+
|
| 42 |
+
if __name__ == "__main__":
|
| 43 |
+
main()
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch>=2.1
|
| 2 |
+
torchvision>=0.16
|
| 3 |
+
timm>=0.9.16
|
| 4 |
+
Pillow>=9.5
|
resnet50-corrosion-classifier-v1.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d78dbd07f779eae5be45fc791877c63ca1e86e61978fd74c959b4adb55b8053a
|
| 3 |
+
size 94426479
|