Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -194,38 +194,119 @@ def analyze_mask_combined(original_image_path, mask_image_path, small_threshold,
|
|
194 |
|
195 |
|
196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
def create_mask(image, x1, y1, x2, y2):
|
198 |
-
# Create a black image with the same size as the input image
|
199 |
mask = np.zeros((image.shape[0], image.shape[1]), dtype=np.uint8)
|
200 |
-
|
201 |
-
# Draw a white rectangle on the mask where the object is located
|
202 |
cv2.rectangle(mask, (int(x1), int(y1)), (int(x2), int(y2)), 255, -1)
|
203 |
-
|
204 |
return mask
|
205 |
|
|
|
|
|
|
|
|
|
|
|
206 |
|
207 |
-
|
208 |
-
|
209 |
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
]
|
214 |
|
|
|
|
|
|
|
215 |
|
216 |
-
|
217 |
-
|
218 |
-
return tex[:int(risk_level)+1]
|
219 |
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
|
224 |
-
|
225 |
-
|
226 |
|
227 |
-
|
|
|
|
|
228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
|
230 |
def convert_image_format(input_path, output_format="png"):
|
231 |
"""
|
|
|
194 |
|
195 |
|
196 |
|
197 |
+
|
198 |
+
import os
|
199 |
+
import numpy as np
|
200 |
+
import cv2
|
201 |
+
import torch
|
202 |
+
from datetime import datetime
|
203 |
+
from PIL import Image
|
204 |
+
from ultralytics import YOLO
|
205 |
+
|
206 |
+
# オブジェクト選択を動的に行う関数
|
207 |
+
def decide_to_object(risk_level):
|
208 |
+
'''
|
209 |
+
tex = [
|
210 |
+
'text','Name tag', 'License plate', 'Mail', 'Documents', 'QR codes',
|
211 |
+
'barcodes', 'Map', 'Digital screens', 'information board',
|
212 |
+
'signboard', 'poster', 'sign', 'utility pole'
|
213 |
+
]
|
214 |
+
'''
|
215 |
+
tex = [
|
216 |
+
'text', 'License plate', 'Digital screens',
|
217 |
+
'signboard', 'poster', 'sign', 'logo', 'card', 'window', 'mirror',
|
218 |
+
'Famous landmark', 'cardboard', 'manhole', 'utility pole'
|
219 |
+
]
|
220 |
+
|
221 |
+
# この配列の要素の順番を変えると消える順番が変わる。
|
222 |
+
risk_level = int(risk_level / 20) * (len(tex) / 10) # 個数決定(1/2)
|
223 |
+
return tex[:int(risk_level) + 1]
|
224 |
+
|
225 |
+
# マスクを生成する関数
|
226 |
def create_mask(image, x1, y1, x2, y2):
|
|
|
227 |
mask = np.zeros((image.shape[0], image.shape[1]), dtype=np.uint8)
|
|
|
|
|
228 |
cv2.rectangle(mask, (int(x1), int(y1)), (int(x2), int(y2)), 255, -1)
|
|
|
229 |
return mask
|
230 |
|
231 |
+
# 特殊な処理を行う関数
|
232 |
+
def special_process_image_yolo(risk_level, image_path, point1, point2, thresholds=None):
|
233 |
+
# デバイスの確認
|
234 |
+
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
235 |
+
print(f"Using device: {device}")
|
236 |
|
237 |
+
# モデルファイルのパス
|
238 |
+
model_path = './1113.pt'
|
239 |
|
240 |
+
# モデルファイルの存在確認
|
241 |
+
if not os.path.isfile(model_path):
|
242 |
+
raise FileNotFoundError(f"モデルファイル '{model_path}' が見つかりません。パスを確認してください。")
|
|
|
243 |
|
244 |
+
# YOLOv8モデルをロードし、指定デバイスに移動
|
245 |
+
model = YOLO(model_path).to(device)
|
246 |
+
print("モデルが正常にロードされ、デバイスに移動しました。")
|
247 |
|
248 |
+
# タイムスタンプを作成
|
249 |
+
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
|
|
250 |
|
251 |
+
# リスクレベルに基づいた減衰率の計算
|
252 |
+
def logistic_decay(risk_level, k=0.1, r0=50):
|
253 |
+
return 1 / (1 + np.exp(-k * (risk_level - r0)))
|
254 |
|
255 |
+
decay_factor = logistic_decay(risk_level)
|
256 |
+
adjusted_thresholds = {key: max(value - decay_factor + 0.8, 0.01) / 2 for key, value in (thresholds or {}).items()}
|
257 |
|
258 |
+
# 画像の読み込みとRGB変換
|
259 |
+
image = cv2.imread(image_path)
|
260 |
+
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
261 |
|
262 |
+
# 推論実行
|
263 |
+
results = model(image_rgb)
|
264 |
+
|
265 |
+
# 初期化したマスク画像
|
266 |
+
mask = np.zeros(image.shape[:2], dtype=np.uint8)
|
267 |
+
|
268 |
+
# リスクレベルに基づいて消去対象のオブジェクトを決定
|
269 |
+
target_objects = decide_to_object(risk_level)
|
270 |
+
|
271 |
+
# 各検出結果に基づきマスク作成
|
272 |
+
for box in results[0].boxes:
|
273 |
+
x1, y1, x2, y2 = map(int, box.xyxy[0])
|
274 |
+
confidence = box.conf[0]
|
275 |
+
class_id = box.cls[0]
|
276 |
+
object_type = model.names[int(class_id)]
|
277 |
+
|
278 |
+
# クラス名が消去対象に含まれている場合のみ処理
|
279 |
+
if object_type in target_objects:
|
280 |
+
threshold = adjusted_thresholds.get(object_type, 0.5)
|
281 |
+
if confidence >= threshold:
|
282 |
+
mask = create_mask(image, x1, y1, x2, y2)
|
283 |
+
|
284 |
+
# 絶対座標に変換した点の範囲を黒に設定
|
285 |
+
p1_x, p1_y = int(point1[0] * image.shape[1]), int(point1[1] * image.shape[0])
|
286 |
+
p2_x, p2_y = int(point2[0] * image.shape[1]), int(point2[1] * image.shape[0])
|
287 |
+
x_min, y_min = max(0, min(p1_x, p2_x)), max(0, min(p1_y, p2_y))
|
288 |
+
x_max, y_max = min(image.shape[1], max(p1_x, p2_x)), min(image.shape[0], max(p1_y, p2_y))
|
289 |
+
mask[y_min:y_max, x_min:x_max] = 0 # 範囲を黒に設定
|
290 |
+
|
291 |
+
# デバッグ用に白い長方形を描画
|
292 |
+
debug_image = image_rgb.copy()
|
293 |
+
cv2.rectangle(debug_image, (x_min, y_min), (x_max, y_max), (255, 255, 255), 2)
|
294 |
+
|
295 |
+
# デバッグ画像とマスク画像を保存
|
296 |
+
save_dir = "./saved_images"
|
297 |
+
os.makedirs(save_dir, exist_ok=True)
|
298 |
+
debug_image_pil = Image.fromarray(debug_image)
|
299 |
+
debug_image_path = os.path.join(save_dir, f"debug_image_with_rectangle_{timestamp}.jpg")
|
300 |
+
debug_image_pil.save(debug_image_path)
|
301 |
+
|
302 |
+
mask_image_pil = Image.fromarray(mask)
|
303 |
+
mask_image_path = os.path.join(save_dir, f"final_mask_{timestamp}.jpg")
|
304 |
+
mask_image_pil.save(mask_image_path)
|
305 |
+
|
306 |
+
print(f"デバッグ画像が {debug_image_path} に保存されました。")
|
307 |
+
print(f"マスク画像が {mask_image_path} に保存されました。")
|
308 |
+
|
309 |
+
return mask_image_path
|
310 |
|
311 |
def convert_image_format(input_path, output_format="png"):
|
312 |
"""
|