Last active
February 20, 2023 11:03
-
-
Save kamranahmedse/463cc2aa2c85a3c2a91f5f0d25071ff5 to your computer and use it in GitHub Desktop.
Image annotation sample to assign pre-defined tags on different image sections
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@recogito/annotorious@latest/dist/annotorious.min.css" /> | |
<script src="https://cdn.jsdelivr.net/npm/@recogito/annotorious@latest/dist/annotorious.min.js"></script> | |
<style> | |
* { | |
margin: 0; | |
padding: 0; | |
} | |
.tag-selector-widget { | |
padding: 20px; | |
display: flex; | |
flex-wrap: wrap; | |
flex-direction: row; | |
gap: 5px; | |
} | |
.tag-selector-widget button { | |
padding: 10px; | |
border-radius: 5px !important; | |
cursor: pointer; | |
display: block; | |
border: 1px solid black; | |
background: white; | |
} | |
.tag-selector-widget button:hover, | |
.tag-selector-widget button.selected { | |
background: black; | |
color: white; | |
} | |
/* General styles for page */ | |
.container { | |
max-width: 800px; | |
margin: 40px auto; | |
} | |
.container .btn-group button { | |
padding: 10px 15px; | |
border-radius: 5px !important; | |
cursor: pointer; | |
display: block; | |
border: 1px solid black; | |
background: white; | |
color: black; | |
} | |
.container .btn-group button:hover { | |
background: black; | |
color: white; | |
} | |
.container img { | |
margin-bottom: 20px; | |
} | |
.container .btn-group { | |
display: flex; | |
flex-direction: row; | |
gap: 10px; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<img id="randomimage" src="https://i.imgur.com/3hZWzob.png" /> | |
<div class="btn-group"> | |
<button id="btn-get-annotations">Get Annotations</button> | |
<button id="btn-del-annotations">Clear Annotations</button> | |
</div> | |
</div> | |
<script> | |
// Accepts an array of possible tags to render | |
function getSelectorWidget(possibleTags) { | |
return function (args) { | |
// 1. Find a current tag setting in the annotation, if any | |
const currentTagBody = args.annotation | |
? args.annotation.bodies.find(function (b) { | |
return b.purpose == 'tagging'; | |
}) | |
: null; | |
// 2. Keep the value in a variable | |
const currentTagValue = currentTagBody ? currentTagBody.value : null; | |
// 3. Triggers callbacks on user action | |
var addTag = function (evt) { | |
if (currentTagBody) { | |
args.onUpdateBody(currentTagBody, { | |
type: 'TextualBody', | |
purpose: 'tagging', | |
value: evt.target.dataset.tag, | |
}); | |
} else { | |
args.onAppendBody({ | |
type: 'TextualBody', | |
purpose: 'tagging', | |
value: evt.target.dataset.tag, | |
}); | |
} | |
}; | |
// 4. This part renders the UI elements | |
const createButton = function (value) { | |
const button = document.createElement('button'); | |
if (value == currentTagValue) { | |
button.className = 'selected'; | |
} | |
button.dataset.tag = value; | |
button.innerText = value; | |
button.addEventListener('click', addTag); | |
return button; | |
}; | |
const container = document.createElement('div'); | |
container.className = 'tag-selector-widget'; | |
possibleTags.forEach((possibleTag) => { | |
const button = createButton(possibleTag); | |
container.appendChild(button); | |
}); | |
return container; | |
}; | |
} | |
function getRawAnnotations() { | |
return anno.getAnnotations(); | |
} | |
function getFormattedAnnotations() { | |
const annotations = anno.getAnnotations(); | |
const formattedAnnotations = []; | |
annotations.forEach((annotation) => { | |
const tagValue = annotation.body[0].value; | |
// has following format | |
// ---> xywh=pixel:68,13,253,62 | |
const rawDimensions = annotation.target.selector.value; | |
// Get x, y, width, height | |
const [, x, y, width, height] = rawDimensions.split(/[:,]/); | |
formattedAnnotations.push({ | |
tag: tagValue, | |
dimensions: { | |
x, | |
y, | |
width, | |
height, | |
}, | |
}); | |
}); | |
return formattedAnnotations; | |
} | |
// Initialize Annotorious after the page has loaded | |
window.onload = function () { | |
window.anno = Annotorious.init({ | |
image: 'randomimage', | |
widgets: [ | |
getSelectorWidget([ | |
'Excerpt', | |
'Comment', | |
'Question', | |
'Answer', | |
'Idea', | |
'Fact', | |
'Conclusion', | |
'Reference', | |
'Other', | |
]), | |
], | |
}); | |
}; | |
document.getElementById('btn-del-annotations').addEventListener('click', function () { | |
anno.clearAnnotations(); | |
}); | |
document.getElementById('btn-get-annotations').addEventListener('click', function () { | |
const annotations = getFormattedAnnotations(); | |
// fetch('http://localhost:3000/annotations', { | |
// method: 'POST', | |
// headers: { | |
// 'Content-Type': 'application/json', | |
// }, | |
// body: JSON.stringify(annotations), | |
// }) | |
// .then((response) => response.json()) | |
// .then((data) => { | |
// console.log('Success:', data); | |
// }) | |
// .catch((error) => { | |
// console.error('Error:', error); | |
// }); | |
console.log(annotations); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment