Spaces:
Running
Running
edg case added
Browse files- .gitignore +2 -1
- comic_panel_extractor/static/annotator.html +129 -77
.gitignore
CHANGED
|
@@ -217,4 +217,5 @@ temp.py
|
|
| 217 |
test*.jpg
|
| 218 |
yolo_output/
|
| 219 |
*:Zone.Identifier
|
| 220 |
-
comic_panel_extractor/best.pt
|
|
|
|
|
|
| 217 |
test*.jpg
|
| 218 |
yolo_output/
|
| 219 |
*:Zone.Identifier
|
| 220 |
+
comic_panel_extractor/best.pt
|
| 221 |
+
*.pt
|
comic_panel_extractor/static/annotator.html
CHANGED
|
@@ -146,7 +146,8 @@
|
|
| 146 |
margin-bottom: 6px;
|
| 147 |
}
|
| 148 |
|
| 149 |
-
.form-select,
|
|
|
|
| 150 |
width: 100%;
|
| 151 |
padding: 10px 12px;
|
| 152 |
border: 1px solid #d1d5db;
|
|
@@ -156,7 +157,8 @@
|
|
| 156 |
transition: all 0.2s;
|
| 157 |
}
|
| 158 |
|
| 159 |
-
.form-select:focus,
|
|
|
|
| 160 |
outline: none;
|
| 161 |
border-color: #4299e1;
|
| 162 |
box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.1);
|
|
@@ -392,6 +394,7 @@
|
|
| 392 |
transform: translateX(100%);
|
| 393 |
opacity: 0;
|
| 394 |
}
|
|
|
|
| 395 |
to {
|
| 396 |
transform: translateX(0);
|
| 397 |
opacity: 1;
|
|
@@ -439,13 +442,13 @@
|
|
| 439 |
.main-container {
|
| 440 |
flex-direction: column;
|
| 441 |
}
|
| 442 |
-
|
| 443 |
.sidebar {
|
| 444 |
width: 100%;
|
| 445 |
height: auto;
|
| 446 |
max-height: 300px;
|
| 447 |
}
|
| 448 |
-
|
| 449 |
.canvas-area {
|
| 450 |
height: calc(100vh - 372px);
|
| 451 |
}
|
|
@@ -478,7 +481,7 @@
|
|
| 478 |
<!-- Image Selection -->
|
| 479 |
<div class="sidebar-section">
|
| 480 |
<div class="section-title">Image Selection</div>
|
| 481 |
-
|
| 482 |
<div class="image-nav">
|
| 483 |
<button class="btn btn-ghost btn-sm" id="prevBtn" disabled>
|
| 484 |
← Prev
|
|
@@ -579,7 +582,7 @@
|
|
| 579 |
Click and drag to create annotation boxes • Select boxes to move or resize
|
| 580 |
</span>
|
| 581 |
</div>
|
| 582 |
-
|
| 583 |
<div class="canvas-container">
|
| 584 |
<canvas id="annotationCanvas" style="display: none;"></canvas>
|
| 585 |
<div id="canvasPlaceholder" class="canvas-placeholder">
|
|
@@ -918,22 +921,36 @@
|
|
| 918 |
if (this.isDrawing && this.currentBox) {
|
| 919 |
// Only add box if it has meaningful size
|
| 920 |
if (Math.abs(this.currentBox.width) > 10 && Math.abs(this.currentBox.height) > 10) {
|
| 921 |
-
|
| 922 |
-
|
| 923 |
-
|
| 924 |
-
|
| 925 |
-
|
| 926 |
-
|
| 927 |
-
|
| 928 |
-
|
| 929 |
-
|
| 930 |
-
|
| 931 |
-
|
| 932 |
-
|
| 933 |
-
|
| 934 |
-
|
| 935 |
-
|
| 936 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 937 |
}
|
| 938 |
this.currentBox = null;
|
| 939 |
}
|
|
@@ -946,6 +963,7 @@
|
|
| 946 |
this.drawCanvas();
|
| 947 |
}
|
| 948 |
|
|
|
|
| 949 |
updateCursor(x, y) {
|
| 950 |
if (this.selectedBoxIndex >= 0) {
|
| 951 |
const handle = this.getResizeHandle(x, y);
|
|
@@ -1010,61 +1028,80 @@
|
|
| 1010 |
case 'nw':
|
| 1011 |
const newWidth = box.width + (box.left - x);
|
| 1012 |
const newHeight = box.height + (box.top - y);
|
|
|
|
|
|
|
|
|
|
| 1013 |
if (newWidth > 10 && newHeight > 10) {
|
| 1014 |
-
box.width = newWidth;
|
| 1015 |
-
box.height = newHeight;
|
| 1016 |
-
box.left =
|
| 1017 |
-
box.top =
|
| 1018 |
}
|
| 1019 |
break;
|
|
|
|
| 1020 |
case 'ne':
|
| 1021 |
-
const neWidth = x - box.left;
|
| 1022 |
const neHeight = box.height + (box.top - y);
|
|
|
|
|
|
|
| 1023 |
if (neWidth > 10 && neHeight > 10) {
|
| 1024 |
box.width = neWidth;
|
| 1025 |
-
box.height = neHeight;
|
| 1026 |
-
box.top =
|
| 1027 |
}
|
| 1028 |
break;
|
|
|
|
| 1029 |
case 'sw':
|
| 1030 |
const swWidth = box.width + (box.left - x);
|
| 1031 |
-
const swHeight = y - box.top;
|
|
|
|
|
|
|
| 1032 |
if (swWidth > 10 && swHeight > 10) {
|
| 1033 |
-
box.width = swWidth;
|
| 1034 |
box.height = swHeight;
|
| 1035 |
-
box.left =
|
| 1036 |
}
|
| 1037 |
break;
|
|
|
|
| 1038 |
case 'se':
|
| 1039 |
-
const seWidth = x - box.left;
|
| 1040 |
-
const seHeight = y - box.top;
|
|
|
|
| 1041 |
if (seWidth > 10 && seHeight > 10) {
|
| 1042 |
box.width = seWidth;
|
| 1043 |
box.height = seHeight;
|
| 1044 |
}
|
| 1045 |
break;
|
|
|
|
| 1046 |
case 'n':
|
| 1047 |
const nHeight = box.height + (box.top - y);
|
|
|
|
|
|
|
| 1048 |
if (nHeight > 10) {
|
| 1049 |
-
box.height = nHeight;
|
| 1050 |
-
box.top =
|
| 1051 |
}
|
| 1052 |
break;
|
|
|
|
| 1053 |
case 's':
|
| 1054 |
-
const sHeight = y - box.top;
|
| 1055 |
if (sHeight > 10) {
|
| 1056 |
box.height = sHeight;
|
| 1057 |
}
|
| 1058 |
break;
|
|
|
|
| 1059 |
case 'w':
|
| 1060 |
const wWidth = box.width + (box.left - x);
|
|
|
|
|
|
|
| 1061 |
if (wWidth > 10) {
|
| 1062 |
-
box.width = wWidth;
|
| 1063 |
-
box.left =
|
| 1064 |
}
|
| 1065 |
break;
|
|
|
|
| 1066 |
case 'e':
|
| 1067 |
-
const eWidth = x - box.left;
|
| 1068 |
if (eWidth > 10) {
|
| 1069 |
box.width = eWidth;
|
| 1070 |
}
|
|
@@ -1075,16 +1112,23 @@
|
|
| 1075 |
this.updateSelectedBoxInfo();
|
| 1076 |
}
|
| 1077 |
|
|
|
|
| 1078 |
moveBox(boxIndex, deltaX, deltaY) {
|
| 1079 |
if (boxIndex < 0 || boxIndex >= this.boxes.length) return;
|
| 1080 |
|
| 1081 |
const box = this.boxes[boxIndex];
|
| 1082 |
-
box.left += deltaX;
|
| 1083 |
-
box.top += deltaY;
|
| 1084 |
|
| 1085 |
-
//
|
| 1086 |
-
|
| 1087 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1088 |
|
| 1089 |
box.saved = false;
|
| 1090 |
this.updateSelectedBoxInfo();
|
|
@@ -1119,27 +1163,27 @@
|
|
| 1119 |
}
|
| 1120 |
} else {
|
| 1121 |
// Regular arrow keys for moving
|
| 1122 |
-
|
| 1123 |
-
|
| 1124 |
-
|
| 1125 |
-
|
| 1126 |
-
|
| 1127 |
-
|
| 1128 |
-
|
| 1129 |
-
|
| 1130 |
-
|
| 1131 |
-
|
| 1132 |
-
|
| 1133 |
-
|
| 1134 |
-
|
| 1135 |
-
|
| 1136 |
-
|
| 1137 |
-
|
| 1138 |
-
|
| 1139 |
-
|
| 1140 |
-
|
| 1141 |
-
|
| 1142 |
-
|
| 1143 |
}
|
| 1144 |
}
|
| 1145 |
|
|
@@ -1164,25 +1208,32 @@
|
|
| 1164 |
if (this.selectedBoxIndex < 0) return;
|
| 1165 |
|
| 1166 |
const box = this.boxes[this.selectedBoxIndex];
|
| 1167 |
-
|
| 1168 |
// Calculate new dimensions
|
| 1169 |
-
|
| 1170 |
-
|
| 1171 |
|
| 1172 |
-
//
|
| 1173 |
if (newWidth >= 10) {
|
|
|
|
|
|
|
| 1174 |
box.width = newWidth;
|
| 1175 |
-
|
| 1176 |
-
|
| 1177 |
-
|
|
|
|
| 1178 |
}
|
| 1179 |
}
|
| 1180 |
|
|
|
|
| 1181 |
if (newHeight >= 10) {
|
|
|
|
|
|
|
| 1182 |
box.height = newHeight;
|
| 1183 |
-
|
| 1184 |
-
|
| 1185 |
-
|
|
|
|
| 1186 |
}
|
| 1187 |
}
|
| 1188 |
|
|
@@ -1191,6 +1242,7 @@
|
|
| 1191 |
this.drawCanvas();
|
| 1192 |
}
|
| 1193 |
|
|
|
|
| 1194 |
deleteSelectedBox() {
|
| 1195 |
if (this.selectedBoxIndex >= 0) {
|
| 1196 |
this.boxes.splice(this.selectedBoxIndex, 1);
|
|
@@ -1385,4 +1437,4 @@
|
|
| 1385 |
</script>
|
| 1386 |
</body>
|
| 1387 |
|
| 1388 |
-
</html>
|
|
|
|
| 146 |
margin-bottom: 6px;
|
| 147 |
}
|
| 148 |
|
| 149 |
+
.form-select,
|
| 150 |
+
.form-input {
|
| 151 |
width: 100%;
|
| 152 |
padding: 10px 12px;
|
| 153 |
border: 1px solid #d1d5db;
|
|
|
|
| 157 |
transition: all 0.2s;
|
| 158 |
}
|
| 159 |
|
| 160 |
+
.form-select:focus,
|
| 161 |
+
.form-input:focus {
|
| 162 |
outline: none;
|
| 163 |
border-color: #4299e1;
|
| 164 |
box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.1);
|
|
|
|
| 394 |
transform: translateX(100%);
|
| 395 |
opacity: 0;
|
| 396 |
}
|
| 397 |
+
|
| 398 |
to {
|
| 399 |
transform: translateX(0);
|
| 400 |
opacity: 1;
|
|
|
|
| 442 |
.main-container {
|
| 443 |
flex-direction: column;
|
| 444 |
}
|
| 445 |
+
|
| 446 |
.sidebar {
|
| 447 |
width: 100%;
|
| 448 |
height: auto;
|
| 449 |
max-height: 300px;
|
| 450 |
}
|
| 451 |
+
|
| 452 |
.canvas-area {
|
| 453 |
height: calc(100vh - 372px);
|
| 454 |
}
|
|
|
|
| 481 |
<!-- Image Selection -->
|
| 482 |
<div class="sidebar-section">
|
| 483 |
<div class="section-title">Image Selection</div>
|
| 484 |
+
|
| 485 |
<div class="image-nav">
|
| 486 |
<button class="btn btn-ghost btn-sm" id="prevBtn" disabled>
|
| 487 |
← Prev
|
|
|
|
| 582 |
Click and drag to create annotation boxes • Select boxes to move or resize
|
| 583 |
</span>
|
| 584 |
</div>
|
| 585 |
+
|
| 586 |
<div class="canvas-container">
|
| 587 |
<canvas id="annotationCanvas" style="display: none;"></canvas>
|
| 588 |
<div id="canvasPlaceholder" class="canvas-placeholder">
|
|
|
|
| 921 |
if (this.isDrawing && this.currentBox) {
|
| 922 |
// Only add box if it has meaningful size
|
| 923 |
if (Math.abs(this.currentBox.width) > 10 && Math.abs(this.currentBox.height) > 10) {
|
| 924 |
+
let left = Math.min(this.startX, this.startX + this.currentBox.width);
|
| 925 |
+
let top = Math.min(this.startY, this.startY + this.currentBox.height);
|
| 926 |
+
let width = Math.abs(this.currentBox.width);
|
| 927 |
+
let height = Math.abs(this.currentBox.height);
|
| 928 |
+
|
| 929 |
+
// Apply boundary conditions
|
| 930 |
+
left = Math.max(0, left);
|
| 931 |
+
top = Math.max(0, top);
|
| 932 |
+
width = Math.min(width, this.originalWidth - left);
|
| 933 |
+
height = Math.min(height, this.originalHeight - top);
|
| 934 |
+
|
| 935 |
+
// Only create box if it still has valid dimensions after boundary check
|
| 936 |
+
if (width > 10 && height > 10) {
|
| 937 |
+
const box = {
|
| 938 |
+
left: left,
|
| 939 |
+
top: top,
|
| 940 |
+
width: width,
|
| 941 |
+
height: height,
|
| 942 |
+
type: 'rect',
|
| 943 |
+
stroke: '#ff0000',
|
| 944 |
+
strokeWidth: 3,
|
| 945 |
+
fill: 'rgba(255, 0, 0, 0.3)',
|
| 946 |
+
saved: false
|
| 947 |
+
};
|
| 948 |
+
|
| 949 |
+
this.boxes.push(box);
|
| 950 |
+
this.selectedBoxIndex = this.boxes.length - 1;
|
| 951 |
+
document.getElementById('boxCount').textContent = this.boxes.length;
|
| 952 |
+
this.updateSelectedBoxInfo();
|
| 953 |
+
}
|
| 954 |
}
|
| 955 |
this.currentBox = null;
|
| 956 |
}
|
|
|
|
| 963 |
this.drawCanvas();
|
| 964 |
}
|
| 965 |
|
| 966 |
+
|
| 967 |
updateCursor(x, y) {
|
| 968 |
if (this.selectedBoxIndex >= 0) {
|
| 969 |
const handle = this.getResizeHandle(x, y);
|
|
|
|
| 1028 |
case 'nw':
|
| 1029 |
const newWidth = box.width + (box.left - x);
|
| 1030 |
const newHeight = box.height + (box.top - y);
|
| 1031 |
+
const newLeft = Math.max(0, x);
|
| 1032 |
+
const newTop = Math.max(0, y);
|
| 1033 |
+
|
| 1034 |
if (newWidth > 10 && newHeight > 10) {
|
| 1035 |
+
box.width = Math.min(newWidth, box.left + box.width);
|
| 1036 |
+
box.height = Math.min(newHeight, box.top + box.height);
|
| 1037 |
+
box.left = newLeft;
|
| 1038 |
+
box.top = newTop;
|
| 1039 |
}
|
| 1040 |
break;
|
| 1041 |
+
|
| 1042 |
case 'ne':
|
| 1043 |
+
const neWidth = Math.min(x - box.left, this.originalWidth - box.left);
|
| 1044 |
const neHeight = box.height + (box.top - y);
|
| 1045 |
+
const neTop = Math.max(0, y);
|
| 1046 |
+
|
| 1047 |
if (neWidth > 10 && neHeight > 10) {
|
| 1048 |
box.width = neWidth;
|
| 1049 |
+
box.height = Math.min(neHeight, box.top + box.height);
|
| 1050 |
+
box.top = neTop;
|
| 1051 |
}
|
| 1052 |
break;
|
| 1053 |
+
|
| 1054 |
case 'sw':
|
| 1055 |
const swWidth = box.width + (box.left - x);
|
| 1056 |
+
const swHeight = Math.min(y - box.top, this.originalHeight - box.top);
|
| 1057 |
+
const swLeft = Math.max(0, x);
|
| 1058 |
+
|
| 1059 |
if (swWidth > 10 && swHeight > 10) {
|
| 1060 |
+
box.width = Math.min(swWidth, box.left + box.width);
|
| 1061 |
box.height = swHeight;
|
| 1062 |
+
box.left = swLeft;
|
| 1063 |
}
|
| 1064 |
break;
|
| 1065 |
+
|
| 1066 |
case 'se':
|
| 1067 |
+
const seWidth = Math.min(x - box.left, this.originalWidth - box.left);
|
| 1068 |
+
const seHeight = Math.min(y - box.top, this.originalHeight - box.top);
|
| 1069 |
+
|
| 1070 |
if (seWidth > 10 && seHeight > 10) {
|
| 1071 |
box.width = seWidth;
|
| 1072 |
box.height = seHeight;
|
| 1073 |
}
|
| 1074 |
break;
|
| 1075 |
+
|
| 1076 |
case 'n':
|
| 1077 |
const nHeight = box.height + (box.top - y);
|
| 1078 |
+
const nTop = Math.max(0, y);
|
| 1079 |
+
|
| 1080 |
if (nHeight > 10) {
|
| 1081 |
+
box.height = Math.min(nHeight, box.top + box.height);
|
| 1082 |
+
box.top = nTop;
|
| 1083 |
}
|
| 1084 |
break;
|
| 1085 |
+
|
| 1086 |
case 's':
|
| 1087 |
+
const sHeight = Math.min(y - box.top, this.originalHeight - box.top);
|
| 1088 |
if (sHeight > 10) {
|
| 1089 |
box.height = sHeight;
|
| 1090 |
}
|
| 1091 |
break;
|
| 1092 |
+
|
| 1093 |
case 'w':
|
| 1094 |
const wWidth = box.width + (box.left - x);
|
| 1095 |
+
const wLeft = Math.max(0, x);
|
| 1096 |
+
|
| 1097 |
if (wWidth > 10) {
|
| 1098 |
+
box.width = Math.min(wWidth, box.left + box.width);
|
| 1099 |
+
box.left = wLeft;
|
| 1100 |
}
|
| 1101 |
break;
|
| 1102 |
+
|
| 1103 |
case 'e':
|
| 1104 |
+
const eWidth = Math.min(x - box.left, this.originalWidth - box.left);
|
| 1105 |
if (eWidth > 10) {
|
| 1106 |
box.width = eWidth;
|
| 1107 |
}
|
|
|
|
| 1112 |
this.updateSelectedBoxInfo();
|
| 1113 |
}
|
| 1114 |
|
| 1115 |
+
|
| 1116 |
moveBox(boxIndex, deltaX, deltaY) {
|
| 1117 |
if (boxIndex < 0 || boxIndex >= this.boxes.length) return;
|
| 1118 |
|
| 1119 |
const box = this.boxes[boxIndex];
|
|
|
|
|
|
|
| 1120 |
|
| 1121 |
+
// Calculate new position
|
| 1122 |
+
let newLeft = box.left + deltaX;
|
| 1123 |
+
let newTop = box.top + deltaY;
|
| 1124 |
+
|
| 1125 |
+
// Apply boundary conditions
|
| 1126 |
+
newLeft = Math.max(0, Math.min(this.originalWidth - box.width, newLeft));
|
| 1127 |
+
newTop = Math.max(0, Math.min(this.originalHeight - box.height, newTop));
|
| 1128 |
+
|
| 1129 |
+
// Update box position
|
| 1130 |
+
box.left = newLeft;
|
| 1131 |
+
box.top = newTop;
|
| 1132 |
|
| 1133 |
box.saved = false;
|
| 1134 |
this.updateSelectedBoxInfo();
|
|
|
|
| 1163 |
}
|
| 1164 |
} else {
|
| 1165 |
// Regular arrow keys for moving
|
| 1166 |
+
switch (e.key) {
|
| 1167 |
+
case 'ArrowLeft':
|
| 1168 |
+
e.preventDefault();
|
| 1169 |
+
this.moveBox(this.selectedBoxIndex, -moveDistance, 0);
|
| 1170 |
+
this.drawCanvas();
|
| 1171 |
+
break;
|
| 1172 |
+
case 'ArrowRight':
|
| 1173 |
+
e.preventDefault();
|
| 1174 |
+
this.moveBox(this.selectedBoxIndex, moveDistance, 0);
|
| 1175 |
+
this.drawCanvas();
|
| 1176 |
+
break;
|
| 1177 |
+
case 'ArrowUp':
|
| 1178 |
+
e.preventDefault();
|
| 1179 |
+
this.moveBox(this.selectedBoxIndex, 0, -moveDistance);
|
| 1180 |
+
this.drawCanvas();
|
| 1181 |
+
break;
|
| 1182 |
+
case 'ArrowDown':
|
| 1183 |
+
e.preventDefault();
|
| 1184 |
+
this.moveBox(this.selectedBoxIndex, 0, moveDistance);
|
| 1185 |
+
this.drawCanvas();
|
| 1186 |
+
break;
|
| 1187 |
}
|
| 1188 |
}
|
| 1189 |
|
|
|
|
| 1208 |
if (this.selectedBoxIndex < 0) return;
|
| 1209 |
|
| 1210 |
const box = this.boxes[this.selectedBoxIndex];
|
| 1211 |
+
|
| 1212 |
// Calculate new dimensions
|
| 1213 |
+
let newWidth = box.width + deltaWidth;
|
| 1214 |
+
let newHeight = box.height + deltaHeight;
|
| 1215 |
|
| 1216 |
+
// Apply boundary conditions for width
|
| 1217 |
if (newWidth >= 10) {
|
| 1218 |
+
// Ensure box doesn't exceed original width
|
| 1219 |
+
newWidth = Math.min(newWidth, this.originalWidth - box.left);
|
| 1220 |
box.width = newWidth;
|
| 1221 |
+
|
| 1222 |
+
// Adjust left position if needed
|
| 1223 |
+
if (box.left + box.width > this.originalWidth) {
|
| 1224 |
+
box.left = this.originalWidth - box.width;
|
| 1225 |
}
|
| 1226 |
}
|
| 1227 |
|
| 1228 |
+
// Apply boundary conditions for height
|
| 1229 |
if (newHeight >= 10) {
|
| 1230 |
+
// Ensure box doesn't exceed original height
|
| 1231 |
+
newHeight = Math.min(newHeight, this.originalHeight - box.top);
|
| 1232 |
box.height = newHeight;
|
| 1233 |
+
|
| 1234 |
+
// Adjust top position if needed
|
| 1235 |
+
if (box.top + box.height > this.originalHeight) {
|
| 1236 |
+
box.top = this.originalHeight - box.height;
|
| 1237 |
}
|
| 1238 |
}
|
| 1239 |
|
|
|
|
| 1242 |
this.drawCanvas();
|
| 1243 |
}
|
| 1244 |
|
| 1245 |
+
|
| 1246 |
deleteSelectedBox() {
|
| 1247 |
if (this.selectedBoxIndex >= 0) {
|
| 1248 |
this.boxes.splice(this.selectedBoxIndex, 1);
|
|
|
|
| 1437 |
</script>
|
| 1438 |
</body>
|
| 1439 |
|
| 1440 |
+
</html>
|