Skip to content

Instantly share code, notes, and snippets.

@kamranahmedse
Last active February 20, 2023 11:03
Show Gist options
  • Save kamranahmedse/463cc2aa2c85a3c2a91f5f0d25071ff5 to your computer and use it in GitHub Desktop.
Save kamranahmedse/463cc2aa2c85a3c2a91f5f0d25071ff5 to your computer and use it in GitHub Desktop.
Image annotation sample to assign pre-defined tags on different image sections
<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