Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
b3c5ab9
Sync with SAM api
Apr 25, 2023
df56c17
request Decoder Service for sample data
Apr 25, 2023
1563608
Update fectch function - SAM
Apr 26, 2023
a45621f
Add loader spinner
Apr 26, 2023
da1bbdb
Display points in the map
Apr 26, 2023
6f47ebf
Get canvas coordinates in pixels
Apr 26, 2023
17ea647
Fix request to SAM api
Apr 26, 2023
b3db302
Clean unused functions
Apr 26, 2023
4016c41
Fix sidebar to 250px
Apr 27, 2023
ef47dfa
Fix butoon to dowload
Apr 27, 2023
71f330a
Add butoon to request predictions
Apr 28, 2023
2531bfe
Print output
May 4, 2023
f6cd810
Create canvas for a layer
May 5, 2023
b491338
Add config file
May 18, 2023
f528a88
Update SAM API url
Jun 5, 2023
a0c1145
Display geojson on the map
Jun 5, 2023
7935920
Select the last point clicked
Jun 9, 2023
79b5fda
Update css for the menus and list
Jun 9, 2023
8c84e22
Update download buttons
Jun 9, 2023
98bf61e
Fix merge polygons
Jun 9, 2023
f05e5f3
Rename function
Jun 9, 2023
fb209e0
Add notification and process SAM responses
Jun 9, 2023
9741995
fiz numeration for items
Jun 12, 2023
9ff3346
Fix sequence of id for each class
Jun 12, 2023
5eff844
Update polygon simplification
Jun 14, 2023
eee8b58
Fill polygon
Jun 14, 2023
bd3eb1a
Fix simplification
Jun 14, 2023
612cf4d
Update SAM request config
Jun 15, 2023
764ff0e
Cache encode images and use that to decode many time
Jun 15, 2023
74fc1ab
Clean console.log outputs
Jun 16, 2023
b9e65d2
Set lint and fix
Jun 16, 2023
3c436f8
Run prettier on the files
Jun 16, 2023
dc5fb59
Fix test
Jun 16, 2023
4dcecb9
Add indexedDB to sttore encode images
Jun 21, 2023
ac653a9
Fix position of the shape images to sent request to decoder
Jun 22, 2023
70008d2
Delete encode item from indexedDB
Jun 22, 2023
db6a1a9
Update pointer icon
Jun 22, 2023
aeffb70
Add hash map in the url
Jun 22, 2023
347a4dd
Refatoring featureCollection and add indexedDB for items
Jun 26, 2023
30734ad
Load items from idexedDB
Jun 26, 2023
6591509
Export storage as object
Jun 26, 2023
649c752
Remove item from indexedDB
Jun 26, 2023
d1fad86
Merge items that overlaps
Jun 26, 2023
8dfaf30
Update item styles
Jun 26, 2023
5c0a1d7
Delete item from db
Jun 27, 2023
a126320
Fix id for items
Jun 27, 2023
423534d
Update id items for SAM results
Jun 27, 2023
8b57fab
Remove unused imports
Jun 27, 2023
4233738
Update model and description for the tool
Jun 27, 2023
d192210
Fix load wms
Jun 28, 2023
2cca69a
Update project names
Jun 28, 2023
d6de742
Update Readme
Jun 28, 2023
5284656
Clear mask in magic wand
Jun 28, 2023
ca01d7c
Add extra projects
Jun 28, 2023
2b5c9d9
Update README.md
Jun 28, 2023
c371e0f
Update public/index.html
Jun 28, 2023
f6e5cdd
Update src/components/Modal.js
Jun 28, 2023
72dad32
Update src/components/Modal.js
Jun 28, 2023
47937a0
Code cleanup/improvements
willemarcel Jun 29, 2023
652b66d
Improve Instructions Modal
willemarcel Jun 29, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
{
"extends": ["react-app", "react-app/jest"]
}
"extends": [
"react-app",
"react-app/jest"
],
"rules": {
"comma-dangle": ["error", "always-multiline"]
}
}
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"semi": true,
"singleQuote": false,
"jsxSingleQuote": false,
"printWidth": 80
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ds-annotate

Magic wand annotation tool for machine learning training data production.
Magic wand and Segment Anything Model (SAM) annotation tool for machine learning training data.

## Installation and Usage
The steps below will walk you through setting up your own instance of the project.
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"homepage": "http://devseed.com/ds-annotate/",
"dependencies": {
"@emotion/react": "^11.10.6",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
Expand All @@ -13,22 +14,25 @@
"@turf/turf": "^6.5.0",
"@types/geojson": "^7946.0.10",
"history": "^5.3.0",
"lodash": "^4.17.21",
"ol": "^6.13.0",
"ol-magic-wand": "^1.0.5",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.4.0",
"react-notifications": "^1.7.4",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"react-spinners": "^0.13.8",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"eject": "react-scripts eject",
"deploy": "yarn build && gh-pages -d build",
"lint": "eslint src",
"lint": "npx eslint . && yarn run prettier",
"prettier": "prettier --write 'src/**/*.js'",
"test": "npm run lint && react-scripts test --env=jsdom --watchAll=false --testMatch **/src/**/*.test.js"
},
Expand Down
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
content="Magic wand and Segment Anything Model (SAM) annotation tool for machine learning training data."
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
Expand Down
13 changes: 8 additions & 5 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ import React from "react";
import { Sidebar } from "./components/Sidebar";
import { MapWrapper } from "./components/map";
import { Modal } from "./components/Modal";
import "react-notifications/lib/notifications.css";
import { NotificationContainer } from "react-notifications";

function App() {
return (
<div className="flex h-screen ">
<div className="w-1/6" aria-label="Sidebar">
<Sidebar></Sidebar>
<div className="flex h-screen">
<div className="w-64 bg-gray-2000" aria-label="Sidebar">
<Sidebar />
</div>
<div className="w-5/6">
<div className="flex-1 bg-gray-100">
<MapWrapper />
</div>
<Modal></Modal>
<Modal />
<NotificationContainer />
</div>
);
}
Expand Down
8 changes: 3 additions & 5 deletions src/components/ClassObj.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@ export const ClassObj = ({ classProps, setOpenMenu }) => {
}}
onClick={() => {
setActiveClass(classProps);
setOpenMenu(false);
// setOpenMenu(false);
}}
>
<span className="text-1xl block float-left">
<span className="text-xs block float-left">
<BsSquareFill style={{ color: classProps.color }}></BsSquareFill>
</span>
<span className={`font-medium flex-1 duration-200`}>
{classProps.name}
</span>
<span className={`flex-1 duration-200`}>{classProps.name}</span>
</li>
);
};
34 changes: 10 additions & 24 deletions src/components/DownloadData.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import React, { useContext } from "react";
import { MainContext } from "../contexts/MainContext";
import { BsDownload } from "react-icons/bs";

import { downloadGeojsonFile, downloadInJOSM } from "../utils/utils";
import { olFeatures2geojson } from "./../utils/featureCollection";
import { olFeatures2geojson } from "./../utils/convert";

export const DownloadData = ({ classProps }) => {
const { items, activeProject } = useContext(MainContext);

const downloadGeojson = () => {
const geojson = JSON.stringify(olFeatures2geojson(items));
const fileName = `${activeProject.properties.name.replace(
/\s/g,
"_"
)}.geojson`;
downloadGeojsonFile(geojson, fileName);
const projectName = activeProject.properties.name.replace(/\s/g, "_");
downloadGeojsonFile(geojson, `${projectName}.geojson`);
};

const josm = () => {
Expand All @@ -23,28 +19,18 @@ export const DownloadData = ({ classProps }) => {
};

return (
<div className="flex flex-row mt-3">
<div className="grid grid-cols-2 gap-2">
<button
type="button"
className="custom_button_2 mr-1"
title="Load data on JOSM"
onClick={() => {
josm();
}}
className="custom_button"
onClick={() => downloadGeojson()}
>
<BsDownload className="w-3 mt-1 mr-2"></BsDownload>
JOSM
Download GeoJSON
</button>
<button
type="button"
className="custom_button_2"
onClick={() => {
downloadGeojson();
}}
title="Download data as GeoJSON"
className="custom_button"
onClick={() => josm()}
>
<BsDownload className="w-3 mt-1 mr-2"></BsDownload>
GeoJson
Export to JOSM
</button>
</div>
);
Expand Down
65 changes: 65 additions & 0 deletions src/components/EncodeItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React, { useContext } from "react";
import { MainContext } from "../contexts/MainContext";
import { MapContext } from "../contexts/MapContext";
import { BsTrash } from "react-icons/bs";
import { storeEncodeItems } from "./../store/indexedDB";

export const EncodeItem = ({ encodeItem, index }) => {
const { encodeItems, dispatchEncodeItems } = useContext(MainContext);
const { map } = useContext(MapContext);

const zoomTo = (encodeItem) => {
if (!map) return;
const { bbox, zoom } = encodeItem;
map.getView().fit(bbox);
map.getView().setZoom(zoom);
const newEncodeItems = encodeItems.map((e) => {
e.selected = false;
return e;
});
encodeItem.selected = true;
newEncodeItems[index] = encodeItem;
dispatchEncodeItems({
type: "CACHING_ENCODED",
payload: [...newEncodeItems],
});
};

const handleRemoveEncodeItem = async (encodeItem) => {
const updatedEncodeItems = encodeItems.filter((item, i) => {
return item.id !== encodeItem.id;
});
dispatchEncodeItems({
type: "CACHING_ENCODED",
payload: updatedEncodeItems,
});
try {
storeEncodeItems.deleteData(encodeItem.id);
} catch (error) {
console.error("Failed to delete encode item:", error);
}
};

return (
<div className="relative">
<img
src={encodeItem.canvas}
alt={`Encode Image ${index + 1}`}
className={`w-100 h-100 object-cover opacity-100 transition-opacity duration-500 ease-in-out transform hover:opacity-100 mb-2 ${
encodeItem.selected ? "border border-blue-300 border-2" : ""
}`}
style={{
width: "100px",
height: "100px",
}}
onClick={() => zoomTo(encodeItem)}
/>
<button
className="absolute bottom-1 right-1 bg-red-500 hover:bg-red-600 w-4 h-4 text-white rounded flex items-center justify-center"
onClick={() => handleRemoveEncodeItem(encodeItem)}
>
<BsTrash className="fill-current w-3 h-3 cursor-pointer" />
</button>
</div>
);
};
15 changes: 10 additions & 5 deletions src/components/Item.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@ import { useContext } from "react";

import { BsTrash } from "react-icons/bs";
import { MainContext } from "./../contexts/MainContext";
import { storeItems } from "./../store/indexedDB";

const Item = ({ item }) => {
const Item = ({ item, index }) => {
const { items, dispatchSetItems, dispatchSetHighlightedItem } =
useContext(MainContext);

const deleteItem = (item) => {
const newItems = items.filter((i) => i.ol_uid !== item.ol_uid);
const newItems = items.filter((i) => {
return i.values_.id !== item.values_.id;
});
dispatchSetItems({
type: "SET_ITEMS",
payload: newItems,
});
// Delete from DB
storeItems.deleteData(item.values_.id);
};

const zoomToItem = (item) => {
Expand All @@ -24,7 +29,7 @@ const Item = ({ item }) => {

return (
<div
className="inline-flex justify-center items-center pr-2 pl-2 ml-3 text-sm font-medium rounded-full"
className="inline-flex justify-center items-center pr-1 pl-1 ml-1 text-xs font-medium rounded-full cursor-pointer"
style={{ background: `${item.values_.color}` }}
onMouseEnter={() => {
zoomToItem(item);
Expand All @@ -34,14 +39,14 @@ const Item = ({ item }) => {
}}
>
<BsTrash
className="fill-current w-3 h-3 mr-2 cursor-pointer"
className="fill-current w-3 h-3 mr-1 cursor-pointer"
onClick={() => {
deleteItem(item);
zoomToItem(null);
}}
title="Delete item"
></BsTrash>
<span>{item.values_.id}</span>
<span>{index}</span>
</div>
);
};
Expand Down
38 changes: 16 additions & 22 deletions src/components/MenuActions.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import React, { useContext, useCallback } from "react";
import { MainContext } from "../contexts/MainContext";
import { BsViewList } from "react-icons/bs";
import { unionPolygons } from "../utils/transformation";
import {
olFeatures2geojson,
geojson2olFeatures,
} from "../utils/featureCollection";
import { mergePolygonClass } from "../utils/transformation";
import { olFeatures2Features, features2olFeatures } from "../utils/convert";
import { storeItems } from "./../store/indexedDB";

export const MenuActions = () => {
const { items, dispatchSetItems } = useContext(MainContext);
Expand All @@ -20,36 +17,33 @@ export const MenuActions = () => {
[dispatchSetItems]
);

const mergPolygons = () => {
const fc = olFeatures2geojson(items);
const mergedFeatures = unionPolygons(fc.features);
const mergedItems = geojson2olFeatures(mergedFeatures);
const mergePolygons = () => {
const features = olFeatures2Features(items);
const mergedFeatures = mergePolygonClass(features);
const mergedItems = features2olFeatures(mergedFeatures);

setItems(mergedItems);
// Save merged features in DB
storeItems.deleteAllData();
mergedFeatures.forEach((item) => {
storeItems.addData({ ...item, id: item.properties.id });
});
};

document.addEventListener("keydown", (e) => {
// Merge polygonos
if (e.key === "m") {
mergPolygons();
mergePolygons();
}
});
return (
<div>
<div className="menuHeader">
<BsViewList></BsViewList>
<span className=" text-base font-medium flex-1 duration-200 false">
Polygon Action
</span>
</div>

<div className="flex flex-row mt-3">
<button
className="custom_button"
onClick={() => {
mergPolygons();
}}
onClick={() => mergePolygons()}
>
Merge (M)
Merge polygons (M)
</button>
</div>
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/components/MenuClass.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MainContext } from "../contexts/MainContext";
import { BsViewList, BsChevronDown } from "react-icons/bs";
import { ClassObj } from "./ClassObj";

import { getClassLayers } from "../utils/featureCollection";
import { getClassLayers } from "../utils/convert";

export const MenuClass = () => {
const { activeProject, activeClass } = useContext(MainContext);
Expand All @@ -25,19 +25,19 @@ export const MenuClass = () => {
}}
>
<BsViewList></BsViewList>
<span className=" text-base font-medium flex-1 duration-200 ">
<span className="text-sm text-base font-small flex-1 duration-200 false">
Classes
</span>
<span
className="inline-flex justify-center items-center px-2 ml-3 text-sm font-medium text-gray-800 bg-gray-200 rounded-full pr-4 pl-4"
className="inline-flex justify-center items-center px-2 ml-3 text-xs font-medium text-gray-800 bg-gray-200 rounded-full pr-4 pl-4"
style={{ background: `${activeClass ? activeClass.color : ""}` }}
>
{activeClass ? activeClass.name : ""}
</span>
<BsChevronDown></BsChevronDown>
</div>
{openMenu && (
<ul className="pt-2">
<ul className="pt-1">
{classes.map((classProps, index) => (
<ClassObj
key={index}
Expand Down
Loading