rein0421 commited on
Commit
2ba2f95
·
verified ·
1 Parent(s): 18ad771

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +153 -37
app.py CHANGED
@@ -913,6 +913,68 @@ async def read_root():
913
  <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
914
  <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
915
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
916
  <style>
917
  body {
918
  background-color: #f0f0f5;
@@ -998,23 +1060,21 @@ async def read_root():
998
  <i class="fas fa-spinner fa-spin fa-3x"></i>
999
  <p>画像を処理中です。少々お待ちください...</p>
1000
  </div>
1001
-
1002
  <div class="container">
1003
- <h1><i class="fas fa-image"></i> 画像処理アプリ</h1>
1004
 
1005
  <ul class="nav nav-tabs" role="tablist">
1006
  <li class="nav-item">
1007
  <a class="nav-link active" id="general-tab" data-toggle="tab" href="#general" role="tab">
1008
- <i class="fas fa-magic"></i> 一般処理モード
1009
  </a>
1010
  </li>
1011
  <li class="nav-item">
1012
  <a class="nav-link" id="face-tab" data-toggle="tab" href="#face" role="tab">
1013
- <i class="fas fa-user-circle"></i> 顔照合モード
1014
  </a>
1015
  </li>
1016
  </ul>
1017
-
1018
  <div class="tab-content">
1019
  <!-- 一般処理モード -->
1020
  <div class="tab-pane fade show active" id="general" role="tabpanel">
@@ -1033,15 +1093,12 @@ async def read_root():
1033
  <option value="mosaic">mosaicインペイント</option>
1034
  </select>
1035
  </div>
1036
-
1037
  <div class="slider-container">
1038
  <label for="riskLevel1" class="slider-label">リスクレベル (0-100): <span id="riskLevelLabel1">50</span></label>
1039
  <div id="slider1"></div>
1040
  </div>
1041
-
1042
  <button class="btn btn-primary mt-4" onclick="processGeneralImage()">処理開始</button>
1043
  </div>
1044
-
1045
  <!-- 顔照合モード -->
1046
  <div class="tab-pane fade" id="face" role="tabpanel">
1047
  <div class="form-group">
@@ -1049,7 +1106,6 @@ async def read_root():
1049
  <input type="file" id="uploadImage2" class="form-control-file" accept="image/*" onchange="previewAndResizeImage('uploadImage2', 'uploadedImage2')">
1050
  </div>
1051
  <img id="uploadedImage2" class="image-preview" src="#" alt="アップロードされた画像" style="display: none;">
1052
-
1053
  <div class="form-group mt-4">
1054
  <label for="faceOption">自分の顔の入力方法を選択:</label>
1055
  <select id="faceOption" class="custom-select" onchange="toggleFaceInput()">
@@ -1057,27 +1113,22 @@ async def read_root():
1057
  <option value="camera">カメラで撮影</option>
1058
  </select>
1059
  </div>
1060
-
1061
  <div class="form-group" id="uploadFaceGroup">
1062
  <label for="uploadFace">顔画像をアップロード:</label>
1063
  <input type="file" id="uploadFace" class="form-control-file" accept="image/*" onchange="previewFaceImage()">
1064
  <img id="facePreview" class="image-preview" src="#" alt="顔画像のプレビュー" style="display: none;">
1065
  </div>
1066
-
1067
  <div class="form-group" id="cameraFaceGroup" style="display: none;">
1068
  <video id="cameraStream" width="100%" autoplay></video>
1069
  <button class="btn btn-secondary mt-2" onclick="captureFaceImage()">顔をキャプチャ</button>
1070
  <canvas id="cameraCanvas" style="display: none;"></canvas>
1071
  </div>
1072
-
1073
  <div class="slider-container">
1074
  <label for="riskLevel2" class="slider-label">リスクレベル (0-100): <span id="riskLevelLabel2">50</span></label>
1075
  <div id="slider2"></div>
1076
  </div>
1077
-
1078
  <button class="btn btn-primary mt-4" onclick="processFaceImage()">処理開始</button>
1079
  </div>
1080
-
1081
  <!-- 処理結果(共通) -->
1082
  <div id="result" class="mt-5">
1083
  <h2>処理結果:</h2>
@@ -1086,10 +1137,93 @@ async def read_root():
1086
  </div>
1087
  </div>
1088
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1089
 
 
1090
  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
1091
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
1092
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
 
 
 
1093
  <script>
1094
  // スライダーの初期化
1095
  $(function() {
@@ -1104,11 +1238,9 @@ async def read_root():
1104
  }
1105
  });
1106
  });
1107
-
1108
  let resizedImageBlob1 = null;
1109
  let resizedImageBlob2 = null;
1110
  let faceImageBlob = null;
1111
-
1112
  function previewAndResizeImage(inputId, imageId) {
1113
  const fileInput = document.getElementById(inputId);
1114
  const uploadedImage = document.getElementById(imageId);
@@ -1122,19 +1254,16 @@ async def read_root():
1122
  const maxHeight = 1200;
1123
  let width = img.width;
1124
  let height = img.height;
1125
-
1126
  if (width > maxWidth || height > maxHeight) {
1127
  const ratio = Math.min(maxWidth / width, maxHeight / height);
1128
  width *= ratio;
1129
  height *= ratio;
1130
  }
1131
-
1132
  const canvas = document.createElement('canvas');
1133
  canvas.width = width;
1134
  canvas.height = height;
1135
  const ctx = canvas.getContext('2d');
1136
  ctx.drawImage(img, 0, 0, width, height);
1137
-
1138
  uploadedImage.src = canvas.toDataURL('image/jpeg');
1139
  uploadedImage.style.display = 'block';
1140
 
@@ -1151,7 +1280,6 @@ async def read_root():
1151
  reader.readAsDataURL(fileInput.files[0]);
1152
  }
1153
  }
1154
-
1155
  function previewFaceImage() {
1156
  const fileInput = document.getElementById('uploadFace');
1157
  if (fileInput.files && fileInput.files[0]) {
@@ -1164,7 +1292,6 @@ async def read_root():
1164
  faceImageBlob = fileInput.files[0];
1165
  }
1166
  }
1167
-
1168
  function toggleFaceInput() {
1169
  const faceOption = document.getElementById('faceOption').value;
1170
  document.getElementById('uploadFaceGroup').style.display = faceOption === 'upload' ? 'block' : 'none';
@@ -1175,14 +1302,12 @@ async def read_root():
1175
  stopCamera();
1176
  }
1177
  }
1178
-
1179
  function startCamera() {
1180
  const video = document.getElementById('cameraStream');
1181
  navigator.mediaDevices.getUserMedia({ video: true })
1182
  .then(stream => video.srcObject = stream)
1183
  .catch(error => console.error('カメラの起動に失敗しました:', error));
1184
  }
1185
-
1186
  function stopCamera() {
1187
  const video = document.getElementById('cameraStream');
1188
  const stream = video.srcObject;
@@ -1191,7 +1316,6 @@ async def read_root():
1191
  video.srcObject = null;
1192
  }
1193
  }
1194
-
1195
  function captureFaceImage() {
1196
  const video = document.getElementById('cameraStream');
1197
  const canvas = document.getElementById('cameraCanvas');
@@ -1202,21 +1326,17 @@ async def read_root():
1202
  canvas.toBlob(blob => faceImageBlob = blob, 'image/jpeg');
1203
  stopCamera();
1204
  }
1205
-
1206
  function processGeneralImage() {
1207
  if (!resizedImageBlob1) {
1208
  alert("画像を選択してください。");
1209
  return;
1210
  }
1211
-
1212
  const processingType = document.getElementById('processingType').value;
1213
  const riskLevel = $("#slider1").slider("value");
1214
  showLoadingSpinner();
1215
-
1216
  const formData = new FormData();
1217
  formData.append('image', resizedImageBlob1, 'resized_image.jpg');
1218
  formData.append('risk_level', riskLevel);
1219
-
1220
  let apiEndpoint;
1221
  if (processingType === "opencv") {
1222
  apiEndpoint = "/create-mask-and-inpaint-opencv";
@@ -1227,27 +1347,21 @@ async def read_root():
1227
  } else if (processingType === "mosaic") {
1228
  apiEndpoint = "/create-mask-and-inpaint-mosaic";
1229
  }
1230
-
1231
  processImageRequest(formData, "https://rein0421-aidentify.hf.space" + apiEndpoint);
1232
  }
1233
-
1234
  function processFaceImage() {
1235
  if (!resizedImageBlob2 || !faceImageBlob) {
1236
  alert("処理する画像と顔画像の両方を設定してください。");
1237
  return;
1238
  }
1239
-
1240
  const riskLevel = $("#slider2").slider("value");
1241
  showLoadingSpinner();
1242
-
1243
  const formData = new FormData();
1244
  formData.append('reference_image', faceImageBlob, 'reference_image.jpg');
1245
  formData.append('test_image', resizedImageBlob2, 'test_image.jpg');
1246
  formData.append('risk_level', riskLevel);
1247
-
1248
  processImageRequest(formData, "https://rein0421-aidentify.hf.space/mosaic_faces");
1249
  }
1250
-
1251
  function processImageRequest(formData, url) {
1252
  fetch(url, {
1253
  method: 'POST',
@@ -1271,15 +1385,12 @@ async def read_root():
1271
  hideLoadingSpinner();
1272
  });
1273
  }
1274
-
1275
  function showLoadingSpinner() {
1276
  document.getElementById('loadingSpinner').style.display = 'block';
1277
  }
1278
-
1279
  function hideLoadingSpinner() {
1280
  document.getElementById('loadingSpinner').style.display = 'none';
1281
  }
1282
-
1283
  // タブ切り替え時の処理
1284
  $('.nav-tabs a').on('shown.bs.tab', function (e) {
1285
  // 結果表示をリセット
@@ -1288,6 +1399,11 @@ async def read_root():
1288
  document.getElementById('downloadLink').href = '#';
1289
  });
1290
  </script>
 
 
 
 
 
1291
  </body>
1292
  </html>
1293
  """
 
913
  <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
914
  <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
915
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet">
916
+ <style>
917
+ /* 既存のスタイル */
918
+ body {
919
+ background-color: #f0f0f5;
920
+ color: #333;
921
+ padding: 40px 20px;
922
+ }
923
+ /* ... 他の既存のスタイル ... */
924
+
925
+ /* ヘルプボタンのスタイル */
926
+ .help-button {
927
+ position: fixed;
928
+ bottom: 20px;
929
+ right: 20px;
930
+ width: 50px;
931
+ height: 50px;
932
+ border-radius: 50%;
933
+ background-color: #007bff;
934
+ color: white;
935
+ border: none;
936
+ box-shadow: 0 2px 10px rgba(0,0,0,0.2);
937
+ z-index: 1000;
938
+ display: flex;
939
+ align-items: center;
940
+ justify-content: center;
941
+ font-size: 1.5rem;
942
+ }
943
+
944
+ .help-button:hover {
945
+ background-color: #0056b3;
946
+ }
947
+
948
+ /* モーダル内のスタイル */
949
+ .help-section {
950
+ margin-bottom: 30px;
951
+ padding: 15px;
952
+ border-radius: 8px;
953
+ background-color: #f8f9fa;
954
+ }
955
+
956
+ .help-section h4 {
957
+ color: #007bff;
958
+ margin-bottom: 15px;
959
+ }
960
+
961
+ .step-list {
962
+ padding-left: 20px;
963
+ }
964
+
965
+ .step-list li {
966
+ margin-bottom: 10px;
967
+ }
968
+
969
+ .modal-body img {
970
+ max-width: 100%;
971
+ border-radius: 5px;
972
+ margin: 10px 0;
973
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
974
+ }
975
+ </style>
976
+
977
+
978
  <style>
979
  body {
980
  background-color: #f0f0f5;
 
1060
  <i class="fas fa-spinner fa-spin fa-3x"></i>
1061
  <p>画像を処理中です。少々お待ちください...</p>
1062
  </div>
 
1063
  <div class="container">
1064
+ <h1><i class="fas fa-image"></i> AIデンティファイ</h1>
1065
 
1066
  <ul class="nav nav-tabs" role="tablist">
1067
  <li class="nav-item">
1068
  <a class="nav-link active" id="general-tab" data-toggle="tab" href="#general" role="tab">
1069
+ <i class="fas fa-magic"></i> 個人情報保護モード
1070
  </a>
1071
  </li>
1072
  <li class="nav-item">
1073
  <a class="nav-link" id="face-tab" data-toggle="tab" href="#face" role="tab">
1074
+ <i class="fas fa-user-circle"></i> 顔保護モード
1075
  </a>
1076
  </li>
1077
  </ul>
 
1078
  <div class="tab-content">
1079
  <!-- 一般処理モード -->
1080
  <div class="tab-pane fade show active" id="general" role="tabpanel">
 
1093
  <option value="mosaic">mosaicインペイント</option>
1094
  </select>
1095
  </div>
 
1096
  <div class="slider-container">
1097
  <label for="riskLevel1" class="slider-label">リスクレベル (0-100): <span id="riskLevelLabel1">50</span></label>
1098
  <div id="slider1"></div>
1099
  </div>
 
1100
  <button class="btn btn-primary mt-4" onclick="processGeneralImage()">処理開始</button>
1101
  </div>
 
1102
  <!-- 顔照合モード -->
1103
  <div class="tab-pane fade" id="face" role="tabpanel">
1104
  <div class="form-group">
 
1106
  <input type="file" id="uploadImage2" class="form-control-file" accept="image/*" onchange="previewAndResizeImage('uploadImage2', 'uploadedImage2')">
1107
  </div>
1108
  <img id="uploadedImage2" class="image-preview" src="#" alt="アップロードされた画像" style="display: none;">
 
1109
  <div class="form-group mt-4">
1110
  <label for="faceOption">自分の顔の入力方法を選択:</label>
1111
  <select id="faceOption" class="custom-select" onchange="toggleFaceInput()">
 
1113
  <option value="camera">カメラで撮影</option>
1114
  </select>
1115
  </div>
 
1116
  <div class="form-group" id="uploadFaceGroup">
1117
  <label for="uploadFace">顔画像をアップロード:</label>
1118
  <input type="file" id="uploadFace" class="form-control-file" accept="image/*" onchange="previewFaceImage()">
1119
  <img id="facePreview" class="image-preview" src="#" alt="顔画像のプレビュー" style="display: none;">
1120
  </div>
 
1121
  <div class="form-group" id="cameraFaceGroup" style="display: none;">
1122
  <video id="cameraStream" width="100%" autoplay></video>
1123
  <button class="btn btn-secondary mt-2" onclick="captureFaceImage()">顔をキャプチャ</button>
1124
  <canvas id="cameraCanvas" style="display: none;"></canvas>
1125
  </div>
 
1126
  <div class="slider-container">
1127
  <label for="riskLevel2" class="slider-label">リスクレベル (0-100): <span id="riskLevelLabel2">50</span></label>
1128
  <div id="slider2"></div>
1129
  </div>
 
1130
  <button class="btn btn-primary mt-4" onclick="processFaceImage()">処理開始</button>
1131
  </div>
 
1132
  <!-- 処理結果(共通) -->
1133
  <div id="result" class="mt-5">
1134
  <h2>処理結果:</h2>
 
1137
  </div>
1138
  </div>
1139
  </div>
1140
+
1141
+
1142
+ <!-- ヘルプボタン -->
1143
+ <button class="help-button" data-toggle="modal" data-target="#helpModal">
1144
+ <i class="fas fa-question"></i>
1145
+ </button>
1146
+
1147
+ <!-- ヘルプモーダル -->
1148
+ <div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel" aria-hidden="true">
1149
+ <div class="modal-dialog modal-lg" role="document">
1150
+ <div class="modal-content">
1151
+ <div class="modal-header">
1152
+ <h5 class="modal-title" id="helpModalLabel">
1153
+ <i class="fas fa-question-circle"></i> AIデンティファイの使い方
1154
+ </h5>
1155
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
1156
+ <span aria-hidden="true">&times;</span>
1157
+ </button>
1158
+ </div>
1159
+ <div class="modal-body">
1160
+ <!-- 一般処理モードの説明 -->
1161
+ <div class="help-section">
1162
+ <h4><i class="fas fa-magic"></i> 個人情報保護モードの使い方</h4>
1163
+ <ol class="step-list">
1164
+   <li>このモードではあなたの個人情報を簡単に保護することができます</li>
1165
+ <li>「画像をアップロード」ボタンをクリックして、処理したい画像を選択します。</li>
1166
+ <li>処理方法を以下から選択します:
1167
+ <ul>
1168
+ <li><strong>OpenCVインペイント:</strong> 一般的な画像補正</li>
1169
+ <li><strong>Simple Lamaインペイント:</strong> 高度な画像補正</li>
1170
+ <li><strong>stampインペイント:</strong> スタンプによる画像加工</li>
1171
+ <li><strong>mosaicインペイント:</strong> モザイクによる加工</li>
1172
+ </ul>
1173
+ </li>
1174
+ <li>スライダーでリスクレベルを調整します(0-100):
1175
+ <ul>
1176
+ <li>値が高いほど、より強い保護が適用されます</li>
1177
+ <li>推奨値は30前後です</li>
1178
+ </ul>
1179
+ </li>
1180
+ <li>「処理開始」ボタンをクリックして処理を実行します。</li>
1181
+ </ol>
1182
+ </div>
1183
+
1184
+ <!-- 顔照合モードの説明 -->
1185
+ <div class="help-section">
1186
+ <h4><i class="fas fa-user-circle"></i> 顔保護モードの使い方</h4>
1187
+ <ol class="step-list">
1188
+   <li>このモードではあなたの顔以外を隠すことができます。</li>
1189
+ <li>「処理する画像をアップロード」から、処理したい画像を選択します。</li>
1190
+ <li>自分の顔の入力方法を選択します:
1191
+ <ul>
1192
+ <li><strong>ファイルからアップロード:</strong> 既存の顔写真を使用</li>
1193
+ <li><strong>カメラで撮影:</strong> Webカメラを使用して顔写真を撮影</li>
1194
+ </ul>
1195
+ </li>
1196
+ <li>選択した方法で顔画像を入力します。</li>
1197
+ <li>スライダーでリスクレベルを調整します。</li>
1198
+ <li>「処理開始」ボタンをクリックして処理を実行します。</li>
1199
+ </ol>
1200
+ </div>
1201
+
1202
+ <!-- 共通の注意事項 -->
1203
+ <div class="help-section">
1204
+ <h4><i class="fas fa-exclamation-triangle"></i> 注意事項</h4>
1205
+ <ul>
1206
+ <li>アップロードする画像は1200×1200ピクセル以下に自動でリサイズされます。</li>
1207
+ <li>処理には数秒から30秒ほどかかる場合があります。</li>
1208
+ <li>処理が完了すると、処理結果が表示され、画像のダウンロードが可能になります。</li>
1209
+ <li>ブラウザのプライバシー設定によっては、カメラの使用許可が必要な場合があります。</li>
1210
+ </ul>
1211
+ </div>
1212
+ </div>
1213
+ <div class="modal-footer">
1214
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">閉じる</button>
1215
+ </div>
1216
+ </div>
1217
+ </div>
1218
+ </div>
1219
 
1220
+ <!-- 既存のスクリプト -->
1221
  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
1222
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
1223
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
1224
+ <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
1225
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
1226
+ <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
1227
  <script>
1228
  // スライダーの初期化
1229
  $(function() {
 
1238
  }
1239
  });
1240
  });
 
1241
  let resizedImageBlob1 = null;
1242
  let resizedImageBlob2 = null;
1243
  let faceImageBlob = null;
 
1244
  function previewAndResizeImage(inputId, imageId) {
1245
  const fileInput = document.getElementById(inputId);
1246
  const uploadedImage = document.getElementById(imageId);
 
1254
  const maxHeight = 1200;
1255
  let width = img.width;
1256
  let height = img.height;
 
1257
  if (width > maxWidth || height > maxHeight) {
1258
  const ratio = Math.min(maxWidth / width, maxHeight / height);
1259
  width *= ratio;
1260
  height *= ratio;
1261
  }
 
1262
  const canvas = document.createElement('canvas');
1263
  canvas.width = width;
1264
  canvas.height = height;
1265
  const ctx = canvas.getContext('2d');
1266
  ctx.drawImage(img, 0, 0, width, height);
 
1267
  uploadedImage.src = canvas.toDataURL('image/jpeg');
1268
  uploadedImage.style.display = 'block';
1269
 
 
1280
  reader.readAsDataURL(fileInput.files[0]);
1281
  }
1282
  }
 
1283
  function previewFaceImage() {
1284
  const fileInput = document.getElementById('uploadFace');
1285
  if (fileInput.files && fileInput.files[0]) {
 
1292
  faceImageBlob = fileInput.files[0];
1293
  }
1294
  }
 
1295
  function toggleFaceInput() {
1296
  const faceOption = document.getElementById('faceOption').value;
1297
  document.getElementById('uploadFaceGroup').style.display = faceOption === 'upload' ? 'block' : 'none';
 
1302
  stopCamera();
1303
  }
1304
  }
 
1305
  function startCamera() {
1306
  const video = document.getElementById('cameraStream');
1307
  navigator.mediaDevices.getUserMedia({ video: true })
1308
  .then(stream => video.srcObject = stream)
1309
  .catch(error => console.error('カメラの起動に失敗しました:', error));
1310
  }
 
1311
  function stopCamera() {
1312
  const video = document.getElementById('cameraStream');
1313
  const stream = video.srcObject;
 
1316
  video.srcObject = null;
1317
  }
1318
  }
 
1319
  function captureFaceImage() {
1320
  const video = document.getElementById('cameraStream');
1321
  const canvas = document.getElementById('cameraCanvas');
 
1326
  canvas.toBlob(blob => faceImageBlob = blob, 'image/jpeg');
1327
  stopCamera();
1328
  }
 
1329
  function processGeneralImage() {
1330
  if (!resizedImageBlob1) {
1331
  alert("画像を選択してください。");
1332
  return;
1333
  }
 
1334
  const processingType = document.getElementById('processingType').value;
1335
  const riskLevel = $("#slider1").slider("value");
1336
  showLoadingSpinner();
 
1337
  const formData = new FormData();
1338
  formData.append('image', resizedImageBlob1, 'resized_image.jpg');
1339
  formData.append('risk_level', riskLevel);
 
1340
  let apiEndpoint;
1341
  if (processingType === "opencv") {
1342
  apiEndpoint = "/create-mask-and-inpaint-opencv";
 
1347
  } else if (processingType === "mosaic") {
1348
  apiEndpoint = "/create-mask-and-inpaint-mosaic";
1349
  }
 
1350
  processImageRequest(formData, "https://rein0421-aidentify.hf.space" + apiEndpoint);
1351
  }
 
1352
  function processFaceImage() {
1353
  if (!resizedImageBlob2 || !faceImageBlob) {
1354
  alert("処理する画像と顔画像の両方を設定してください。");
1355
  return;
1356
  }
 
1357
  const riskLevel = $("#slider2").slider("value");
1358
  showLoadingSpinner();
 
1359
  const formData = new FormData();
1360
  formData.append('reference_image', faceImageBlob, 'reference_image.jpg');
1361
  formData.append('test_image', resizedImageBlob2, 'test_image.jpg');
1362
  formData.append('risk_level', riskLevel);
 
1363
  processImageRequest(formData, "https://rein0421-aidentify.hf.space/mosaic_faces");
1364
  }
 
1365
  function processImageRequest(formData, url) {
1366
  fetch(url, {
1367
  method: 'POST',
 
1385
  hideLoadingSpinner();
1386
  });
1387
  }
 
1388
  function showLoadingSpinner() {
1389
  document.getElementById('loadingSpinner').style.display = 'block';
1390
  }
 
1391
  function hideLoadingSpinner() {
1392
  document.getElementById('loadingSpinner').style.display = 'none';
1393
  }
 
1394
  // タブ切り替え時の処理
1395
  $('.nav-tabs a').on('shown.bs.tab', function (e) {
1396
  // 結果表示をリセット
 
1399
  document.getElementById('downloadLink').href = '#';
1400
  });
1401
  </script>
1402
+ <script>
1403
+ $(document).ready(function() {
1404
+ $('#helpModal').modal('show'); // ページ読み込み時にモーダルを表示
1405
+ });
1406
+ </script>
1407
  </body>
1408
  </html>
1409
  """