Spaces:
Sleeping
Sleeping
File size: 17,667 Bytes
a98230c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | <!-- CONFIG_HASH: 699e5e95747aae42d452fa7b4d557076_51f6085f563f5d680c0377ce351f17b0 -->
<!-- Generated annotation layout file -->
<!-- This file was automatically generated based on the annotation schemes in your config -->
<!-- You can customize this file to modify the layout of your annotation interface -->
<!-- Changes to this file will be preserved across server restarts -->
<div class="annotation_schema">
<form id="object_detection" class="annotation-form image-annotation" action="javascript:void(0)">
<fieldset schema="object_detection">
<legend>Draw boxes around objects you see in the image. Use the polygon tool for irregular shapes.</legend>
<!-- Image Annotation Container -->
<div class="image-annotation-container" data-schema="object_detection" data-ai-enabled="false">
<!-- Toolbar -->
<div class="image-annotation-toolbar">
<!-- Tool buttons -->
<div class="tool-group">
<span class="tool-group-label">Tools:</span>
<button type="button" class="tool-btn" data-tool="bbox" title="Bounding Box (B)">□ Box</button>
<button type="button" class="tool-btn" data-tool="polygon" title="Polygon (P)">⬡ Polygon</button>
</div>
<!-- Label selector -->
<div class="label-group">
<span class="tool-group-label">Label:</span>
<button type="button" class="label-btn" data-label="person" data-color="#FF6B6B" title="person (1)" style="--label-color: #FF6B6B;"><span class="label-color-dot" style="background-color: #FF6B6B;"></span>person</button>
<button type="button" class="label-btn" data-label="vehicle" data-color="#4ECDC4" title="vehicle (2)" style="--label-color: #4ECDC4;"><span class="label-color-dot" style="background-color: #4ECDC4;"></span>vehicle</button>
<button type="button" class="label-btn" data-label="animal" data-color="#45B7D1" title="animal (3)" style="--label-color: #45B7D1;"><span class="label-color-dot" style="background-color: #45B7D1;"></span>animal</button>
<button type="button" class="label-btn" data-label="object" data-color="#96CEB4" title="object (4)" style="--label-color: #96CEB4;"><span class="label-color-dot" style="background-color: #96CEB4;"></span>object</button>
</div>
<!-- Zoom controls -->
<div class="zoom-group">
<button type="button" class="zoom-btn" data-action="zoom-in" title="Zoom In (+)">+</button>
<button type="button" class="zoom-btn" data-action="zoom-out" title="Zoom Out (-)">-</button>
<button type="button" class="zoom-btn" data-action="zoom-fit" title="Fit to View (0)">Fit</button>
<button type="button" class="zoom-btn" data-action="zoom-reset" title="Reset Zoom">100%</button>
</div>
<!-- Edit controls -->
<div class="edit-group">
<button type="button" class="edit-btn" data-action="undo" title="Undo (Ctrl+Z)">Undo</button>
<button type="button" class="edit-btn" data-action="redo" title="Redo (Ctrl+Shift+Z)">Redo</button>
<button type="button" class="edit-btn delete-btn" data-action="delete" title="Delete Selected (Del)">Delete</button>
</div>
<!-- Brush size control (shown when brush/eraser selected) -->
<div class="brush-size-group" style="display: none;">
<span class="tool-group-label">Size:</span>
<input type="range" class="brush-size-slider" min="1" max="100" value="20" title="Brush Size">
<span class="brush-size-value">20</span>
</div>
<!-- Annotation count -->
<div class="count-group">
<span class="annotation-count">Annotations: <span class="count-value">0</span></span>
</div>
</div>
<!-- Canvas wrapper -->
<div class="canvas-wrapper">
<canvas id="canvas-object_detection" class="annotation-canvas"></canvas>
<!-- Mask canvas for segmentation (overlaid on top) -->
<canvas id="mask-canvas-object_detection" class="mask-canvas" style="display: none;"></canvas>
</div>
<!-- Hidden input for storing annotation data -->
<input type="hidden"
name="object_detection"
id="input-object_detection"
class="annotation-data-input"
value="">
<!-- Hidden input for storing mask data (RLE encoded) -->
<input type="hidden"
name="object_detection_masks"
id="mask-input-object_detection"
class="mask-data-input"
value="">
</div>
<!-- Initialize the annotation manager -->
<script>
(function() {
// Wait for DOM and dependencies
function initWhenReady() {
if (typeof ImageAnnotationManager === 'undefined') {
setTimeout(initWhenReady, 100);
return;
}
var container = document.querySelector('.image-annotation-container[data-schema="object_detection"]');
if (!container) return;
var config = {"schemaName": "object_detection", "tools": ["bbox", "polygon"], "labels": [{"name": "person", "color": "#FF6B6B", "key_value": "1"}, {"name": "vehicle", "color": "#4ECDC4", "key_value": "2"}, {"name": "animal", "color": "#45B7D1", "key_value": "3"}, {"name": "object", "color": "#96CEB4", "key_value": "4"}], "zoomEnabled": true, "panEnabled": true, "minAnnotations": 1, "maxAnnotations": null, "freeformBrushSize": 5, "freeformSimplify": true, "brushSize": 20, "eraserSize": 20, "maskOpacity": 0.5, "aiSupport": false, "aiFeatures": {}, "sourceField": ""};
var canvasId = 'canvas-object_detection';
var inputId = 'input-object_detection';
// Get image URL from the instance display
// Priority: 1) data-image-url on #text-content, 2) img src, 3) text content itself
var instanceContainer = document.getElementById('instance-text');
console.log('[ImageAnnotation] Instance container:', instanceContainer);
var textContent = instanceContainer ? instanceContainer.querySelector('#text-content') : null;
console.log('[ImageAnnotation] Text content element:', textContent);
var imageUrl = null;
// Method 1: Check data-image-url attribute (set by template when has_image_annotation=true)
if (textContent) {
imageUrl = textContent.getAttribute('data-image-url');
if (imageUrl) {
console.log('[ImageAnnotation] Found URL from data-image-url:', imageUrl);
}
}
// Method 2: Fallback to looking for an img element with data-source-url or src
if (!imageUrl && instanceContainer) {
var imgElement = instanceContainer.querySelector('img');
if (imgElement) {
imageUrl = imgElement.getAttribute('data-source-url') || imgElement.src;
console.log('[ImageAnnotation] Found URL from img element:', imageUrl);
}
}
// Method 3: If text content looks like a URL, use it directly
if (!imageUrl && textContent) {
var textVal = textContent.textContent.trim();
if (textVal.match(/^https?:\/\/.+\.(jpg|jpeg|png|gif|webp|svg)/i)) {
imageUrl = textVal;
console.log('[ImageAnnotation] Found URL from text content:', imageUrl);
}
}
// Method 4: Check source_field in instance data (via display fields)
if (!imageUrl && config.sourceField) {
var displayFields = document.querySelectorAll('[data-field-key="' + config.sourceField + '"]');
displayFields.forEach(function(field) {
var url = field.getAttribute('data-source-url') || field.getAttribute('src');
if (url && !imageUrl) {
imageUrl = url;
console.log('[ImageAnnotation] Found URL from source_field display:', imageUrl);
}
});
}
if (!imageUrl) {
console.error('[ImageAnnotation] No image URL found! Check that the instance data contains an image URL.');
}
// Initialize manager
console.log('Initializing ImageAnnotationManager with canvas:', canvasId);
var manager = new ImageAnnotationManager(canvasId, inputId, config);
// Store reference on container
container.annotationManager = manager;
// Load image if available
if (imageUrl) {
console.log('Calling loadImage with:', imageUrl);
manager.loadImage(imageUrl);
} else {
console.warn('No image URL found for annotation');
}
// Wire up toolbar buttons
container.querySelectorAll('.tool-btn').forEach(function(btn) {
btn.addEventListener('click', function() {
var tool = this.dataset.tool;
manager.setTool(tool);
container.querySelectorAll('.tool-btn').forEach(function(b) {
b.classList.remove('active');
});
this.classList.add('active');
// Show/hide brush size control for brush/eraser tools
var brushSizeGroup = container.querySelector('.brush-size-group');
if (brushSizeGroup) {
brushSizeGroup.style.display = (tool === 'brush' || tool === 'eraser') ? 'flex' : 'none';
}
});
});
// Wire up brush size slider
var brushSlider = container.querySelector('.brush-size-slider');
var brushSizeValue = container.querySelector('.brush-size-value');
if (brushSlider) {
brushSlider.addEventListener('input', function() {
var size = parseInt(this.value);
if (brushSizeValue) brushSizeValue.textContent = size;
manager.setBrushSize(size);
});
}
container.querySelectorAll('.label-btn').forEach(function(btn) {
btn.addEventListener('click', function() {
var label = this.dataset.label;
var color = this.dataset.color;
manager.setLabel(label, color);
container.querySelectorAll('.label-btn').forEach(function(b) {
b.classList.remove('active');
});
this.classList.add('active');
});
});
container.querySelectorAll('.zoom-btn').forEach(function(btn) {
btn.addEventListener('click', function() {
var action = this.dataset.action;
if (action === 'zoom-in') manager.zoom(1.2);
else if (action === 'zoom-out') manager.zoom(0.8);
else if (action === 'zoom-fit') manager.zoomFit();
else if (action === 'zoom-reset') manager.zoomReset();
});
});
container.querySelectorAll('.edit-btn').forEach(function(btn) {
btn.addEventListener('click', function() {
var action = this.dataset.action;
if (action === 'undo') manager.undo();
else if (action === 'redo') manager.redo();
else if (action === 'delete') manager.deleteSelected();
});
});
// Set default tool and label
var firstToolBtn = container.querySelector('.tool-btn');
if (firstToolBtn) firstToolBtn.click();
var firstLabelBtn = container.querySelector('.label-btn');
if (firstLabelBtn) firstLabelBtn.click();
// Update count display
manager.onAnnotationChange = function(count) {
var countEl = container.querySelector('.count-value');
if (countEl) countEl.textContent = count;
};
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initWhenReady);
} else {
initWhenReady();
}
})();
</script>
</fieldset>
</form>
<form id="image_quality" class="annotation-form radio shadcn-radio-container" action="javascript:void(0)" data-annotation-id="1" data-annotation-type="radio" data-schema-name="image_quality" data-grid-columns="1">
<fieldset schema="image_quality">
<legend class="shadcn-radio-title">How clear is this image?</legend>
<div class="shadcn-radio-options">
<div class="shadcn-radio-option">
<input class="image_quality shadcn-radio-input annotation-input"
type="radio"
id="image_quality_Very clear_radio"
name="image_quality"
value="Very clear"
selection_constraint="single"
schema="image_quality"
label_name="Very clear"
onclick="onlyOne(this);registerAnnotation(this);"
validation=""
data-key="c">
<label for="image_quality_Very clear_radio" class="shadcn-radio-label" >Very Clear <span class="keybinding-badge">C</span></label>
</div>
<div class="shadcn-radio-option">
<input class="image_quality shadcn-radio-input annotation-input"
type="radio"
id="image_quality_Somewhat clear_radio"
name="image_quality"
value="Somewhat clear"
selection_constraint="single"
schema="image_quality"
label_name="Somewhat clear"
onclick="onlyOne(this);registerAnnotation(this);"
validation=""
data-key="s">
<label for="image_quality_Somewhat clear_radio" class="shadcn-radio-label" >Somewhat Clear <span class="keybinding-badge">S</span></label>
</div>
<div class="shadcn-radio-option">
<input class="image_quality shadcn-radio-input annotation-input"
type="radio"
id="image_quality_Blurry_radio"
name="image_quality"
value="Blurry"
selection_constraint="single"
schema="image_quality"
label_name="Blurry"
onclick="onlyOne(this);registerAnnotation(this);"
validation=""
data-key="b">
<label for="image_quality_Blurry_radio" class="shadcn-radio-label" >Blurry <span class="keybinding-badge">B</span></label>
</div>
</div></fieldset></form>
</div>
|