Skip to content

Commit

Permalink
Merge branch 'master' into snyk-upgrade-f5cb4ec876db40df5186c60c09cd397f
Browse files Browse the repository at this point in the history
  • Loading branch information
sumn2u authored Jun 20, 2024
2 parents 07efdf8 + b907a84 commit b72d012
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 32 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Annotate-Lab is an open-source application designed for image annotation, compri
- [Contributing](#contributing)
- [License](#license)

## Project Structure
## Project Structure [[documentation page]](https://annotate-docs.dwaste.live/overview/project-structure)
```sh

annotation-lab/
Expand Down Expand Up @@ -68,7 +68,7 @@ annotation-lab/
- **app.py**: Main Flask application file.
- **requirements.txt**: Contains server dependencies.

## Settings
## Settings [[documentation page]](https://annotate-docs.dwaste.live/fundamentals/set-up-and-run/configuration)
One can configure the tools, tags, upload images and do many more from the settings.

![configuration](./sample_images/configuration.png)
Expand All @@ -85,7 +85,7 @@ One can configure the tools, tags, upload images and do many more from the setti
- pandas
- Other dependencies as listed in `requirements.txt`

## Setup and Installation
## Setup and Installation [[documentation page]](https://annotate-docs.dwaste.live/fundamentals/set-up-and-run)

### Client Setup
1. Navigate to the `client` directory:
Expand Down Expand Up @@ -195,7 +195,7 @@ This command discovers and runs all test files (`test_*.py`) in the `server/test
2. Use the user interface to upload and annotate images.
3. The annotations and other interactions will be handled by the Flask server running at [http://localhost:5000](http://localhost:5000).

## Configurations (Optional)
## Configurations (Optional) [[documentation page]](https://annotate-docs.dwaste.live/overview/customization)
You can customize various aspects of Annotate-Lab through configuration settings. To do this, modify the `config.py` file in the `server` directory or the `config.js` file in the `client` directory.
```python
# config.py
Expand Down Expand Up @@ -314,7 +314,7 @@ Sample of annotated image along with its mask and settings is show below.
```

## Troubleshooting
## Troubleshooting [[documentation page]](https://annotate-docs.dwaste.live/troubleshooting)

- Ensure that both the client and server are running.
- Check the browser console and terminal for any errors and troubleshoot accordingly.
Expand Down
28 changes: 17 additions & 11 deletions client/src/Annotation/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const userReducer = (state, action) => {
export default () => {
const [selectedImageIndex, changeSelectedImageIndex] = useState(0)
const [showLabel, setShowLabel] = useState(false)
const [isSettingsOpen, setIsSettingsOpen] = useState(false)
const [imageNames, setImageNames] = useState([])
const settingsConfig = useSettings()
const { showSnackbar } = useSnackbar();
Expand Down Expand Up @@ -112,6 +113,7 @@ export default () => {
images: payload
};
});
changeSelectedImageIndex(0)
setImageNames(payload)
}
};
Expand All @@ -125,7 +127,7 @@ export default () => {
const images = await Promise.all(fetchPromises);
setSettings(prevSettings => ({
...prevSettings,
images
imagesBlob: images
}));
setImageNames(images);
} catch (error) {
Expand All @@ -144,24 +146,24 @@ export default () => {
const savedConfiguration = settingsConfig.settings|| {};
if (savedConfiguration.configuration && savedConfiguration.configuration.labels.length > 0) {
setSettings(savedConfiguration);
setShowLabel(true)
if (settings.images.length > 0) {
fetchImages(settings.images);
}
}
}


const showAnnotationLab = () => {
preloadConfiguration();
}
useEffect(() => {
preloadConfiguration();
if (settings.images.length > 0) {
fetchImages(settings.images);
} else {
setLoading(false);
}
}, [settingsConfig.settings, showLabel]);
}, [ ]);


return (
<>
{ !showLabel ? ( // Render loading indicator if loading is true
<SetupPage setConfiguration={setConfiguration} settings={settings} setShowLabel={setShowLabel}/>
<SetupPage setConfiguration={setConfiguration} settings={settings} setShowLabel={setShowLabel} showAnnotationLab={showAnnotationLab}/>
) : (
<Annotator
taskDescription={settings.taskDescription || "Annotate each image according to this _markdown_ specification."}
Expand All @@ -179,7 +181,11 @@ export default () => {
showTags={true}
selectedTool= {getToolSelectionType(settings.configuration.regions)}
openDocs={() => window.open(config.DOCS_URL, '_blank')}
hideSettings={true}
hideSettings={false}
onShowSettings = {() => {
setIsSettingsOpen(!isSettingsOpen)
setShowLabel(false)
}}
selectedImageIndex={selectedImageIndex}
/>)}
</>
Expand Down
6 changes: 5 additions & 1 deletion client/src/Annotator/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const Annotator = ({
settings,
keypointDefinitions,
onSelectJump,
onShowSettings,
openDocs,
hideHeader,
hideHeaderText,
Expand Down Expand Up @@ -160,6 +161,8 @@ export const Annotator = ({
}
} else if (action.buttonName === "Docs" ) {
return openDocs();
} else if (action.buttonName === "Settings") {
return onShowSettings();
}
}
dispatchToReducer(action);
Expand Down Expand Up @@ -241,7 +244,8 @@ Annotator.propTypes = {
hideSave: PropTypes.bool,
enabledRegionProps: PropTypes.arrayOf(PropTypes.string),
userReducer: PropTypes.func,
onSelectJump: PropTypes.func
onSelectJump: PropTypes.func,
onShowSettings: PropTypes.func
}

export default Annotator
19 changes: 18 additions & 1 deletion client/src/ImageUpload/ImageUpload.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,23 @@ jest.mock('../config.js', () => ({

jest.mock('axios')

const images = [
{
src: 'http://127.0.0.1:5000/uploads/clothes.jpeg',
name: 'clothes',
selectedClsList: '',
comment: '',
processed: false,
},
{
src: 'http://127.0.0.1:5000/uploads/shoes.jpeg',
name: 'shoes',
selectedClsList: '',
comment: '',
processed: false,
},
];

// Mock the useTranslation hook
jest.mock('react-i18next', () => ({
useTranslation: () => ({
Expand All @@ -33,7 +50,7 @@ useSnackbar.mockReturnValue({ showSnackbar: mockShowSnackbar })

const renderComponent = (props = {}) =>
render(
<ImageUpload {...props} />
<ImageUpload settingsImages={images} {...props} />
)

describe('ImageUpload', () => {
Expand Down
19 changes: 15 additions & 4 deletions client/src/ImageUpload/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { useSnackbar } from '../SnackbarContext';
import { useTranslation } from "react-i18next"
import config from '../config.js';

const ImageUpload = ({ onImageUpload }) => {
const ImageUpload = ({ onImageUpload, settingsImages }) => {
const { t } = useTranslation();
const { showSnackbar } = useSnackbar();
const [images, setImages] = useState([]);
const [images, setImages] = useState(settingsImages);
const [loading, setLoading] = useState(false);
const [progress, setProgress] = useState(0);

Expand Down Expand Up @@ -102,7 +102,18 @@ const ImageUpload = ({ onImageUpload }) => {

const handleRemoveImage = (index) => {
const imageToRemove = images[index];
deleteImage(imageToRemove.filename);
if (imageToRemove && !imageToRemove.filename) {
if (imageToRemove.src) {
let parts = imageToRemove.src.split('/');
let filename = parts[parts.length - 1];
imageToRemove.filename = filename;
}
}
if (imageToRemove && imageToRemove.filename) {
deleteImage(imageToRemove.filename);
} else {
console.error('Error deleting image: imageToRemove or imageToRemove.filename is undefined');
}
};

const { getRootProps, getInputProps, isDragActive } = useDropzone({
Expand Down Expand Up @@ -165,7 +176,7 @@ const ImageUpload = ({ onImageUpload }) => {
alignItems="center"
>
<img
src={image.preview}
src={image.preview || image.src}
alt="preview"
style={{
width: '100px',
Expand Down
1 change: 0 additions & 1 deletion client/src/RegionSelectorSidebarBox/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ const RowLayout = ({
const RowHeader = ({ regions, onChangeRegion, onDeleteRegion }) => {
const visible = regions.find(r => r.visible === false) == null;
const locked = regions.find(r => r.locked === false) == null;
console.log(visible, locked)
const {t} = useTranslation();
return (
<RowLayout
Expand Down
20 changes: 11 additions & 9 deletions client/src/SetupPage/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ const StyledCardContent = styled(CardContent)(({ theme }) => ({
}));


export const SetupPage = ({setConfiguration, settings, setShowLabel}) => {
export const SetupPage = ({setConfiguration, settings, setShowLabel, showAnnotationLab}) => {
const { configuration } = settings;
const [currentTab, setTab] = useState("datatype");
const [hasConfig, setHasConfig] = useState(false);
const settingsConfig = useSettings()
Expand All @@ -63,13 +64,15 @@ export const SetupPage = ({setConfiguration, settings, setShowLabel}) => {

const handleImageUpload = (images) => {
const extractedNames = images.map(image => {
const src = image.preview;
const selectedClsList = ''; // Assuming 'cls' information is not present
const comment = ''; // Assuming 'comment' information is not present
const processed = false; // Assuming 'processed' information is not present
const name = image.filename.split('.')[0]; // Remove file extension from image name
const src = image.preview || image.src;
const selectedClsList = '' || image.selectedClsList; // Assuming 'cls' information is not present
const comment = '' || image.comment; // Assuming 'comment' information is not present
const processed = false || image.processed; // Assuming 'processed' information is not present
const name = image.filename?.split('.')[0] || image.name; // Remove file extension from image name
return { src, name, selectedClsList, comment, processed };
});
settings.images = extractedNames;
settingsConfig.changeSetting('settings',settings);
setConfiguration({type: "UPDATE_IMAGES", payload: extractedNames})
};

Expand All @@ -78,11 +81,11 @@ export const SetupPage = ({setConfiguration, settings, setShowLabel}) => {
}

const showLab = ()=> {
const { configuration } = settings;
const hasLabels = configuration.labels.length > 0;
setShowLabel(hasLabels)
if(hasLabels) {
settingsConfig.changeSetting('settings',settings);
showAnnotationLab()
}
}

Expand All @@ -94,7 +97,6 @@ export const SetupPage = ({setConfiguration, settings, setShowLabel}) => {
const isConfigComplete = settings.configuration.labels.length > 0;
const isImagesUploaded = settings.images.length > 0;


return (
<Box display="flex" justifyContent="center" minHeight="100vh" marginTop={"5rem"}>
<Box>
Expand Down Expand Up @@ -153,7 +155,7 @@ export const SetupPage = ({setConfiguration, settings, setShowLabel}) => {
<Typography gutterBottom sx={{ fontWeight: 'bold', color: 'rgb(66, 66, 66)', fontSize: '18px' }}>
{t("btn.upload_images")}
</Typography>
<ImageUpload onImageUpload={handleImageUpload} />
<ImageUpload onImageUpload={handleImageUpload} settingsImages={settings.images} />
</Box>
<Box display="flex" justifyContent="end">
<Button variant="contained" disabled={!isImagesUploaded} onClick={showLab} disableElevation>
Expand Down
Binary file modified sample_images/example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b72d012

Please sign in to comment.