From 14f66a02045b2928c1797246325c7689bc964ebd Mon Sep 17 00:00:00 2001 From: ChromaticPanic <78883122+ChromaticPanic@users.noreply.github.com> Date: Fri, 5 Jul 2024 03:27:19 +0000 Subject: [PATCH 1/9] 167 Annotation init --- package.json | 2 +- src/_versions.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 4ab30fa..5ab8cb4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nachet-frontend", "private": true, - "version": "0.9.0", + "version": "0.9.1", "type": "module", "scripts": { "dev": "vite", diff --git a/src/_versions.ts b/src/_versions.ts index da384ab..1ae2040 100644 --- a/src/_versions.ts +++ b/src/_versions.ts @@ -11,8 +11,8 @@ export interface TsAppVersion { export const versions: TsAppVersion = { version: '0.9.0', name: 'nachet-frontend', - versionDate: '2024-06-22T20:47:06.767Z', - gitCommitHash: '', - versionLong: '0.9.0-', + versionDate: '2024-07-05T03:26:49.628Z', + gitCommitHash: '637ff43', + versionLong: '0.9.0-637ff43', }; export default versions; From 5347a3157ff718fad012088b6e4cbfd04429262b Mon Sep 17 00:00:00 2001 From: ChromaticPanic <78883122+ChromaticPanic@users.noreply.github.com> Date: Fri, 5 Jul 2024 05:14:03 +0000 Subject: [PATCH 2/9] ui fixes --- .../body/feedback_form/FeedbackForm.tsx | 8 ++- .../body/feedback_form/FreeformBox.tsx | 4 +- .../body/microscope_feed/MicroscopeFeed.tsx | 60 +++++++++++++++---- .../ScaledInferenceBox.tsx | 6 +- 4 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/components/body/feedback_form/FeedbackForm.tsx b/src/components/body/feedback_form/FeedbackForm.tsx index 896a99f..90acde4 100755 --- a/src/components/body/feedback_form/FeedbackForm.tsx +++ b/src/components/body/feedback_form/FeedbackForm.tsx @@ -117,6 +117,8 @@ export const NegativeFeedbackForm = ( }; }, []); + const formWidth = "300px"; + const { inference, position, classList, onCancel, onSubmit } = props; const [selectedClass, setSelectedClass] = useState(defaultClass); const [comment, setComment] = useState(reasons[2]); @@ -211,10 +213,10 @@ export const NegativeFeedbackForm = ( return ( { )} @@ -135,7 +136,6 @@ const FreeformBox = (props: FreeformBoxProps) => { { const height = windowSize.height * 0.605; const defaultBoxPosition: BoxCSS = { - minWidth: width, - minHeight: height, - maxWidth: width, - maxHeight: height, - left: 0, - top: 0, + minWidth: 100, + minHeight: 100, + maxWidth: 100, + maxHeight: 100, + left: width / 2 - 50, + top: height / 2 - 50, }; const [imageData, setImageData] = useState(null); @@ -237,6 +238,10 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { }); }; + const handleAnnotate = () => { + enterFeedbackMode(imageIndex, null); + }; + const exitFeedbackMode = () => { toggleShowInference(true); setFeedbackMode(false); @@ -245,16 +250,39 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { }; const enterFeedbackMode = ( - index: number | null, + index: number, boxPosition: BoxCSS | null, ) => { - if (imageData == null) { - return; - } - - if (index == null || boxPosition == null) { + if (boxPosition == null) { setScaledFeedbackBox(defaultBoxPosition); + const image = imageCache.find((image) => image.index === imageIndex) + if (image == null) { + return; + }; + const unscaledBox = getUnscaledCoordinates( + width, + height, + image.imageDims[0], + image.imageDims[1], + defaultBoxPosition, + ); + setInferenceForRevision({ + userId: uuid, + inferenceId: "", + boxes: [ + { + classId: "", + label: "", + boxId: "", + box: unscaledBox, + comment: "", + }, + ], + }); } else { + if (imageData == null) { + return; + } setScaledFeedbackBox(boxPosition); setInferenceForRevision({ userId: uuid, @@ -373,6 +401,14 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { handleInference(); }} /> + } + disabled={isWebcamActive} // Disable when the webcam is active + onClick={() => { + handleAnnotate(); + }} + />
{feedbackMode && scaledFeedbackBox && inferenceForRevision && ( diff --git a/src/components/body/scaled_inference_box/ScaledInferenceBox.tsx b/src/components/body/scaled_inference_box/ScaledInferenceBox.tsx index 43e948c..408e4c6 100644 --- a/src/components/body/scaled_inference_box/ScaledInferenceBox.tsx +++ b/src/components/body/scaled_inference_box/ScaledInferenceBox.tsx @@ -1,6 +1,6 @@ import { Button } from "@mui/material"; import { MouseEvent, useState } from "react"; -import { BoxCSS, Images } from "../../../common/types"; +import { BoxCSS, InferenceBox } from "../../../common/types"; import { SimpleFeedbackForm } from "../feedback_form"; import { getScaledBounds } from "../../../common"; @@ -8,14 +8,14 @@ const ScaledInferenceBox = (props: { index: number; imageWidth: number; imageHeight: number; - box: Images["boxes"][0]; + box: InferenceBox; canvasWidth: number; canvasHeight: number; label: string; visible: boolean; submitPositiveFeedback: (index: number) => void; handleNegativeFeedback: ( - index: number | null, + index: number, boxPosition: BoxCSS | null, ) => void; }): JSX.Element => { From 90dde5c0877b78d7f0035ac014b79a614d2ea6e8 Mon Sep 17 00:00:00 2001 From: ChromaticPanic <78883122+ChromaticPanic@users.noreply.github.com> Date: Fri, 5 Jul 2024 05:35:57 +0000 Subject: [PATCH 3/9] ui fixes annotation mode in components --- .../body/feedback_form/FeedbackForm.tsx | 50 +++++++++++-------- .../body/feedback_form/FreeformBox.tsx | 47 +++++++++-------- .../body/microscope_feed/MicroscopeFeed.tsx | 9 +++- 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/src/components/body/feedback_form/FeedbackForm.tsx b/src/components/body/feedback_form/FeedbackForm.tsx index 90acde4..71fee0c 100755 --- a/src/components/body/feedback_form/FeedbackForm.tsx +++ b/src/components/body/feedback_form/FeedbackForm.tsx @@ -71,7 +71,7 @@ export const SimpleFeedbackForm = ( flexWrap: "wrap", }} > - + void; onSubmit: (feedbackDataNegative: FeedbackDataNegative) => void; + isNewAnnotation: boolean; } export const NegativeFeedbackForm = ( @@ -119,7 +120,14 @@ export const NegativeFeedbackForm = ( const formWidth = "300px"; - const { inference, position, classList, onCancel, onSubmit } = props; + const { + inference, + position, + classList, + onCancel, + onSubmit, + isNewAnnotation, + } = props; const [selectedClass, setSelectedClass] = useState(defaultClass); const [comment, setComment] = useState(reasons[2]); @@ -255,24 +263,26 @@ export const NegativeFeedbackForm = ( }} disabled={comment === "No Seed"} /> - + {!isNewAnnotation && ( + + )} void; onCancel: () => void; + isNewAnnotation: boolean; } const FreeformBox = (props: FreeformBoxProps) => { - const { onSubmit, onCancel, position } = props; + const { onSubmit, onCancel, position, isNewAnnotation } = props; const [dragEnabled, setDragEnabled] = useState(true); const [topX, setTopX] = useState(position.left); const [topY, setTopY] = useState(position.top); @@ -123,27 +124,31 @@ const FreeformBox = (props: FreeformBoxProps) => { )} - - - + {!isNewAnnotation && ( + <> + + + - - - + + + + + )} diff --git a/src/components/body/microscope_feed/MicroscopeFeed.tsx b/src/components/body/microscope_feed/MicroscopeFeed.tsx index 54b8d4b..cb77c4d 100755 --- a/src/components/body/microscope_feed/MicroscopeFeed.tsx +++ b/src/components/body/microscope_feed/MicroscopeFeed.tsx @@ -139,6 +139,7 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { const [imageData, setImageData] = useState(null); const [feedbackMode, setFeedbackMode] = useState(false); + const [isNewAnnotation, setIsNewAnnotation] = useState(false); const [scaledFeedbackBox, setScaledFeedbackBox] = useState( null, ); @@ -239,6 +240,7 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { }; const handleAnnotate = () => { + setIsNewAnnotation(true); enterFeedbackMode(imageIndex, null); }; @@ -247,6 +249,7 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { setFeedbackMode(false); setInferenceForRevision(null); setScaledFeedbackBox(null); + setIsNewAnnotation(false); }; const enterFeedbackMode = ( @@ -396,7 +399,7 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { } - disabled={isWebcamActive} // Disable when the webcam is active + disabled={isWebcamActive || imageCache.length == 0} // Disable when the webcam is active onClick={() => { handleInference(); }} @@ -404,7 +407,7 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { } - disabled={isWebcamActive} // Disable when the webcam is active + disabled={isWebcamActive || imageCache.length == 0} // Disable when the webcam is active onClick={() => { handleAnnotate(); }} @@ -419,11 +422,13 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { classList={classList} onCancel={exitFeedbackMode} onSubmit={submitNegativeFeedback} + isNewAnnotation={isNewAnnotation} /> )} From 5663b752b58d8eec1f237ac3fb13a38dde28a0e6 Mon Sep 17 00:00:00 2001 From: ChromaticPanic <78883122+ChromaticPanic@users.noreply.github.com> Date: Fri, 5 Jul 2024 05:45:00 +0000 Subject: [PATCH 4/9] broken --- .../body/microscope_feed/MicroscopeFeed.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/components/body/microscope_feed/MicroscopeFeed.tsx b/src/components/body/microscope_feed/MicroscopeFeed.tsx index cb77c4d..af90002 100755 --- a/src/components/body/microscope_feed/MicroscopeFeed.tsx +++ b/src/components/body/microscope_feed/MicroscopeFeed.tsx @@ -216,6 +216,22 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { }); }; + const submitNewAnnotation = (feedbackDataNegative: FeedbackDataNegative) => { + if (imageData === null) { + return; + } + console.log("Submitting new annotation"); + + sendNewAnnotation(feedbackDataNegative, backendUrl) + .then(() => { + console.log("New Annotation submitted successfully"); + exitFeedbackMode(); + }) + .catch((error) => { + console.error("Error submitting new annotation: ", error); + }); + }; + const handleFreeformSubmit = (box: BoxCSS) => { setScaledFeedbackBox(box); setInferenceForRevision((prev) => { From 0752d5546ae734fd8a56280be161662d345111fb Mon Sep 17 00:00:00 2001 From: ChromaticPanic <78883122+ChromaticPanic@users.noreply.github.com> Date: Fri, 5 Jul 2024 06:55:10 +0000 Subject: [PATCH 5/9] box scaling fix --- src/common/imageutils.ts | 4 +- .../body/feedback_form/FreeformBox.tsx | 48 +++++++++--------- .../body/microscope_feed/MicroscopeFeed.tsx | 49 +++++-------------- .../ScaledInferenceBox.tsx | 2 +- 4 files changed, 38 insertions(+), 65 deletions(-) diff --git a/src/common/imageutils.ts b/src/common/imageutils.ts index 864292a..ecf5afb 100644 --- a/src/common/imageutils.ts +++ b/src/common/imageutils.ts @@ -37,8 +37,8 @@ export const getUnscaledCoordinates = ( const scaleFactorHeight = itemHeight / containerHeight; const topX = box.left * scaleFactorWidth; const topY = box.top * scaleFactorHeight; - const bottomX = box.left + box.minWidth * scaleFactorWidth; - const bottomY = box.top + box.minHeight * scaleFactorHeight; + const bottomX = (box.left + box.minWidth) * scaleFactorWidth; + const bottomY = (box.top + box.minHeight) * scaleFactorHeight; return { topX, topY, diff --git a/src/components/body/feedback_form/FreeformBox.tsx b/src/components/body/feedback_form/FreeformBox.tsx index 69e5ac7..9e267ed 100644 --- a/src/components/body/feedback_form/FreeformBox.tsx +++ b/src/components/body/feedback_form/FreeformBox.tsx @@ -12,11 +12,10 @@ interface FreeformBoxProps { position: BoxCSS; onSubmit: (boxPosition: BoxCSS) => void; onCancel: () => void; - isNewAnnotation: boolean; } const FreeformBox = (props: FreeformBoxProps) => { - const { onSubmit, onCancel, position, isNewAnnotation } = props; + const { onSubmit, onCancel, position } = props; const [dragEnabled, setDragEnabled] = useState(true); const [topX, setTopX] = useState(position.left); const [topY, setTopY] = useState(position.top); @@ -124,31 +123,28 @@ const FreeformBox = (props: FreeformBoxProps) => { )} - {!isNewAnnotation && ( - <> - - - - - - - - )} + + + + + + + diff --git a/src/components/body/microscope_feed/MicroscopeFeed.tsx b/src/components/body/microscope_feed/MicroscopeFeed.tsx index af90002..cf90d7c 100755 --- a/src/components/body/microscope_feed/MicroscopeFeed.tsx +++ b/src/components/body/microscope_feed/MicroscopeFeed.tsx @@ -216,22 +216,6 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { }); }; - const submitNewAnnotation = (feedbackDataNegative: FeedbackDataNegative) => { - if (imageData === null) { - return; - } - console.log("Submitting new annotation"); - - sendNewAnnotation(feedbackDataNegative, backendUrl) - .then(() => { - console.log("New Annotation submitted successfully"); - exitFeedbackMode(); - }) - .catch((error) => { - console.error("Error submitting new annotation: ", error); - }); - }; - const handleFreeformSubmit = (box: BoxCSS) => { setScaledFeedbackBox(box); setInferenceForRevision((prev) => { @@ -257,7 +241,7 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { const handleAnnotate = () => { setIsNewAnnotation(true); - enterFeedbackMode(imageIndex, null); + enterFeedbackMode(imageIndex, defaultBoxPosition); }; const exitFeedbackMode = () => { @@ -268,26 +252,23 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { setIsNewAnnotation(false); }; - const enterFeedbackMode = ( - index: number, - boxPosition: BoxCSS | null, - ) => { - if (boxPosition == null) { - setScaledFeedbackBox(defaultBoxPosition); - const image = imageCache.find((image) => image.index === imageIndex) - if (image == null) { - return; - }; + const enterFeedbackMode = (index: number, boxPosition: BoxCSS) => { + if (imageData == null) { + return; + } + + setScaledFeedbackBox(boxPosition); + if (isNewAnnotation) { const unscaledBox = getUnscaledCoordinates( width, height, - image.imageDims[0], - image.imageDims[1], - defaultBoxPosition, + imageData.imageDims[0], + imageData.imageDims[1], + boxPosition, ); setInferenceForRevision({ userId: uuid, - inferenceId: "", + inferenceId: imageData.boxes[0].inferenceId, boxes: [ { classId: "", @@ -299,10 +280,6 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { ], }); } else { - if (imageData == null) { - return; - } - setScaledFeedbackBox(boxPosition); setInferenceForRevision({ userId: uuid, inferenceId: imageData.boxes[index].inferenceId, @@ -322,6 +299,7 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { ], }); } + toggleShowInference(false); setFeedbackMode(true); }; @@ -444,7 +422,6 @@ const MicroscopeFeed = (props: MicroscopeFeedProps): JSX.Element => { position={scaledFeedbackBox} onCancel={exitFeedbackMode} onSubmit={handleFreeformSubmit} - isNewAnnotation={isNewAnnotation} /> )} diff --git a/src/components/body/scaled_inference_box/ScaledInferenceBox.tsx b/src/components/body/scaled_inference_box/ScaledInferenceBox.tsx index 408e4c6..0b97da5 100644 --- a/src/components/body/scaled_inference_box/ScaledInferenceBox.tsx +++ b/src/components/body/scaled_inference_box/ScaledInferenceBox.tsx @@ -16,7 +16,7 @@ const ScaledInferenceBox = (props: { submitPositiveFeedback: (index: number) => void; handleNegativeFeedback: ( index: number, - boxPosition: BoxCSS | null, + boxPosition: BoxCSS, ) => void; }): JSX.Element => { const { From a64682f2708aeefde5e9e3f219db4d14ff3d512a Mon Sep 17 00:00:00 2001 From: ChromaticPanic <78883122+ChromaticPanic@users.noreply.github.com> Date: Fri, 5 Jul 2024 07:51:11 +0000 Subject: [PATCH 6/9] feedback form --- .../body/feedback_form/FeedbackForm.tsx | 117 ++++++++++++++---- 1 file changed, 91 insertions(+), 26 deletions(-) diff --git a/src/components/body/feedback_form/FeedbackForm.tsx b/src/components/body/feedback_form/FeedbackForm.tsx index 71fee0c..49bb344 100755 --- a/src/components/body/feedback_form/FeedbackForm.tsx +++ b/src/components/body/feedback_form/FeedbackForm.tsx @@ -3,7 +3,6 @@ import { Box, IconButton, FormControl, - // FormLabel, Button, Autocomplete, TextField, @@ -12,6 +11,14 @@ import { MenuItem, SelectChangeEvent, FilterOptionsState, + Paper, + TableContainer, + Table, + TableBody, + TableRow, + TableCell, + TableHead, + Typography, } from "@mui/material"; import CheckCircleOutlinedIcon from "@mui/icons-material/CheckCircleOutlined"; import CancelOutlinedIcon from "@mui/icons-material/CancelOutlined"; @@ -71,7 +78,10 @@ export const SimpleFeedbackForm = ( flexWrap: "wrap", }} > - + { - return ["No Seed", "Multi Seed", "Wrong Seed", "Wrong Seed not in List"]; + return [ + "Seed not Detected", + "Wrong Seed", + "No Seed", + "Multi Seed", + "Wrong Seed not in List", + ]; }, []); /* Section stub convert to prop or use state when backend defined */ @@ -129,7 +145,7 @@ export const NegativeFeedbackForm = ( isNewAnnotation, } = props; const [selectedClass, setSelectedClass] = useState(defaultClass); - const [comment, setComment] = useState(reasons[2]); + const [comment, setComment] = useState(reasons[1]); const filter = createFilterOptions(); @@ -218,6 +234,12 @@ export const NegativeFeedbackForm = ( } }, [comment]); + useEffect(() => { + if (isNewAnnotation) { + setComment(reasons[0]); + } + }, [isNewAnnotation, reasons]); + return ( - + + + Feedback + + + + + + + Bounding Box + _ + + + + + TopX + + {inference.boxes[0].box.topX.toFixed(2)} + + + + TopY + + {inference.boxes[0].box.topY.toFixed(2)} + + + + BottomX + + {inference.boxes[0].box.bottomX.toFixed(2)} + + + + BottomY + + {inference.boxes[0].box.bottomY.toFixed(2)} + + + +
+
} @@ -263,26 +326,27 @@ export const NegativeFeedbackForm = ( }} disabled={comment === "No Seed"} /> - {!isNewAnnotation && ( - - )} + +