From 9af22cd29bb9cdd9c9b1f9c2f7875c487ea4525f Mon Sep 17 00:00:00 2001 From: Leandro Rosemberg Date: Fri, 16 Aug 2024 12:24:55 -0300 Subject: [PATCH 1/7] Add functionality: ESC clear last unsaved polygon --- script.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/script.js b/script.js index aa69671..1828971 100644 --- a/script.js +++ b/script.js @@ -270,6 +270,11 @@ window.addEventListener('keydown', function(e) { masterColors.push(rgb_color); } + + if (e.key === 'Escape') { + points = [] + drawAllPolygons(); + } }); canvas.addEventListener('drop', function(e) { From 052c76f2a0ca05fb310c4db91603b0c6866a8740 Mon Sep 17 00:00:00 2001 From: Leandro Rosemberg Date: Fri, 16 Aug 2024 12:53:37 -0300 Subject: [PATCH 2/7] Add instructions --- index.html | 23 ++++++++++++++++++++++- styles.css | 21 +++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 8e4e410..f5cc6d2 100644 --- a/index.html +++ b/index.html @@ -38,6 +38,27 @@

Draw points to create polygon coordinates

+
+

How to use

+
    +
  1. Drop an image to the indicated area
  2. +
  3. Select the desired mode: Press L to draw a line, or P to draw a polygon
  4. +
  5. Start creating your polygon, clicking in the desired points of the image
  6. +
  7. If in polygon mode, press ENTER to finish the polygon
  8. +
  9. Repeat steps 2 - 4 as many times as you want
  10. +
  11. To finish, copy the numpy points to your clipboard
  12. +
+
+
+

Keyboard shortcuts

+
    +
  • L: Switch to line drawing mode
  • +
  • P: Swicth to polygon drawing mode
  • +
  • Enter: If you drawing a polygon, end the polygon
  • +
  • Esc: When drawing, clear the current polygon
  • +
  • Ctrl(Cmd)-Z: Undo the last point
  • +
+

NumPy Points

Copy the points below into your Python code.

Copy Python to Clipboard @@ -45,7 +66,7 @@

NumPy Points

-
+
diff --git a/styles.css b/styles.css index 06f43bc..318673f 100644 --- a/styles.css +++ b/styles.css @@ -167,3 +167,24 @@ pre { footer { margin-top: 20px; } + +li { + margin-bottom: 4px; +} + +/* Helpers */ +.ta-left { + text-align: left; +} + +.mb-1 { + margin-bottom: 8px; +} + +.mb-2 { + margin-bottom: 16px; +} + +.mb-3 { + margin-bottom: 24px; +} \ No newline at end of file From abc48eee8dc69ee284be77cf844b1e01e5c3d6e0 Mon Sep 17 00:00:00 2001 From: Leandro Rosemberg Date: Fri, 16 Aug 2024 13:32:23 -0300 Subject: [PATCH 3/7] Add functionality: Its possible to use Ctrl/Cmd-Z to undo last point --- script.js | 144 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 83 insertions(+), 61 deletions(-) diff --git a/script.js b/script.js index 1828971..a1b4bd5 100644 --- a/script.js +++ b/script.js @@ -91,6 +91,50 @@ function getScaledCoords(e) { return [x / scaleFactor, y / scaleFactor]; } +function drawCurrentPolygon (cursorX, cursorY) { + //ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(img, 0, 0); + for (var i = 0; i < points.length - 1; i++) { + // draw arc around each point + ctx.beginPath(); + ctx.strokeStyle = rgb_color; + ctx.arc(points[i][0], points[i][1], 5, 0, 2 * Math.PI); + // fill with white + ctx.fillStyle = 'white'; + ctx.fill(); + ctx.stroke(); + drawLine(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1]); + } + + if ((points.length > 0 && drawMode == "polygon") || (points.length > 0 && points.length < 2 && drawMode == "line")) { + ctx.beginPath(); + ctx.strokeStyle = rgb_color; + ctx.arc(points[i][0], points[i][1], 5, 0, 2 * Math.PI); + // fill with white + ctx.fillStyle = 'white'; + ctx.fill(); + ctx.stroke(); + + if (cursorX && cursorY) { + drawLine(points[points.length - 1][0], points[points.length - 1][1], cursorX, cursorY); + } + + if (points.length == 2 && drawMode == "line") { + console.log("line"); + // draw arc around each point + ctx.beginPath(); + ctx.strokeStyle = rgb_color; + ctx.arc(points[0][0], points[0][1], 5, 0, 2 * Math.PI); + // fill with white + ctx.fillStyle = 'white'; + ctx.fill(); + ctx.stroke(); + masterPoints.push(points); + points = []; + } + } +} + function drawAllPolygons () { // draw all points for previous regions for (var i = 0; i < masterPoints.length; i++) { @@ -124,6 +168,15 @@ function drawAllPolygons () { } } +function getParentPoints () { + var parentPoints = []; + for (var i = 0; i < masterPoints.length; i++) { + parentPoints.push(masterPoints[i]); + } + parentPoints.push(points); + return parentPoints; +} + function clearall() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0); @@ -180,55 +233,15 @@ canvas.addEventListener('mousemove', function(e) { ycoord.innerHTML = y; if (canvas.style.cursor == 'crosshair') { - //ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.drawImage(img, 0, 0); - for (var i = 0; i < points.length - 1; i++) { - // draw arc around each point - ctx.beginPath(); - ctx.strokeStyle = rgb_color; - ctx.arc(points[i][0], points[i][1], 5, 0, 2 * Math.PI); - // fill with white - ctx.fillStyle = 'white'; - ctx.fill(); - ctx.stroke(); - drawLine(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1]); - } - if ((points.length > 0 && drawMode == "polygon") || (points.length > 0 && points.length < 2 && drawMode == "line")) { - ctx.beginPath(); - ctx.strokeStyle = rgb_color; - ctx.arc(points[i][0], points[i][1], 5, 0, 2 * Math.PI); - // fill with white - ctx.fillStyle = 'white'; - ctx.fill(); - ctx.stroke(); - drawLine(points[points.length - 1][0], points[points.length - 1][1], x, y); - - if (points.length == 2 && drawMode == "line") { - console.log("line"); - // draw arc around each point - ctx.beginPath(); - ctx.strokeStyle = rgb_color; - ctx.arc(points[0][0], points[0][1], 5, 0, 2 * Math.PI); - // fill with white - ctx.fillStyle = 'white'; - ctx.fill(); - ctx.stroke(); - masterPoints.push(points); - points = []; - } - } - var parentPoints = []; - - for (var i = 0; i < masterPoints.length; i++) { - parentPoints.push(masterPoints[i]); - } - parentPoints.push(points); - + drawCurrentPolygon(x, y) drawAllPolygons(); } }); + + window.addEventListener('keydown', function(e) { + e.stopImmediatePropagation() if (e.key === 'Enter') { canvas.style.cursor = 'default'; // remove line drawn by mouseover @@ -273,7 +286,22 @@ window.addEventListener('keydown', function(e) { if (e.key === 'Escape') { points = [] + + // TODO: From here on down it's the same, isolate the code + drawCurrentPolygon() drawAllPolygons(); + var parentPoints = getParentPoints(); + writePoints(parentPoints); + } + + if (e.key === 'z' && (e.ctrlKey || e.metaKey)) { + points.pop() + + // TODO: From here on down it's the same, isolate the code + drawCurrentPolygon() + drawAllPolygons(); + var parentPoints = getParentPoints(); + writePoints(parentPoints); } }); @@ -332,6 +360,14 @@ function writePoints(parentPoints) { parentPoints = normalized; } + var hasPoints = parentPoints?.some(point => point?.length); + + if (!hasPoints) { + document.querySelector('#python').innerHTML = ''; + document.querySelector('#json').innerHTML; + return; + } + // create np.array list var code_template = ` [ @@ -344,6 +380,7 @@ ${points.map(function(point) { }).join(',')} ] `; + document.querySelector('#python').innerHTML = code_template; var json_template = ` @@ -383,28 +420,13 @@ canvas.addEventListener('click', function(e) { } ctx.arc(x, y, 155, 0, 2 * Math.PI); - // concat all points into one array - var parentPoints = []; - - for (var i = 0; i < masterPoints.length; i++) { - parentPoints.push(masterPoints[i]); - } - // add "points" - parentPoints.push(points); + var parentPoints = getParentPoints(); writePoints(parentPoints); }); document.querySelector('#normalize_checkbox').addEventListener('change', function(e) { showNormalized = e.target.checked; - // normalize all - var parentPoints = []; - - for (var i = 0; i < masterPoints.length; i++) { - parentPoints.push(masterPoints[i]); - } - - parentPoints.push(points); - + var parentPoints = getParentPoints(); writePoints(parentPoints); }); \ No newline at end of file From 41bc631b880cfb8b13d4ddcf515596579bfd0f42 Mon Sep 17 00:00:00 2001 From: Leandro Rosemberg Date: Fri, 16 Aug 2024 14:11:53 -0300 Subject: [PATCH 4/7] Clean empty points in writePoints --- script.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/script.js b/script.js index a1b4bd5..d8d7ac3 100644 --- a/script.js +++ b/script.js @@ -360,9 +360,10 @@ function writePoints(parentPoints) { parentPoints = normalized; } - var hasPoints = parentPoints?.some(point => point?.length); + // clean empty points + parentPoints = parentPoints.filter(points => !!points.length); - if (!hasPoints) { + if (!parentPoints.length) { document.querySelector('#python').innerHTML = ''; document.querySelector('#json').innerHTML; return; From 0b29d269b010f78349de14d32ee308ae4ac3d988 Mon Sep 17 00:00:00 2001 From: Leandro Rosemberg Date: Fri, 16 Aug 2024 14:26:30 -0300 Subject: [PATCH 5/7] Bugfix: the last line that connected to the mouse kept appearing when enter is pressed. Code refactor: simplified the Keyboard events and enter event. --- script.js | 42 ++++++++++-------------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/script.js b/script.js index d8d7ac3..ba54fc3 100644 --- a/script.js +++ b/script.js @@ -242,34 +242,16 @@ canvas.addEventListener('mousemove', function(e) { window.addEventListener('keydown', function(e) { e.stopImmediatePropagation() + let validKey = false + if (e.key === 'Enter') { + validKey = true canvas.style.cursor = 'default'; - // remove line drawn by mouseover - // ctx.clearRect(0, 0, canvas.width, canvas.height); - // join the dots - drawLine(points[0][0], points[0][1], points[points.length - 1][0], points[points.length - 1][1]); - // fill polygon with color - if (drawMode == 'polygon') { - ctx.beginPath(); - ctx.moveTo(points[0][0], points[0][1]); - ctx.fillStyle = opaque_color; - for (var i = 1; i < points.length; i++) { - ctx.lineTo(points[i][0], points[i][1]); - } - ctx.closePath(); - ctx.fill(); - // draw line connecting last two points - } + + // save current polygon points masterPoints.push(points); - // draw arc around last point - ctx.beginPath(); - ctx.strokeStyle = rgb_color; - ctx.arc(points[points.length - 1][0], points[points.length - 1][1], 5, 0, 2 * Math.PI); - // fill with white - ctx.fillStyle = 'white'; - ctx.fill(); - ctx.stroke(); points = []; + // dont choose a color that has already been chosen var remaining_choices = color_choices.filter(function(x) { return !masterColors.includes(x); @@ -280,24 +262,20 @@ window.addEventListener('keydown', function(e) { } rgb_color = remaining_choices[Math.floor(Math.random() * remaining_choices.length)]; - masterColors.push(rgb_color); } if (e.key === 'Escape') { + validKey = true points = [] - - // TODO: From here on down it's the same, isolate the code - drawCurrentPolygon() - drawAllPolygons(); - var parentPoints = getParentPoints(); - writePoints(parentPoints); } if (e.key === 'z' && (e.ctrlKey || e.metaKey)) { + validKey = true points.pop() + } - // TODO: From here on down it's the same, isolate the code + if (validKey) { drawCurrentPolygon() drawAllPolygons(); var parentPoints = getParentPoints(); From 88f64ab4b62cd9cf9c2e5e288945ff64ac7180da Mon Sep 17 00:00:00 2001 From: Leandro Rosemberg Date: Fri, 16 Aug 2024 15:01:28 -0300 Subject: [PATCH 6/7] Readme --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b89e6a..02d3833 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,10 @@ To use PolygonZone, open up the [PolygonZone web application](https://roboflow.g 4. Continue to draw as many polygons as you need. 5. Copy the NumPy array or JSON object that contains the coordinates of the polygons you have drawn. -You can zoom in and out of an image using the mouse wheel or a laptop track pad. +## Funcionalities +- You can zoom in and out of an image using the mouse wheel or a laptop track pad. +- You can undo the last point pressing Ctrl/Cmd+Z +- You can discard the last unsaved polygon pressing Esc ## Contributing 🤝 From 9038321477d6f6bb2e193ff50bbc6ac4bb015eb0 Mon Sep 17 00:00:00 2001 From: Leandro Rosemberg Date: Fri, 16 Aug 2024 15:02:26 -0300 Subject: [PATCH 7/7] Typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 02d3833..257e897 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ To use PolygonZone, open up the [PolygonZone web application](https://roboflow.g 4. Continue to draw as many polygons as you need. 5. Copy the NumPy array or JSON object that contains the coordinates of the polygons you have drawn. -## Funcionalities +## Functionalities - You can zoom in and out of an image using the mouse wheel or a laptop track pad. - You can undo the last point pressing Ctrl/Cmd+Z - You can discard the last unsaved polygon pressing Esc