Spaces:
Runtime error
Runtime error
Commit ·
fc5d81f
1
Parent(s): a508bb8
カルピスのモデル
Browse files- app.py +5 -4
- configs/calpis_bottle_cap.yaml +112 -0
- models/calpis_bottle_cap.ckpt +3 -0
- utils/preprocess.py +45 -16
app.py
CHANGED
|
@@ -36,6 +36,7 @@ if __name__ == "__main__":
|
|
| 36 |
choices=[
|
| 37 |
"asahachi_black",
|
| 38 |
"fukazara_scoop_black_4",
|
|
|
|
| 39 |
],
|
| 40 |
label="Model",
|
| 41 |
),
|
|
@@ -48,7 +49,7 @@ if __name__ == "__main__":
|
|
| 48 |
type="text",
|
| 49 |
label="Threshold of difference between max and median",
|
| 50 |
value="0.095",
|
| 51 |
-
),
|
| 52 |
Textbox(
|
| 53 |
type="text",
|
| 54 |
label="Threshold of median",
|
|
@@ -63,11 +64,11 @@ if __name__ == "__main__":
|
|
| 63 |
Textbox(
|
| 64 |
type="text",
|
| 65 |
label="Anomaly Map Max",
|
| 66 |
-
),
|
| 67 |
Textbox(
|
| 68 |
type="text",
|
| 69 |
label="Anomaly Map Median",
|
| 70 |
-
),
|
| 71 |
Textbox(
|
| 72 |
type="text",
|
| 73 |
label="Anomaly Map",
|
|
@@ -87,4 +88,4 @@ if __name__ == "__main__":
|
|
| 87 |
],
|
| 88 |
title="Anomaly Detection with Anomalib",
|
| 89 |
)
|
| 90 |
-
interface.launch()
|
|
|
|
| 36 |
choices=[
|
| 37 |
"asahachi_black",
|
| 38 |
"fukazara_scoop_black_4",
|
| 39 |
+
"calpis_bottle_cap",
|
| 40 |
],
|
| 41 |
label="Model",
|
| 42 |
),
|
|
|
|
| 49 |
type="text",
|
| 50 |
label="Threshold of difference between max and median",
|
| 51 |
value="0.095",
|
| 52 |
+
),
|
| 53 |
Textbox(
|
| 54 |
type="text",
|
| 55 |
label="Threshold of median",
|
|
|
|
| 64 |
Textbox(
|
| 65 |
type="text",
|
| 66 |
label="Anomaly Map Max",
|
| 67 |
+
),
|
| 68 |
Textbox(
|
| 69 |
type="text",
|
| 70 |
label="Anomaly Map Median",
|
| 71 |
+
),
|
| 72 |
Textbox(
|
| 73 |
type="text",
|
| 74 |
label="Anomaly Map",
|
|
|
|
| 88 |
],
|
| 89 |
title="Anomaly Detection with Anomalib",
|
| 90 |
)
|
| 91 |
+
interface.launch()
|
configs/calpis_bottle_cap.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: cap
|
| 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: ./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
|
models/calpis_bottle_cap.ckpt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:755722860af37b81aa994fe94e6e734355357e8d445be2b1797b27ee2a8f34c0
|
| 3 |
+
size 110947742
|
utils/preprocess.py
CHANGED
|
@@ -15,32 +15,61 @@ def convert_to_png(image_path):
|
|
| 15 |
return png_path
|
| 16 |
|
| 17 |
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
| 19 |
def fill_background_and_crop(image_path):
|
| 20 |
# 背景色の設定(BGR)
|
| 21 |
-
color = [
|
| 22 |
|
|
|
|
| 23 |
image = cv2.imread(str(image_path))
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
contours, _ = cv2.findContours(
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
largest_contour = max(contours, key=cv2.contourArea)
|
| 31 |
-
mask = np.zeros_like(
|
| 32 |
cv2.drawContours(mask, [largest_contour], -1,
|
| 33 |
-
color=(255,)
|
| 34 |
mask_rgb = cv2.cvtColor(mask, cv2.COLOR_GRAY2RGB)
|
| 35 |
-
background_color = np.zeros_like(
|
| 36 |
background_color[:, :] = color
|
| 37 |
-
object_with_bg = np.where(mask_rgb == 255,
|
| 38 |
-
|
| 39 |
-
|
| 40 |
# Find the bounding rect and crop the image
|
| 41 |
x, y, w, h = cv2.boundingRect(largest_contour)
|
| 42 |
-
cropped_image =
|
| 43 |
-
cropped_image = cv2.
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
| 45 |
# Overwrite the original image
|
| 46 |
cv2.imwrite(str(image_path), cropped_image)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
return png_path
|
| 16 |
|
| 17 |
|
| 18 |
+
OUTPUT_SIZE = 256
|
| 19 |
+
EDGE_THRESHOLD = 30
|
| 20 |
+
|
| 21 |
+
|
| 22 |
def fill_background_and_crop(image_path):
|
| 23 |
# 背景色の設定(BGR)
|
| 24 |
+
color = [255, 0, 0]
|
| 25 |
|
| 26 |
+
# 画像を読み込み、HSV色空間に変換
|
| 27 |
image = cv2.imread(str(image_path))
|
| 28 |
+
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
|
| 29 |
+
v_channel = hsv_image[:, :, 2]
|
| 30 |
+
|
| 31 |
+
# Vチャネルに対してガウシアンブラーを適用
|
| 32 |
+
blurred_v = cv2.GaussianBlur(v_channel, (5, 5), 0)
|
| 33 |
+
|
| 34 |
+
# cv2.Cannyを使用してエッジ検出
|
| 35 |
+
edges = cv2.Canny(blurred_v, threshold1=EDGE_THRESHOLD, threshold2=100)
|
| 36 |
+
|
| 37 |
+
# エッジを太くするためにダイレーションを適用
|
| 38 |
+
kernel = np.ones((5, 5), np.uint8)
|
| 39 |
+
edges_dilated = cv2.dilate(edges, kernel, iterations=1)
|
| 40 |
+
|
| 41 |
+
# 輪郭を検出
|
| 42 |
contours, _ = cv2.findContours(
|
| 43 |
+
edges_dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
| 44 |
+
if not contours:
|
| 45 |
+
print("No contours found, image unchanged.")
|
| 46 |
+
return
|
| 47 |
+
|
| 48 |
largest_contour = max(contours, key=cv2.contourArea)
|
| 49 |
+
mask = np.zeros_like(v_channel)
|
| 50 |
cv2.drawContours(mask, [largest_contour], -1,
|
| 51 |
+
color=(255,), thickness=cv2.FILLED)
|
| 52 |
mask_rgb = cv2.cvtColor(mask, cv2.COLOR_GRAY2RGB)
|
| 53 |
+
background_color = np.zeros_like(image, dtype=np.uint8)
|
| 54 |
background_color[:, :] = color
|
| 55 |
+
object_with_bg = np.where(mask_rgb == 255, image, background_color)
|
| 56 |
+
|
|
|
|
| 57 |
# Find the bounding rect and crop the image
|
| 58 |
x, y, w, h = cv2.boundingRect(largest_contour)
|
| 59 |
+
cropped_image = object_with_bg[y:y+h, x:x+w]
|
| 60 |
+
cropped_image = cv2.GaussianBlur(cropped_image, (5, 5), 0)
|
| 61 |
+
|
| 62 |
+
# リサイズ処理の最適化
|
| 63 |
+
cropped_image = resize_image_optimized(cropped_image, OUTPUT_SIZE)
|
| 64 |
+
|
| 65 |
# Overwrite the original image
|
| 66 |
cv2.imwrite(str(image_path), cropped_image)
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def resize_image_optimized(image, size):
|
| 70 |
+
h, w = image.shape[:2]
|
| 71 |
+
ratio = size / max(h, w)
|
| 72 |
+
new_h, new_w = int(h * ratio), int(w * ratio)
|
| 73 |
+
resized_image = cv2.resize(
|
| 74 |
+
image, (new_w, new_h), interpolation=cv2.INTER_LINEAR)
|
| 75 |
+
return resized_image
|