simple-image-label
Version:
Javascript image annotate, use in deep learning
9 lines • 15.2 kB
JavaScript
function e(e,t,l,i){Object.defineProperty(e,t,{get:l,set:i,enumerable:!0,configurable:!0})}function t(e){return e&&e.__esModule?e.default:e}var l="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},i={},s={},n=l.parcelRequire9a68;null==n&&((n=function(e){if(e in i)return i[e].exports;if(e in s){var t=s[e];delete s[e];var l={id:e,exports:{}};return i[e]=l,t.call(l.exports,l,l.exports),l.exports}var n=Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}).register=function(e,t){s[e]=t},l.parcelRequire9a68=n),n.register("b9D7K",function(t,l){e(t.exports,"register",()=>i,e=>i=e),e(t.exports,"resolve",()=>s,e=>s=e);var i,s,n={};i=function(e){for(var t=Object.keys(e),l=0;l<t.length;l++)n[t[l]]=e[t[l]]},s=function(e){var t=n[e];if(null==t)throw Error("Could not resolve bundle with id "+e);return t}}),n("b9D7K").register(JSON.parse('{"bFgRH":"index.a3f13d0f.js","1mYHr":"1.c6fd5d15.jpg","6FKux":"2.c318c7c4.jpg","eJv76":"index.807d122e.css"}'));var a={};function o(e){let t=Array.isArray(e)?[]:{};if(e&&"object"==typeof e)for(let l in e)e.hasOwnProperty(l)&&(e[l]&&e[l],t[l]=e[l]);return t}function r(){for(var e=[],t=0;t<36;t++)e[t]="0123456789abcdef".substr(Math.floor(16*Math.random()),1);return e[14]="4",e[8]=e[13]=e[18]=e[23]="-",e.join("")}function h(e,t){if("object"!=typeof e||"object"!=typeof t)return e===t;for(let l in e)if(e.hasOwnProperty(l)&&e[l]!==t[l])return!1;return!0}function d(e){return e.indexOf("%")>-1?+e.replace("%","")/100:e.indexOf("px")>-1?+e.replace("px","")/100:void 0}function u(e){return 100*e+"%"}Object.defineProperty(a,"__esModule",{value:!0,configurable:!0}),Object.defineProperty(a,"default",{get:()=>m,set:void 0,enumerable:!0,configurable:!0});var m=class{constructor(e){this.imageLabelAreaEl=document.getElementById(e.el||"imageLabelArea"),this.imageUrl=e.imageUrl,this.labels=e.labels||[],this.labelClick=e.labelClick,this.contextmenu=e.contextmenu,this.error=e.error,this.readOnly=e.readOnly||!1,this.isMouseDown=!1,this.labelsContainer=null,this.defaultZIndex=0,this.$w=0,this.$h=0,this.resizeDotClasses=["n","s","w","e","nw","ne","sw","se"],this.resizeDotName=null,this.labelItem=null,this.labelItemTemp=null,this.startPoint=null,this.startPointTemp=null,this.endPoint=null,this.labelRelativePointContainer={x:null,y:null},this.activeUuid=null,this.imageInfo=null,this.init()}init(){this.imageInfo=null,this.labelsContainer||(this.imageLabelAreaEl.innerHTML=`
<div class="__simple-image-label__">
<div class="s-image-content">
<img id="label-bg_img" src="${this.imageUrl}">
<div id="labelsContainer" class="label-content"></div>
</div>
</div>
`);let e=document.getElementById("label-bg_img");e.src!==this.imageUrl&&(e.src=this.imageUrl),e.onload=()=>{this.labelAreaEvent(),this.resizeImage()},e.onerror=e=>{this.error&&"function"==typeof this.error&&this.error(e)},this.labelsContainer=document.getElementById("labelsContainer"),this.initLabelElement()}resizeImage(){var e;let t=()=>{let{width:e}=this.imageInfo,t=this.imageLabelAreaEl.querySelector(".__simple-image-label__");this.imageLabelAreaEl.clientWidth>=e?t.style.width=u(e/this.imageLabelAreaEl.clientWidth):t.style.width="100%",this.$w=this.labelsContainer.clientWidth,this.$h=this.labelsContainer.clientHeight};this.imageInfo?t():(e=this.imageUrl,new Promise((t,l)=>{let i=new Image;i.src=e,i.onload=()=>{t({width:i.width,height:i.height})}})).then(e=>{this.imageInfo=e,t()})}initLabelElement(){this.labels.forEach(e=>{e.uuid||(e.uuid=r()),this.createLabelElement(e)})}labelAreaEvent(){this.$w=this.labelsContainer.clientWidth,this.$h=this.labelsContainer.clientHeight,this.startPoint={x:0,y:0},this.endPoint={x:0,y:0},this.labelItem={uuid:"",x:0,y:0,width:0,height:0,name:"",color:""},this.labelsContainer.onmousedown=e=>this.mousedown(e),this.labelsContainer.onmousemove=e=>this.mousemove(e),this.labelsContainer.onmouseup=e=>this.mouseup(e),this.labelsContainer.oncontextmenu=e=>{e.preventDefault(),this.contextmenu&&"function"==typeof this.contextmenu&&this.contextmenu(e)},this.readOnly?(window.removeEventListener("resize",this.resize.bind(this),!1),this.labelsContainer.style.cursor="default",this.clearAllLabelActive()):this.labelsContainer.style.cursor="crosshair",window.addEventListener("resize",this.resize.bind(this),!1),this.resizeDotDisplayStatus()}resize(){this.$w=this.labelsContainer.clientWidth,this.$h=this.labelsContainer.clientHeight,this.resizeImage()}resizeDotDisplayStatus(){document.querySelectorAll(".resize-dot").forEach(e=>{this.readOnly?e.style.display="none":e.style.display="block"})}mousedown(e){if(this.readOnly||0!==e.button)return;this.isMouseDown=!0;let t=e.target.className.includes("label-text"),l=e.target.className.includes("label-item"),i=e.target.className.includes("resize-dot"),s=l?e.target.id:e.target.parentNode.id;if(i)return this.labelItem=this.getLabelByUuid(e.target.parentNode.id),this.labelItemTemp=o(this.labelItem),this.endPoint={x:this.labelItemTemp.x+this.labelItemTemp.width,y:this.labelItemTemp.y+this.labelItemTemp.height},this.resizeDotName=this.getLabelDot(e),this.dragListen(s,t),void this.removeDragListen();if(l||t)return this.clearAllLabelActive(),this.setLabelActive(s),void this.dragListen(s,t);let n=e.clientX-this.getLabelsContainerRelativePoints().x,a=e.clientY-this.getLabelsContainerRelativePoints().y,h=n/this.$w,d=a/this.$h;this.startPoint={x:h,y:d},this.startPointTemp||(this.startPointTemp=o(this.startPoint)),this.labelItem.uuid=r(),this.labelItem.x=h,this.labelItem.y=d,this.labelItem.width=0,this.labelItem.height=0,this.createLabelElement(this.labelItem)}mousemove(e){if(this.readOnly)return;let t=e.target.className.includes("label-text"),l=e.target.className.includes("label-item"),i=e.target.className.includes("resize-dot"),s=l?e.target.id:e.target.parentNode.id;i?this.removeDragListen(s,t):(l||t)&&(this.isMouseDown||this.mouseEnterLabel(s),this.dragListen(s,t));let n=e.clientX-this.getLabelsContainerRelativePoints().x,a=e.clientY-this.getLabelsContainerRelativePoints().y,o=n/this.$w,r=a/this.$h;this.endPoint={x:o,y:r},this.labelItem.uuid&&this.calc(this.labelItem,this.startPoint,this.endPoint)}mouseup(e){if(this.readOnly)return;let t=e.clientX-this.getLabelsContainerRelativePoints().x,l=e.clientY-this.getLabelsContainerRelativePoints().y,i=t/this.$w,s=l/this.$h;this.endPoint={x:i,y:s},this.calc(this.labelItem,this.startPoint,this.endPoint),(h(this.startPoint,this.endPoint)||0===this.labelItem.width&&0===this.labelItem.height)&&this.removeLabelByUuid(this.labelItem.uuid),this.labelItem={},this.isMouseDown=!1,this.resizeDotName=null,this.labelItemTemp=null}getLabelsContainerRelativePoints(){let e=document.querySelector(".__simple-image-label__");return{x:e.getBoundingClientRect().x,y:e.getBoundingClientRect().y}}createLabelElement(e){let{x:t,y:l,width:i,height:s,uuid:n,color:a,name:o}=e;this.clearAllLabelActive();let r=document.createElement("div");r.className="label-item",r.id=n,r.style.left=u(t),r.style.top=u(l),r.style.width=u(i),r.style.height=u(s),r.style.position="absolute",r.style.border="1px solid rgb(58,238,121)",r.style.backgroundColor="rgba(191,191,191,.5)",r.style.zIndex=this.labels.length,a&&(r.style.borderColor=a),this.resizeDotClasses.forEach(e=>{let t=document.createElement("div");t.className=`resize-dot resize-dot-${e}`,r.appendChild(t)});let h=document.createElement("div");h.className="label-text",h.innerText=o,o&&(h.style.display="block",a&&(h.style.color=a)),r.appendChild(h),this.labelsContainer.appendChild(r)}calc(e,t,l){h(t,l)||(e.width=l.x-t.x,e.height=l.y-t.y,e.uuid&&!this.getLabelByUuid(e.uuid)?this.labels.push(e):this.changeLabelSize(e,l))}changeLabelSize(e,t){let l=document.getElementById(e.uuid);if(!l)return;let{x:i,y:s,width:n,height:a,uuid:o}=e;if(this.resizeDotName){let e=this.labelItemTemp.y+this.labelItemTemp.height;if(this.resizeDotName.includes("n")){let i=this.labelItemTemp.y-t.y,s=i>0?this.labelItemTemp.height+Math.abs(i):this.labelItemTemp.height-Math.abs(i),n=t.y>=e?e:t.y;l.style.top=u(n),l.style.height=u(s<0?0:s)}if(this.resizeDotName.includes("s")){let e=t.y-s;l.style.height=u(e<=0?0:e)}if(this.resizeDotName.includes("w")){let e=this.labelItemTemp.x+this.labelItemTemp.width-t.x<=0?this.labelItemTemp.x+this.labelItemTemp.width:t.x;l.style.left=u(e);let i=this.labelItemTemp.x-t.x<0?this.labelItemTemp.width-Math.abs(this.labelItemTemp.x-t.x):this.labelItemTemp.width+Math.abs(this.labelItemTemp.x-t.x);l.style.width=u(i<=0?0:i)}this.resizeDotName.includes("e")&&(l.style.width=u(i<=0?t.x:t.x-i))}else{let e=Math.abs(n),t=Math.abs(a);l.style.width=u(n<=0?0:e),l.style.height=u(a<=0?0:t),l.style.left=u(i),l.style.top=u(s)}let r={x:d(l.style.left),y:d(l.style.top),height:d(l.style.height),width:d(l.style.width)};this.setLabelByUuid(o,r)}getLabelByUuid(e){return this.labels.find(t=>t.uuid===e)}setLabelByUuid(e,t={}){let l=document.getElementById(e);if(!l)return;let i=l.querySelector(".label-text"),s=Object.keys(t);this.labels.forEach(n=>{n.uuid===e&&s.forEach(e=>{n[e]=t[e],n.name&&(i.style.display="block",i.innerText=n.name),n.color&&(l.style.borderColor=n.color,i.style.color=n.color)})})}removeLabelByUuid(e){let t=document.getElementById(e);this.labels=Object.assign([],this.labels.filter(t=>t.uuid!==e)),t&&t.parentNode.removeChild(t),this.labelClick&&"function"==typeof this.labelClick&&this.labelClick(null)}removeAllLabels(){document.querySelectorAll(".label-item").forEach(e=>{e.parentNode.removeChild(e)}),this.labels=[]}clearAllLabelActive(){let e=document.querySelectorAll(".label-item");e.length&&e.forEach(e=>{e.classList.remove("label-item-active")})}setLabelActive(e){let t=document.getElementById(e);t&&(t.classList.add("label-item-active"),this.labelClick&&"function"==typeof this.labelClick&&this.labelClick(this.getLabelByUuid(e)))}getLabelDot(e){let t=e.target.className.replace("resize-dot resize-dot-","");return this.clearAllLabelActive(),this.setLabelActive(e.target.parentNode.id),t}mouseEnterLabel(e){if(this.readOnly)return;let t=document.getElementById(e);t&&(t.style.cursor="default")}dragListen(e,t=!1){let l=document.getElementById(e);if(!l)return;let i=t?l.querySelector(".label-text"):null;if(t)return i.onmousedown=e=>this.dragStart(e),i.onmousemove=e=>this.dragLabel(e),void(i.onmouseup=e=>this.dragEnd(e));l.onmousedown=e=>this.dragStart(e),l.onmousemove=e=>this.dragLabel(e),l.onmouseup=e=>this.dragEnd(e)}removeDragListen(e,t=!1){let l=document.getElementById(e);if(!l)return;let i=t?l.querySelector(".label-text"):null;l.onmousedown=null,l.onmousemove=null,l.onmouseup=null,t&&(i.onmousedown=null,i.onmousemove=null,i.onmouseup=null)}dragStart(e){if(this.readOnly)return;let t=document.getElementById(e.target.id||e.target.parentNode.id);t&&(t.style.cursor="move",this.labelRelativePointContainer.x=e.pageX-t.offsetLeft,this.labelRelativePointContainer.y=e.pageY-t.offsetTop,this.defaultZIndex=t.style.zIndex,t.style.zIndex=100)}dragLabel(e){if(this.readOnly||(e.preventDefault(),!this.labelRelativePointContainer.x||!this.labelRelativePointContainer.y))return;let t=document.getElementById(e.target.id||e.target.parentNode.id);if(!t||"default"===t.style.cursor)return;let l=1-(t.style.width?d(t.style.width):0),i=1-(t.style.height?d(t.style.height):0),s=e.pageX-this.labelRelativePointContainer.x,n=e.pageY-this.labelRelativePointContainer.y;t.style.left=s/this.$w<=0?0:s/this.$w>=l?u(l):u(s/this.$w),t.style.top=n/this.$h<=0?0:n/this.$h>=i?u(i):u(n/this.$h)}dragEnd(e){if(this.readOnly)return;let t=document.getElementById(e.target.id||e.target.parentNode.id);t&&(t.style.cursor="default",this.labels.forEach(l=>{l.uuid===e.target.id&&(l.x=d(t.style.left),l.y=d(t.style.top))}),this.labelRelativePointContainer.x=null,this.labelRelativePointContainer.y=null,t.style.zIndex=this.defaultZIndex)}getLabels(){return this.labels}activeLabel(){let e=document.querySelector(".label-item-active").id;return this.labels.find(t=>t.uuid===e)}setImage(e){this.removeAllLabels(),this.imageUrl=e,this.init()}setLabels(e){this.labels=e,this.init()}getImageInfo(){return this.imageInfo}getCoordinate(e){let{height:t,width:l}=this.imageInfo;return{x:e.x*l,y:e.y*t,x1:(e.x+e.width)*l,y1:(e.y+e.height)*t}}getLabelsCoordinate(){return this.labels.map(e=>this.getCoordinate(e))}convertToYoloCoordinate(e){let t=this.getCoordinate(e),{height:l,width:i}=this.imageInfo;return[(t.x+t.x1)/2/i,(t.y+t.y1)/2/l,e.width,e.height]}getLabelsYoloCoordinate(){return this.labels.map(e=>this.convertToYoloCoordinate(e))}setReadOnly(e){this.readOnly=e,this.labelAreaEvent()}},b={};b=new URL(n("b9D7K").resolve("1mYHr"),import.meta.url).toString();var c={};c=new URL(n("b9D7K").resolve("6FKux"),import.meta.url).toString();const g=document.getElementById("pre-btn"),y=document.getElementById("next-btn"),f=document.getElementById("delete-btn"),p=document.getElementById("set-name-btn"),x=document.getElementById("set-color-btn"),v=document.getElementById("default-coord"),w=document.getElementById("yolo-coord"),I=document.getElementById("read-only-btn"),L=[{color:"red",height:.251473,name:"House",width:.200318,x:.0309278,y:.532417},{x:.588202,y:.42436100000000004,width:.37571599999999994,height:.453832,name:"Tree",color:"yellow"}],C=[{x:.46949199999999996,y:.128668,width:.191526,height:.202032,name:"Grass Mud Horse",color:"blue"},{x:.7186440000000001,y:.241535,width:.15762700000000002,height:.177201,name:"Grass Mud Horse",color:"blue"},{x:.7406780000000001,y:.536117,width:.130508,height:.173815,name:"Duck",color:"red"},{x:.874576,y:.481941,width:.115254,height:.148984,name:"Duck",color:"red"},{x:.0338983,y:.574492,width:.111864,height:.13544,name:"Duck",color:"red"}];let E=null;const T=new/*@__PURE__*/(t(a))({el:"imageLabelArea",imageUrl:/*@__PURE__*/t(b),labels:L,contextmenu:e=>{},error:e=>{console.log(e)},labelClick:e=>{if(!e){O();return}E=e,console.log("Current clicked label : ",e);let t=T.getLabelsCoordinate();console.log("All labels coord : ",t);let l=T.getLabelsYoloCoordinate();console.log("All YOLO coord : ",l);let i=T.getCoordinate(e),s=T.convertToYoloCoordinate(e);v.innerText="默认坐标:"+JSON.stringify(i),w.innerText="YOLO坐标:"+JSON.stringify(s),f.disabled=!1,p.disabled=!1,x.disabled=!1}});function P(e,t){// 重设图片
T.setImage(e,e=>{console.error(e)}),T.setLabels(t)}function O(){E=null,f.disabled=!0,p.disabled=!0,x.disabled=!0,v.innerText="",w.innerText=""}f.disabled=!0,p.disabled=!0,x.disabled=!0,g.style.display="none",y.onclick=()=>{P(/*@__PURE__*/t(c),C),g.style.display="block",y.style.display="none",O()},g.onclick=()=>{P(/*@__PURE__*/t(b),L),y.style.display="block",g.style.display="none",O()},f.onclick=()=>{E&&T.removeLabelByUuid(E.uuid)},p.onclick=()=>{let e=window.prompt("设置当前label名称");e&&T.setLabelByUuid(E.uuid,{name:e})},x.onclick=()=>{let e=window.prompt("设置当前label颜色");e&&T.setLabelByUuid(E.uuid,{color:e})},I.innerText="Enable read only",I.onclick=()=>{console.log("imageLabelContent.readOnly",T.readOnly);let e=!T.readOnly;e?(I.innerText="Disable read only",O()):I.innerText="Enable read only",T.setReadOnly(e)};