HuggingFace-SK commited on
Commit
95ef0b2
·
1 Parent(s): e35d869

update to android

Browse files
static/browser_detect.css CHANGED
@@ -20,7 +20,7 @@ body {
20
  padding: 10px;
21
  background: #5d5d5d;
22
  border-radius: 12.5px;
23
- min-width:min-content;
24
  max-width: 100%;
25
  font-weight: bold;
26
  color: #DFDFDF;
@@ -376,3 +376,63 @@ margin-bottom: 40px;
376
  justify-content: space-evenly;
377
  align-items: center;
378
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  padding: 10px;
21
  background: #5d5d5d;
22
  border-radius: 12.5px;
23
+ min-width: min-content;
24
  max-width: 100%;
25
  font-weight: bold;
26
  color: #DFDFDF;
 
376
  justify-content: space-evenly;
377
  align-items: center;
378
  }
379
+
380
+ .switch {
381
+ position: relative;
382
+ display: inline-block;
383
+ width: 60px;
384
+ height: 34px;
385
+ }
386
+
387
+ .switch input {
388
+ opacity: 0;
389
+ width: 0;
390
+ height: 0;
391
+ }
392
+
393
+ .slider {
394
+ position: absolute;
395
+ cursor: pointer;
396
+ top: 0;
397
+ left: 0;
398
+ right: 0;
399
+ bottom: 0;
400
+ background-color: #ccc;
401
+ -webkit-transition: .4s;
402
+ transition: .4s;
403
+ }
404
+
405
+ .slider:before {
406
+ position: absolute;
407
+ content: "";
408
+ height: 26px;
409
+ width: 26px;
410
+ left: 4px;
411
+ bottom: 4px;
412
+ background-color: white;
413
+ -webkit-transition: .4s;
414
+ transition: .4s;
415
+ }
416
+
417
+ input:checked + .slider {
418
+ background-color: #2196F3;
419
+ }
420
+
421
+ input:focus + .slider {
422
+ box-shadow: 0 0 1px #2196F3;
423
+ }
424
+
425
+ input:checked + .slider:before {
426
+ -webkit-transform: translateX(26px);
427
+ -ms-transform: translateX(26px);
428
+ transform: translateX(26px);
429
+ }
430
+
431
+ /* Rounded sliders */
432
+ .slider.round {
433
+ border-radius: 34px;
434
+ }
435
+
436
+ .slider.round:before {
437
+ border-radius: 50%;
438
+ }
templates/browser-detect.html CHANGED
@@ -168,7 +168,7 @@
168
  <div class="about-card">
169
  <span>Version</span>
170
 
171
- <span>1.2.3</span>
172
  </div>
173
  <div class="about-card">
174
  <span>Author</span>
@@ -254,6 +254,24 @@
254
  <a>Listen 🔊</a>
255
  </button>
256
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  </form>
258
  </section>
259
  <div class="bottom-nav">
@@ -639,7 +657,7 @@
639
  </script>
640
 
641
  <script type="module">
642
- document.getElementById("info-").addEventListener("click", switchPage.bind(null, "info-"));
643
  document.getElementById("home-").addEventListener("click", switchPage.bind(null, "home-"));
644
  document.getElementById("settings-").addEventListener("click", switchPage.bind(null, "settings-"));
645
 
@@ -651,6 +669,16 @@
651
  let webcamRunning = false;
652
  var time_since_letter = 0
653
  var last_letter_time = 0
 
 
 
 
 
 
 
 
 
 
654
  var is_first_run = 1
655
  const letter_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"]
656
  const phrase_list = [" Good", " Hello", " How're", " I'm", " Thanks", " You"]
@@ -662,7 +690,7 @@
662
  const vision = await FilesetResolver.forVisionTasks("https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.0/wasm"); // This doesnt really matter as this is already imported somewhere else, and the code runs fine without the request
663
  handLandmarker = await HandLandmarker.createFromOptions(vision, {
664
  baseOptions: {
665
- //modelAssetPath: `http://127.0.0.1:8125/assets/static/hand_landmarker.task`, // For Android
666
  modelAssetPath: `https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task`, // For Web
667
  delegate: "GPU"
668
  },
@@ -698,6 +726,7 @@
698
  }
699
  })
700
  var global_res = 0;
 
701
  const video = document.getElementById("webcam");
702
  const canvasElement = document.getElementById("output_canvas");
703
  const canvasCtx = canvasElement.getContext("2d", { willReadFrequently: true });
@@ -832,7 +861,7 @@
832
  }
833
  canvasCtx.save();
834
  canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
835
-
836
  if (is_first_run == 1) {
837
  var elem_rect = document.getElementById("output_canvas").getBoundingClientRect()
838
  console.log(elem_rect.height | 0);
@@ -843,13 +872,13 @@
843
 
844
  if (results.landmarks && results.handednesses[0]) {
845
  var current_time = Math.round(Date.now())
846
- document.getElementById("predicted_result").style.width = String((current_time - last_letter_time) / 7) + "%"
847
  if (results.handednesses[0][0].categoryName == "Left") {
848
- if(!Array.from(document.getElementById('modeSelector').classList).includes('right') ){
849
- annotateImage()
850
  }
851
  canvasCtx.drawImage(video, 0, 0, canvasElement.width, (video.videoHeight / video.videoWidth) * canvasElement.width)
852
- annotateImage(Array.from(document.getElementById('modeSelector').classList).includes('right') )
853
  console.log("LEFT")
854
  //detectSign()
855
  } else {
@@ -861,7 +890,7 @@
861
 
862
 
863
  if (previous_result == current_result) {
864
- if (current_time - last_letter_time > 700) {
865
  last_letter_time = current_time
866
  word_list.push(" ")
867
  triggerPulse()
@@ -873,6 +902,7 @@
873
  last_letter_time = current_time
874
  }
875
  }
 
876
  }
877
  else {
878
  canvasCtx.drawImage(video, 0, 0, canvasElement.width, (video.videoHeight / video.videoWidth) * canvasElement.width)
@@ -902,12 +932,12 @@
902
  }
903
 
904
  canvasCtx.restore();
905
- // Kepp predicting
906
  if (webcamRunning === true) {
907
  window.requestAnimationFrame(predictWebcam);
908
  }
909
  }
910
- function annotateImage(firstA=true) {
911
 
912
  //console.log(results.landmarks)
913
  if (results.landmarks[0]) {
@@ -955,20 +985,21 @@
955
  if (crop_bottom > image_height) {
956
  crop_bottom = image_height
957
  }
958
- if(firstA == true){
959
- canvasCtx.beginPath();
960
- canvasCtx.rect(crop_left, crop_top, crop_right - crop_left, crop_bottom - crop_top);
961
- canvasCtx.stroke();
962
- if(!Array.from(document.getElementById("modeSelector").classList).includes('right')){
963
- canvasCtx.fillStyle="#ffffff"
964
- canvasCtx.fill()
 
 
 
 
 
 
965
  }
966
- }else{
967
- canvasCtx.beginPath();
968
- canvasCtx.rect(crop_left, crop_top, crop_right - crop_left, crop_bottom - crop_top);
969
- canvasCtx.stroke();
970
- }
971
-
972
 
973
 
974
  }
@@ -986,7 +1017,7 @@
986
  const zValues = hand.map(node => node.z);
987
  const maxZ = Math.max.apply(null, zValues)
988
  const minZ = Math.min.apply(null, zValues)
989
- const zRange = maxZ-minZ
990
  hand.forEach(node => {
991
  node.z = ((node.z - minZ) / zRange) * 255
992
  });
@@ -1060,8 +1091,8 @@
1060
  drawLandmarks(canvasCtx, hand[17], '#ff3030'); // Pinky palm (17)
1061
 
1062
  // Crop Canvas
1063
- if(firstA == true){
1064
- cropCanvas(canvasElement, crop_left, crop_top, crop_right - crop_left, crop_bottom - crop_top)
1065
  }
1066
  }
1067
  // Add more drawing calls for each landmark collection as needed
@@ -1092,14 +1123,55 @@
1092
 
1093
  predict(tf.expandDims(predictionInput, 0));
1094
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1095
  async function predict(inputTensor) {
1096
 
1097
  console.log(index_list[0])
1098
  objectDetector.then(function (res) {
 
1099
  var prediction = res.predict(inputTensor);
 
1100
  var outputArray = prediction.dataSync(); // Get the output as an array
1101
- var predictedClass = outputArray.indexOf(Math.max(...outputArray)); // Get the index
 
 
 
 
 
1102
  var current_result = index_list[predictedClass]
 
1103
  var previous_result = document.getElementById("predicted_result").innerText
1104
  document.getElementById("predicted_result").innerText = current_result
1105
  var current_time = Math.round(Date.now())
@@ -1108,7 +1180,8 @@
1108
  }
1109
  console.log("p:", previous_result, "c:", current_result)
1110
  if (previous_result == current_result) {
1111
- if (current_time - last_letter_time > 700) {
 
1112
  last_letter_time = current_time
1113
  word_list.push(current_result)
1114
  triggerPulse()
@@ -1143,7 +1216,7 @@
1143
  var image_width = canvasElement.width
1144
 
1145
  canvasCtx.strokeStyle = strokeColor;
1146
- canvasCtx.lineWidth = strokeWidth-1;
1147
  canvasCtx.beginPath();
1148
  canvasCtx.moveTo(startNode.x * image_width, startNode.y * image_height);
1149
  canvasCtx.lineTo(endNode.x * image_width, endNode.y * image_height);
@@ -1186,8 +1259,8 @@
1186
  resultWrapper.addEventListener('animationend', () => {
1187
  resultWrapper.classList.remove('pulse');
1188
  }, { once: true });*/
1189
- }
1190
- </script>
1191
 
1192
 
1193
 
 
168
  <div class="about-card">
169
  <span>Version</span>
170
 
171
+ <span>1.2.5</span>
172
  </div>
173
  <div class="about-card">
174
  <span>Author</span>
 
254
  <a>Listen 🔊</a>
255
  </button>
256
  </div>
257
+ <div class="about-card">
258
+ <label for="duration">Input Duration <span id="durationValue"></span>(ms)</label>
259
+ <input type="range" id="duration" min="200" max="1500" step="1" value="300"
260
+ oninput="document.getElementById('durationValue').innerText=this.value">
261
+ </div>
262
+ <div class="about-card">
263
+ <label for="repeat">Repeat Buffer <span id="repeatValue"></span>(ms)</label>
264
+ <input type="range" id="repeat" min="200" max="700" step="1" value="500"
265
+ oninput="document.getElementById('repeatValue').innerText=this.value">
266
+ </div>
267
+ <div class="about-card" style="flex-direction:row; align-items: center;">
268
+ <label style="margin-right: 10px;" for="duration">Natural Input :</label>
269
+
270
+ <label class="switch">
271
+ <input type="checkbox" id="natInp" unchecked>
272
+ <span class="slider round"></span>
273
+ </label>
274
+ </div>
275
  </form>
276
  </section>
277
  <div class="bottom-nav">
 
657
  </script>
658
 
659
  <script type="module">
660
+ document.getElementById("info-").addEventListener("click", switchPage.bind(null, "info-"));
661
  document.getElementById("home-").addEventListener("click", switchPage.bind(null, "home-"));
662
  document.getElementById("settings-").addEventListener("click", switchPage.bind(null, "settings-"));
663
 
 
669
  let webcamRunning = false;
670
  var time_since_letter = 0
671
  var last_letter_time = 0
672
+ var maxPercentage = 1
673
+
674
+ function inputFrequency() {
675
+ return document.getElementById('duration').value
676
+ }
677
+ function repeatBuffer() {
678
+ return document.getElementById('repeat').value
679
+ }
680
+ document.getElementById('durationValue').innerText = inputFrequency()
681
+ document.getElementById('repeatValue').innerText = repeatBuffer()
682
  var is_first_run = 1
683
  const letter_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"]
684
  const phrase_list = [" Good", " Hello", " How're", " I'm", " Thanks", " You"]
 
690
  const vision = await FilesetResolver.forVisionTasks("https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.0/wasm"); // This doesnt really matter as this is already imported somewhere else, and the code runs fine without the request
691
  handLandmarker = await HandLandmarker.createFromOptions(vision, {
692
  baseOptions: {
693
+ // modelAssetPath: `http://127.0.0.1:8125/assets/static/hand_landmarker.task`, // For Android
694
  modelAssetPath: `https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task`, // For Web
695
  delegate: "GPU"
696
  },
 
726
  }
727
  })
728
  var global_res = 0;
729
+ var global_cres = ''
730
  const video = document.getElementById("webcam");
731
  const canvasElement = document.getElementById("output_canvas");
732
  const canvasCtx = canvasElement.getContext("2d", { willReadFrequently: true });
 
861
  }
862
  canvasCtx.save();
863
  canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
864
+
865
  if (is_first_run == 1) {
866
  var elem_rect = document.getElementById("output_canvas").getBoundingClientRect()
867
  console.log(elem_rect.height | 0);
 
872
 
873
  if (results.landmarks && results.handednesses[0]) {
874
  var current_time = Math.round(Date.now())
875
+
876
  if (results.handednesses[0][0].categoryName == "Left") {
877
+ if (!Array.from(document.getElementById('modeSelector').classList).includes('right')) {
878
+ annotateImage()
879
  }
880
  canvasCtx.drawImage(video, 0, 0, canvasElement.width, (video.videoHeight / video.videoWidth) * canvasElement.width)
881
+ annotateImage(Array.from(document.getElementById('modeSelector').classList).includes('right'))
882
  console.log("LEFT")
883
  //detectSign()
884
  } else {
 
890
 
891
 
892
  if (previous_result == current_result) {
893
+ if (current_time - last_letter_time > getNaturalLength(" ")) {
894
  last_letter_time = current_time
895
  word_list.push(" ")
896
  triggerPulse()
 
902
  last_letter_time = current_time
903
  }
904
  }
905
+ document.getElementById("predicted_result").style.width = String((current_time - last_letter_time) / getNaturalLength(global_cres) * 100) + "%"
906
  }
907
  else {
908
  canvasCtx.drawImage(video, 0, 0, canvasElement.width, (video.videoHeight / video.videoWidth) * canvasElement.width)
 
932
  }
933
 
934
  canvasCtx.restore();
935
+ // Keep predicting
936
  if (webcamRunning === true) {
937
  window.requestAnimationFrame(predictWebcam);
938
  }
939
  }
940
+ function annotateImage(firstA = true) {
941
 
942
  //console.log(results.landmarks)
943
  if (results.landmarks[0]) {
 
985
  if (crop_bottom > image_height) {
986
  crop_bottom = image_height
987
  }
988
+ if (firstA == true) {
989
+ canvasCtx.beginPath();
990
+ canvasCtx.rect(crop_left, crop_top, crop_right - crop_left, crop_bottom - crop_top);
991
+ canvasCtx.stroke();
992
+ if (!Array.from(document.getElementById("modeSelector").classList).includes('right')) {
993
+ canvasCtx.fillStyle = "#ffffff"
994
+ canvasCtx.fill()
995
+ }
996
+
997
+ } else {
998
+ canvasCtx.beginPath();
999
+ canvasCtx.rect(crop_left, crop_top, crop_right - crop_left, crop_bottom - crop_top);
1000
+ canvasCtx.stroke();
1001
  }
1002
+
 
 
 
 
 
1003
 
1004
 
1005
  }
 
1017
  const zValues = hand.map(node => node.z);
1018
  const maxZ = Math.max.apply(null, zValues)
1019
  const minZ = Math.min.apply(null, zValues)
1020
+ const zRange = maxZ - minZ
1021
  hand.forEach(node => {
1022
  node.z = ((node.z - minZ) / zRange) * 255
1023
  });
 
1091
  drawLandmarks(canvasCtx, hand[17], '#ff3030'); // Pinky palm (17)
1092
 
1093
  // Crop Canvas
1094
+ if (firstA == true) {
1095
+ cropCanvas(canvasElement, crop_left, crop_top, crop_right - crop_left, crop_bottom - crop_top)
1096
  }
1097
  }
1098
  // Add more drawing calls for each landmark collection as needed
 
1123
 
1124
  predict(tf.expandDims(predictionInput, 0));
1125
  }
1126
+ function getNaturalLength(letter) {
1127
+ console.log('i got', letter, word_list[word_list.length - 1])
1128
+ if (document.getElementById("natInp").checked) {
1129
+ console.log('naturally:')
1130
+ if (letter != word_list[word_list.length - 1]) {
1131
+ return ((inputFrequency()) * (1 / (maxPercentage / 100)))
1132
+ } else {
1133
+ console.log("penalty!")
1134
+ var rb = Number(repeatBuffer())
1135
+ return ((inputFrequency()*(80/100))+400)
1136
+ }
1137
+ } else {
1138
+ console.log('stably:')
1139
+ if (letter != word_list[word_list.length - 1]) {
1140
+ return ((inputFrequency()))
1141
+ } else {
1142
+ console.log("penalty!")
1143
+ var rb = Number(repeatBuffer())
1144
+ return ((inputFrequency()*(80/100))+rb)
1145
+ }
1146
+ }
1147
+ }
1148
+ function mapLogitsToPercentage(logits) {
1149
+ // Apply ceiling of 260
1150
+ const cappedLogits = logits.map(value => Math.min(value, 260));
1151
+
1152
+ // Map the values from 0-260 to 0-100
1153
+ const mappedPercentages = cappedLogits.map(value => (value / 260) * 100);
1154
+
1155
+ return mappedPercentages;
1156
+ }
1157
+
1158
+
1159
  async function predict(inputTensor) {
1160
 
1161
  console.log(index_list[0])
1162
  objectDetector.then(function (res) {
1163
+
1164
  var prediction = res.predict(inputTensor);
1165
+
1166
  var outputArray = prediction.dataSync(); // Get the output as an array
1167
+ var percentages = mapLogitsToPercentage(outputArray)
1168
+ maxPercentage = Math.max(...percentages)
1169
+ document.getElementById('predicted_result').style.opacity = (maxPercentage+30)+'%'
1170
+
1171
+ var predictedClass = percentages.indexOf(Math.max(...percentages)); // Get the index
1172
+
1173
  var current_result = index_list[predictedClass]
1174
+ global_cres = current_result
1175
  var previous_result = document.getElementById("predicted_result").innerText
1176
  document.getElementById("predicted_result").innerText = current_result
1177
  var current_time = Math.round(Date.now())
 
1180
  }
1181
  console.log("p:", previous_result, "c:", current_result)
1182
  if (previous_result == current_result) {
1183
+
1184
+ if (current_time - last_letter_time > getNaturalLength(current_result)) {
1185
  last_letter_time = current_time
1186
  word_list.push(current_result)
1187
  triggerPulse()
 
1216
  var image_width = canvasElement.width
1217
 
1218
  canvasCtx.strokeStyle = strokeColor;
1219
+ canvasCtx.lineWidth = strokeWidth - 1;
1220
  canvasCtx.beginPath();
1221
  canvasCtx.moveTo(startNode.x * image_width, startNode.y * image_height);
1222
  canvasCtx.lineTo(endNode.x * image_width, endNode.y * image_height);
 
1259
  resultWrapper.addEventListener('animationend', () => {
1260
  resultWrapper.classList.remove('pulse');
1261
  }, { once: true });*/
1262
+ }
1263
+ </script>
1264
 
1265
 
1266