Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upload folder to the viewer #31

Merged
merged 6 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
72 changes: 27 additions & 45 deletions src/viewer/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,22 @@
// Created by O. Vysotska in 2023
import { useState, useEffect } from "react";
import { useState } from "react";
import "./App.css";
import { ProtoLoader, MessageType } from "./ProtoLoader";
import { CostMatrix, CostMatrixElement } from "./costMatrix";
import { ImagesLoader } from "./ImagesLoader";
import {
MatchingResultElement,
readMatchingResultFromProto,
} from "./matchingResult";
import CostMatrixComponent from "./CostMatrixComponent";
import { CostMatrixElement } from "./resources/costMatrix";
import { ImagesPreview } from "./components/ImagesPreview";
import CostMatrixComponent from "./components/CostMatrixComponent";

import DataLoader from "./components/DataLoader";

function App() {
const [costMatrixProto, setCostMatrixProto] = useState(null);
const [costMatrix, setCostMatrix] = useState<CostMatrix>();
const [matchingResultProto, setMatchingResultProto] = useState(null);
const [matchingResult, setMatchingResult] =
useState<MatchingResultElement[]>();
const [costMatrixProtoFile, setCostMatrixProtoFile] = useState<File>();
const [matchingResultProtoFile, setMatchingResultProtoFile] =
useState<File>();
const [queryImageFiles, setQueryImageFiles] = useState<File[]>();
const [referenceImageFiles, setReferenceImageFiles] = useState<File[]>();

const [selectedCostMatrixElement, setSelectedCostMatrixElement] =
useState<CostMatrixElement>();

useEffect(() => {
if (costMatrixProto != null) {
console.log("Cost Matrix proto is loaded", costMatrixProto);
setCostMatrix(new CostMatrix(costMatrixProto));
}
}, [costMatrixProto]);

useEffect(() => {
console.log("Matching result proto changed", matchingResultProto);
setMatchingResult(readMatchingResultFromProto(matchingResultProto));
}, [matchingResultProto]);

return (
<div className="App">
<div
Expand All @@ -43,23 +29,17 @@ function App() {
}}
>
<h1 style={{ textAlign: "center" }}>Cost Matrix Viewer</h1>
<DataLoader
setCostMatrixProtoFile={setCostMatrixProtoFile}
setMatchingResultProtoFile={setMatchingResultProtoFile}
setQueryImageFiles={setQueryImageFiles}
setReferenceImageFiles={setReferenceImageFiles}
/>
<div className="costMatrix" style={{ backgroundColor: "ghostwhite" }}>
<div style={{display: "flex", flexDirection: "column", alignItems: "center"}}>
<div>
<ProtoLoader
onLoad={setCostMatrixProto}
messageType={MessageType.CostMatrix}
/>
<ProtoLoader
onLoad={setMatchingResultProto}
messageType={MessageType.MatchingResult}
/>
</div>
</div>
{costMatrix && (
{costMatrixProtoFile && (
<CostMatrixComponent
costMatrix={costMatrix}
matchingResult={matchingResult}
costMatrixProtoFile={costMatrixProtoFile}
matchingResultProtoFile={matchingResultProtoFile}
setSelectedCostMatrixElement={setSelectedCostMatrixElement}
/>
)}
Expand All @@ -77,14 +57,16 @@ function App() {
}}
>
<div>
<ImagesLoader
imageType={"Query"}
<ImagesPreview
imageFiles={queryImageFiles}
imageSource={"Query"}
showImageId={selectedCostMatrixElement?.queryId}
/>
</div>
<div>
<ImagesLoader
imageType={"Reference"}
<ImagesPreview
imageFiles={referenceImageFiles}
imageSource={"Reference"}
showImageId={selectedCostMatrixElement?.refId}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
// Created by O. Vysotska in 2023
import { useState, useEffect } from "react";
import { CostMatrix, CostMatrixElement } from "./costMatrix";
import { CostMatrix, CostMatrixElement } from "../resources/costMatrix";
import { ImageCostMatrix, ZoomBlockParams } from "./ImageCostMatrix";
import { MatchingResultElement } from "./matchingResult";
import InteractiveCostMatrix from "./InteractiveCostMatrix";

import { FormGroup, FormControlLabel, Switch } from "@mui/material";

import {
readMatchingResultFromProto,
readProtoFromFile,
MatchingResultElement,
ProtoMessageType,
} from "../resources/readers";

function getMatchingResultInZoomBlock(
results: MatchingResultElement[],
zoomParams: ZoomBlockParams
Expand All @@ -21,12 +27,13 @@ function getMatchingResultInZoomBlock(
}

type CostMatrixProps = {
costMatrix: CostMatrix;
matchingResult?: MatchingResultElement[];
costMatrixProtoFile: File;
matchingResultProtoFile?: File;
setSelectedCostMatrixElement: (element: CostMatrixElement) => void;
};

function CostMatrixComponent(props: CostMatrixProps): React.ReactElement {
const [costMatrix, setCostMatrix] = useState<CostMatrix>();
const [image, setImage] = useState<ImageBitmap>();
const [matchingResult, setMatchingResult] =
useState<MatchingResultElement[]>();
Expand All @@ -37,6 +44,21 @@ function CostMatrixComponent(props: CostMatrixProps): React.ReactElement {
const [selectedElement, setSelectedElement] = useState<CostMatrixElement>();

const { setSelectedCostMatrixElement } = props;

// Read costMatrix from proto file.
useEffect(() => {
if (props.costMatrixProtoFile == null) {
return;
}
readProtoFromFile(props.costMatrixProtoFile, ProtoMessageType.CostMatrix)
.then((costMatrixProto) => {
setCostMatrix(new CostMatrix(costMatrixProto));
})
.catch((e) => {
console.log("Couldn't read file", props.costMatrixProtoFile);
});
}, [props.costMatrixProtoFile]);

useEffect(() => {
if (selectedElement == null) {
return;
Expand All @@ -45,29 +67,42 @@ function CostMatrixComponent(props: CostMatrixProps): React.ReactElement {
}, [selectedElement, setSelectedCostMatrixElement]);

useEffect(() => {
if (props.costMatrix != null) {
props.costMatrix.createImage().then((result) => {
if (costMatrix != null) {
costMatrix.createImage().then((result) => {
setImage(result);
});
}
}, [props.costMatrix]);
}, [costMatrix]);

// Read Matching result proto file
useEffect(() => {
setMatchingResult(props.matchingResult);
}, [props.matchingResult]);
if (props.matchingResultProtoFile == null) {
return;
}
readProtoFromFile(
props.matchingResultProtoFile,
ProtoMessageType.MatchingResult
)
.then((matchingResultProto) => {
setMatchingResult(readMatchingResultFromProto(matchingResultProto));
})
.catch((e) => {
console.log("Couldn't read file", props.matchingResultProtoFile);
});
}, [props.matchingResultProtoFile]);

useEffect(() => {
if (zoomParams == null || props.costMatrix == null) {
if (zoomParams == null || costMatrix == null) {
return;
}
setZoomedCostMatrix(
props.costMatrix.getSubMatrix(
costMatrix.getSubMatrix(
zoomParams.topLeftX,
zoomParams.topLeftY,
zoomParams.windowHeightPx
)
);
}, [zoomParams, props.costMatrix]);
}, [zoomParams, costMatrix]);

function showMatchingResult(event: any) {
if (event.target.checked) {
Expand Down
77 changes: 77 additions & 0 deletions src/viewer/src/components/DataLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import Alert from "@mui/material/Alert";
ovysotska marked this conversation as resolved.
Show resolved Hide resolved

type DataLoaderProps = {
setMatchingResultProtoFile: (file: File) => void;
setCostMatrixProtoFile: (file: File) => void;
setQueryImageFiles: (files: File[]) => void;
setReferenceImageFiles: (file: File[]) => void;
};

function DataLoader(props: DataLoaderProps): React.ReactElement {
async function onChange(event: React.ChangeEvent<HTMLInputElement>) {
const fileList = event.target.files;
if (fileList == null) {
return;
}
const files = Array.from(fileList);

const costMatrixProtoFile = files.find((file) => {
return file.webkitRelativePath.split("/")[1].endsWith(".CostMatrix.pb");
});
if (costMatrixProtoFile == null) {
console.warn("CostMatrix proto file was not found");
} else {
props.setCostMatrixProtoFile(costMatrixProtoFile);
}

const matchingResultProtoFile = files.find((file) => {
return file.webkitRelativePath
.split("/")[1]
.endsWith(".MatchingResult.pb");
});

if (matchingResultProtoFile == null) {
console.warn("MatchingResult proto file was not found");
} else {
props.setMatchingResultProtoFile(matchingResultProtoFile);
}

const queryImageFiles = files.filter((file) => {
console.log(file.webkitRelativePath.split("/")[1]);
return file.webkitRelativePath.split("/")[1] === "query_images";
});
if (queryImageFiles.length === 0) {
props.setQueryImageFiles([]);
} else {
props.setQueryImageFiles(queryImageFiles);
}

const referenceImageFiles = files.filter((file) => {
return file.webkitRelativePath.split("/")[1] === "reference_images";
});
if (referenceImageFiles.length === 0) {
console.warn("Reference images was not found");
props.setReferenceImageFiles([]);
} else {
props.setReferenceImageFiles(referenceImageFiles);
}
}

return (
<div style={{ textAlign: "center" }}>
<label htmlFor="folderPicker">Select folder </label>
<input
type="file"
id="folderPicker"
name="fileList"
/* @ts-expect-error */
webkitdirectory=""
directory=""
multiple
onChange={onChange}
/>
</div>
);
}

export default DataLoader;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { forwardRef } from "react";
import { useState, useRef, useEffect } from "react";
import { MatchingResultElement } from "./matchingResult";
import { MatchingResultElement } from "../resources/readers";

const kZoomWindowPx = 30;

Expand Down
Loading
Loading