Spaces:
Runtime error
Runtime error
Commit ·
349dc13
1
Parent(s): 2d4d83d
深皿新モデル(回転させたデータで学習)
Browse files- app.py +20 -1
- configs/fukazara_scoop_black_4.yaml +112 -0
- lightning_inference.py +17 -8
- models/fukazara_scoop_black_4.ckpt +3 -0
- requirements.txt +1 -1
- utils/preprocess.py +8 -0
app.py
CHANGED
|
@@ -23,9 +23,10 @@ else:
|
|
| 23 |
|
| 24 |
if __name__ == "__main__":
|
| 25 |
interface = Interface(
|
| 26 |
-
fn=lambda modelName, image: infer(
|
| 27 |
input=np.array(PILImage.open(image)),
|
| 28 |
suffix=".png",
|
|
|
|
| 29 |
configPath=Path(CONFIGS_PATH + modelName + ".yaml"),
|
| 30 |
weightsPath=Path(MODELS_PATH + modelName + ".ckpt")
|
| 31 |
),
|
|
@@ -37,6 +38,7 @@ if __name__ == "__main__":
|
|
| 37 |
"fukazara_scoop_black",
|
| 38 |
"fukazara_scoop_black_2",
|
| 39 |
"fukazara_scoop_black_3",
|
|
|
|
| 40 |
],
|
| 41 |
label="Model",
|
| 42 |
),
|
|
@@ -45,16 +47,33 @@ if __name__ == "__main__":
|
|
| 45 |
label="Image",
|
| 46 |
file_count="single",
|
| 47 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
],
|
| 49 |
outputs=[
|
| 50 |
Textbox(
|
| 51 |
type="text",
|
| 52 |
label="isAnomaly",
|
| 53 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
Image(
|
| 55 |
type="numpy",
|
| 56 |
label="Result",
|
| 57 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
Image(
|
| 59 |
type="numpy",
|
| 60 |
label="Input",
|
|
|
|
| 23 |
|
| 24 |
if __name__ == "__main__":
|
| 25 |
interface = Interface(
|
| 26 |
+
fn=lambda modelName, image, threshold: infer(
|
| 27 |
input=np.array(PILImage.open(image)),
|
| 28 |
suffix=".png",
|
| 29 |
+
threshold=float(threshold),
|
| 30 |
configPath=Path(CONFIGS_PATH + modelName + ".yaml"),
|
| 31 |
weightsPath=Path(MODELS_PATH + modelName + ".ckpt")
|
| 32 |
),
|
|
|
|
| 38 |
"fukazara_scoop_black",
|
| 39 |
"fukazara_scoop_black_2",
|
| 40 |
"fukazara_scoop_black_3",
|
| 41 |
+
"fukazara_scoop_black_4",
|
| 42 |
],
|
| 43 |
label="Model",
|
| 44 |
),
|
|
|
|
| 47 |
label="Image",
|
| 48 |
file_count="single",
|
| 49 |
),
|
| 50 |
+
Textbox(
|
| 51 |
+
type="text",
|
| 52 |
+
label="Threshold",
|
| 53 |
+
value="0.55",
|
| 54 |
+
),
|
| 55 |
],
|
| 56 |
outputs=[
|
| 57 |
Textbox(
|
| 58 |
type="text",
|
| 59 |
label="isAnomaly",
|
| 60 |
),
|
| 61 |
+
Textbox(
|
| 62 |
+
type="text",
|
| 63 |
+
label="Anomaly Map Max",
|
| 64 |
+
),
|
| 65 |
+
Textbox(
|
| 66 |
+
type="text",
|
| 67 |
+
label="Anomaly Map",
|
| 68 |
+
),
|
| 69 |
Image(
|
| 70 |
type="numpy",
|
| 71 |
label="Result",
|
| 72 |
),
|
| 73 |
+
Image(
|
| 74 |
+
type="numpy",
|
| 75 |
+
label="Anomaly Map (with custom threshold)",
|
| 76 |
+
),
|
| 77 |
Image(
|
| 78 |
type="numpy",
|
| 79 |
label="Input",
|
configs/fukazara_scoop_black_4.yaml
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# https://github.com/openvinotoolkit/anomalib/blob/main/src/anomalib/models/patchcore/config.yaml
|
| 2 |
+
|
| 3 |
+
dataset:
|
| 4 |
+
name: original
|
| 5 |
+
format: mvtec
|
| 6 |
+
path: /workspaces/anomaly-detection/datasets/original
|
| 7 |
+
task: segmentation
|
| 8 |
+
category: fukazara_scoop_black_4
|
| 9 |
+
train_batch_size: 32
|
| 10 |
+
eval_batch_size: 32
|
| 11 |
+
num_workers: 8
|
| 12 |
+
image_size: 256 # dimensions to which images are resized (mandatory)
|
| 13 |
+
# center_crop: 224 # dimensions to which images are center-cropped after resizing (optional)
|
| 14 |
+
normalization: imagenet # data distribution to which the images will be normalized: [none, imagenet]
|
| 15 |
+
transform_config:
|
| 16 |
+
train: null
|
| 17 |
+
eval: null
|
| 18 |
+
test_split_mode: synthetic # options: [from_dir, synthetic]
|
| 19 |
+
test_split_ratio: 0.2 # fraction of train images held out testing (usage depends on test_split_mode)
|
| 20 |
+
val_split_mode: synthetic # options: [same_as_test, from_test, synthetic]
|
| 21 |
+
val_split_ratio: 0.5 # fraction of train/test images held out for validation (usage depends on val_split_mode)
|
| 22 |
+
tiling:
|
| 23 |
+
apply: false
|
| 24 |
+
tile_size: null
|
| 25 |
+
stride: null
|
| 26 |
+
remove_border_count: 0
|
| 27 |
+
use_random_tiling: False
|
| 28 |
+
random_tile_count: 16
|
| 29 |
+
|
| 30 |
+
model:
|
| 31 |
+
name: patchcore
|
| 32 |
+
backbone: wide_resnet50_2
|
| 33 |
+
pre_trained: true
|
| 34 |
+
layers:
|
| 35 |
+
- layer2
|
| 36 |
+
- layer3
|
| 37 |
+
coreset_sampling_ratio: 0.001
|
| 38 |
+
num_neighbors: 9
|
| 39 |
+
normalization_method: min_max # options: [null, min_max, cdf]
|
| 40 |
+
|
| 41 |
+
metrics:
|
| 42 |
+
image:
|
| 43 |
+
- F1Score
|
| 44 |
+
- AUROC
|
| 45 |
+
pixel:
|
| 46 |
+
- F1Score
|
| 47 |
+
- AUROC
|
| 48 |
+
threshold:
|
| 49 |
+
method: adaptive #options: [adaptive, manual]
|
| 50 |
+
manual_image: null
|
| 51 |
+
manual_pixel: null
|
| 52 |
+
|
| 53 |
+
visualization:
|
| 54 |
+
show_images: False # show images on the screen
|
| 55 |
+
save_images: True # save images to the file system
|
| 56 |
+
log_images: True # log images to the available loggers (if any)
|
| 57 |
+
image_save_path: null # path to which images will be saved
|
| 58 |
+
mode: full # options: ["full", "simple"]
|
| 59 |
+
|
| 60 |
+
project:
|
| 61 |
+
seed: 0
|
| 62 |
+
path: /workspaces/anomaly-detection/results
|
| 63 |
+
|
| 64 |
+
logging:
|
| 65 |
+
logger: [] # options: [comet, tensorboard, wandb, csv] or combinations.
|
| 66 |
+
log_graph: false # Logs the model graph to respective logger.
|
| 67 |
+
|
| 68 |
+
optimization:
|
| 69 |
+
export_mode: null # options: onnx, openvino
|
| 70 |
+
|
| 71 |
+
# PL Trainer Args. Don't add extra parameter here.
|
| 72 |
+
trainer:
|
| 73 |
+
enable_checkpointing: true
|
| 74 |
+
default_root_dir: null
|
| 75 |
+
gradient_clip_val: 0
|
| 76 |
+
gradient_clip_algorithm: norm
|
| 77 |
+
num_nodes: 1
|
| 78 |
+
devices: 1
|
| 79 |
+
enable_progress_bar: true
|
| 80 |
+
overfit_batches: 0.0
|
| 81 |
+
track_grad_norm: -1
|
| 82 |
+
check_val_every_n_epoch: 1 # Don't validate before extracting features.
|
| 83 |
+
fast_dev_run: false
|
| 84 |
+
accumulate_grad_batches: 4
|
| 85 |
+
max_epochs: 1
|
| 86 |
+
min_epochs: null
|
| 87 |
+
max_steps: -1
|
| 88 |
+
min_steps: null
|
| 89 |
+
max_time: null
|
| 90 |
+
limit_train_batches: 0.5
|
| 91 |
+
limit_val_batches: 1.0
|
| 92 |
+
limit_test_batches: 1.0
|
| 93 |
+
limit_predict_batches: 1.0
|
| 94 |
+
val_check_interval: 1.0 # Don't validate before extracting features.
|
| 95 |
+
log_every_n_steps: 50
|
| 96 |
+
accelerator: auto # <"cpu", "gpu", "tpu", "ipu", "hpu", "auto">
|
| 97 |
+
strategy: null
|
| 98 |
+
sync_batchnorm: false
|
| 99 |
+
precision: 32
|
| 100 |
+
enable_model_summary: true
|
| 101 |
+
num_sanity_val_steps: 0
|
| 102 |
+
profiler: null
|
| 103 |
+
benchmark: false
|
| 104 |
+
deterministic: false
|
| 105 |
+
reload_dataloaders_every_n_epochs: 0
|
| 106 |
+
auto_lr_find: false
|
| 107 |
+
replace_sampler_ddp: true
|
| 108 |
+
detect_anomaly: false
|
| 109 |
+
auto_scale_batch_size: false
|
| 110 |
+
plugins: null
|
| 111 |
+
move_metrics_to_cpu: false
|
| 112 |
+
multiple_trainloader_mode: max_size_cycle
|
lightning_inference.py
CHANGED
|
@@ -12,8 +12,9 @@ from anomalib.data.utils import InputNormalizationMethod, get_transforms
|
|
| 12 |
from anomalib.models import get_model
|
| 13 |
from anomalib.utils.callbacks import get_callbacks
|
| 14 |
|
| 15 |
-
from utils.preprocess import fill_background_and_crop
|
| 16 |
-
|
|
|
|
| 17 |
|
| 18 |
def has_blue_pixels(image_path):
|
| 19 |
# 画像を読み込む
|
|
@@ -29,6 +30,7 @@ def has_blue_pixels(image_path):
|
|
| 29 |
def infer(
|
| 30 |
input: np.ndarray,
|
| 31 |
suffix: str,
|
|
|
|
| 32 |
configPath: Path,
|
| 33 |
weightsPath: Path):
|
| 34 |
"""Run inference."""
|
|
@@ -69,27 +71,34 @@ def infer(
|
|
| 69 |
input_path = Path(tempfile.mktemp(suffix=suffix))
|
| 70 |
cv2.imwrite(str(input_path), input)
|
| 71 |
|
| 72 |
-
|
|
|
|
| 73 |
|
| 74 |
# create the dataset
|
| 75 |
dataset = InferenceDataset(
|
| 76 |
-
|
| 77 |
image_size=tuple(config.dataset.image_size),
|
| 78 |
transform=transform
|
| 79 |
)
|
| 80 |
dataloader = DataLoader(dataset)
|
| 81 |
|
| 82 |
# generate predictions
|
| 83 |
-
|
| 84 |
model=model,
|
| 85 |
dataloaders=[dataloader],
|
| 86 |
return_predictions=True,
|
| 87 |
)
|
| 88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
# read the output image
|
| 90 |
-
output_path = "/tmp/" + sessionId + "/tmp/" +
|
| 91 |
|
| 92 |
# Check if the output image has blue pixels
|
| 93 |
-
|
|
|
|
| 94 |
|
| 95 |
-
return
|
|
|
|
| 12 |
from anomalib.models import get_model
|
| 13 |
from anomalib.utils.callbacks import get_callbacks
|
| 14 |
|
| 15 |
+
from utils.preprocess import fill_background_and_crop, convert_to_png
|
| 16 |
+
from utils.save_anomaly_map_as_png import save_anomaly_map_as_png
|
| 17 |
+
from utils.tensor_to_list import tensor_to_list
|
| 18 |
|
| 19 |
def has_blue_pixels(image_path):
|
| 20 |
# 画像を読み込む
|
|
|
|
| 30 |
def infer(
|
| 31 |
input: np.ndarray,
|
| 32 |
suffix: str,
|
| 33 |
+
threshold,
|
| 34 |
configPath: Path,
|
| 35 |
weightsPath: Path):
|
| 36 |
"""Run inference."""
|
|
|
|
| 71 |
input_path = Path(tempfile.mktemp(suffix=suffix))
|
| 72 |
cv2.imwrite(str(input_path), input)
|
| 73 |
|
| 74 |
+
png_path = Path(convert_to_png(input_path))
|
| 75 |
+
fill_background_and_crop(png_path)
|
| 76 |
|
| 77 |
# create the dataset
|
| 78 |
dataset = InferenceDataset(
|
| 79 |
+
png_path,
|
| 80 |
image_size=tuple(config.dataset.image_size),
|
| 81 |
transform=transform
|
| 82 |
)
|
| 83 |
dataloader = DataLoader(dataset)
|
| 84 |
|
| 85 |
# generate predictions
|
| 86 |
+
result = trainer.predict(
|
| 87 |
model=model,
|
| 88 |
dataloaders=[dataloader],
|
| 89 |
return_predictions=True,
|
| 90 |
)
|
| 91 |
|
| 92 |
+
anomaly_map = result[0]["anomaly_maps"].squeeze()
|
| 93 |
+
anomaly_map_path = "/tmp/" + sessionId + "/tmp/anomaly_map.png"
|
| 94 |
+
save_anomaly_map_as_png(anomaly_map, anomaly_map_path, threshold)
|
| 95 |
+
anomaly_map_list = tensor_to_list(anomaly_map)
|
| 96 |
+
|
| 97 |
# read the output image
|
| 98 |
+
output_path = "/tmp/" + sessionId + "/tmp/" + png_path.name
|
| 99 |
|
| 100 |
# Check if the output image has blue pixels
|
| 101 |
+
anomaly_map_max = anomaly_map.max().item()
|
| 102 |
+
is_anomaly = anomaly_map.max().item() > threshold
|
| 103 |
|
| 104 |
+
return is_anomaly, anomaly_map_max, anomaly_map_list, cv2.imread(str(output_path)), cv2.imread(str(anomaly_map_path)), cv2.imread(str(png_path))
|
models/fukazara_scoop_black_4.ckpt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9fe2f79b20d6cd9d039740bc866ccf4735c8f9ea9af27a4cc5c0349d44e516de
|
| 3 |
+
size 140731294
|
requirements.txt
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
openvino==2023.2.0
|
| 2 |
-
anomalib
|
| 3 |
wandb
|
|
|
|
| 1 |
openvino==2023.2.0
|
| 2 |
+
anomalib==0.7.0
|
| 3 |
wandb
|
utils/preprocess.py
CHANGED
|
@@ -7,6 +7,14 @@ import argparse
|
|
| 7 |
from pathlib import Path
|
| 8 |
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
# Function to fill background and crop the image to make the object fill the frame
|
| 11 |
def fill_background_and_crop(image_path):
|
| 12 |
# 背景色の設定(BGR)
|
|
|
|
| 7 |
from pathlib import Path
|
| 8 |
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 9 |
|
| 10 |
+
|
| 11 |
+
def convert_to_png(image_path):
|
| 12 |
+
image = cv2.imread(str(image_path))
|
| 13 |
+
png_path = str(image_path).rsplit('.', 1)[0] + '.png'
|
| 14 |
+
cv2.imwrite(png_path, image)
|
| 15 |
+
return png_path
|
| 16 |
+
|
| 17 |
+
|
| 18 |
# Function to fill background and crop the image to make the object fill the frame
|
| 19 |
def fill_background_and_crop(image_path):
|
| 20 |
# 背景色の設定(BGR)
|