검색 업로드
This commit is contained in:
parent
6c9d0690aa
commit
110d0d3b1b
@ -10,7 +10,7 @@ import Typography from '@mui/material/Typography';
|
|||||||
import SearchIcon from '@mui/icons-material/Search';
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
import TextField from '@mui/material/TextField';
|
import TextField from '@mui/material/TextField';
|
||||||
import Skeleton from '@mui/material/Skeleton';
|
import Skeleton from '@mui/material/Skeleton';
|
||||||
import { InputAdornment, Stack, Button } from '@mui/material';
|
import { InputAdornment, Stack, Button, Modal } from '@mui/material';
|
||||||
import MenuList from '@mui/material/MenuList';
|
import MenuList from '@mui/material/MenuList';
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||||
@ -25,8 +25,8 @@ import FormControl from '@mui/material/FormControl';
|
|||||||
import Select from '@mui/material/Select';
|
import Select from '@mui/material/Select';
|
||||||
import { useCurrencyConvert } from 'src/hooks/convertCurrency';
|
import { useCurrencyConvert } from 'src/hooks/convertCurrency';
|
||||||
import { useCurrencyFormatter } from 'src/hooks/formatCurrency';
|
import { useCurrencyFormatter } from 'src/hooks/formatCurrency';
|
||||||
const axios = require("axios");
|
const axios = require('axios');
|
||||||
const fs = require("fs");
|
const fs = require('fs');
|
||||||
const FormData = require('form-data');
|
const FormData = require('form-data');
|
||||||
// api
|
// api
|
||||||
import * as api from 'src/services';
|
import * as api from 'src/services';
|
||||||
@ -59,6 +59,10 @@ export default function Search({ ...props }) {
|
|||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [search, setSearch] = React.useState('');
|
const [search, setSearch] = React.useState('');
|
||||||
|
const [image, setImage] = React.useState(null);
|
||||||
|
const [predictions, setPredictions] = React.useState([]);
|
||||||
|
const [showModal, setShowModal] = React.useState(false);
|
||||||
|
const canvasRef = React.useRef(null);
|
||||||
|
|
||||||
const { data: filters, isLoading: filtersLoading } = useQuery(['get-search-filters'], () => api.getSearchFilters());
|
const { data: filters, isLoading: filtersLoading } = useQuery(['get-search-filters'], () => api.getSearchFilters());
|
||||||
const { mutate, isLoading } = useMutation('search', api.search, {
|
const { mutate, isLoading } = useMutation('search', api.search, {
|
||||||
@ -69,6 +73,18 @@ export default function Search({ ...props }) {
|
|||||||
|
|
||||||
const [focus, setFocus] = React.useState(true);
|
const [focus, setFocus] = React.useState(true);
|
||||||
|
|
||||||
|
// 파일 선택 핸들러
|
||||||
|
const handleFileChange = (event) => {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = () => {
|
||||||
|
setImage(reader.result); // 이미지 상태 업데이트
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleListItemClick = (prop) => {
|
const handleListItemClick = (prop) => {
|
||||||
if (multiSelect) {
|
if (multiSelect) {
|
||||||
const matched = state.selected.filter((v) => prop._id === v._id);
|
const matched = state.selected.filter((v) => prop._id === v._id);
|
||||||
@ -104,66 +120,82 @@ export default function Search({ ...props }) {
|
|||||||
|
|
||||||
const fileInputRef = React.useRef(null);
|
const fileInputRef = React.useRef(null);
|
||||||
|
|
||||||
// 이미지를 찾는 함수
|
const detectWithRoboflow = async () => {
|
||||||
const handleImageSearch = () => {
|
if (!image) return;
|
||||||
if (fileInputRef.current) {
|
|
||||||
fileInputRef.current.click(); // 숨겨진 파일 입력을 트리거
|
const canvas = canvasRef.current;
|
||||||
|
const ctx = canvas?.getContext('2d');
|
||||||
|
|
||||||
|
const img = new Image();
|
||||||
|
img.src = image;
|
||||||
|
|
||||||
|
img.onload = async () => {
|
||||||
|
// 캔버스 크기 설정
|
||||||
|
canvas.width = img.width;
|
||||||
|
canvas.height = img.height;
|
||||||
|
ctx.drawImage(img, 0, 0);
|
||||||
|
|
||||||
|
// 이미지를 Blob으로 변환
|
||||||
|
const response = await fetch(image);
|
||||||
|
const blob = await response.blob();
|
||||||
|
|
||||||
|
// API 호출
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', blob);
|
||||||
|
|
||||||
|
const apiEndpoint = `https://detect.roboflow.com/picup/1?api_key=s9OJq0UPljSqkPsJY6xP`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const apiResponse = await fetch(apiEndpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await apiResponse.json();
|
||||||
|
console.log('Predictions:', result);
|
||||||
|
|
||||||
|
if (result.predictions) {
|
||||||
|
setShowModal(true);
|
||||||
|
setPredictions(result.predictions);
|
||||||
|
|
||||||
|
// 바운딩 박스와 라벨 표시
|
||||||
|
result.predictions.forEach((prediction) => {
|
||||||
|
const { x, y, width, height, class: label, confidence } = prediction;
|
||||||
|
|
||||||
|
// 바운딩 박스
|
||||||
|
ctx.strokeStyle = 'red';
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.strokeRect(x - 50, y - 80, width, height);
|
||||||
|
|
||||||
|
// 라벨
|
||||||
|
ctx.fillStyle = 'red';
|
||||||
|
ctx.font = '16px Arial';
|
||||||
|
ctx.fillText(`${label} (${(confidence * 100).toFixed(2)}%)`, x - 50, y - 80 > 10 ? y - 5 : 10);
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
setShowModal(false);
|
||||||
|
}, 1000);
|
||||||
|
setTimeout(() => {
|
||||||
|
setSearch(result.predictions[0].class);
|
||||||
|
}, 500);
|
||||||
|
setTimeout(() => {
|
||||||
|
onKeyDown
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error detecting objects:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// 파일 선택 시 호출되는 함수
|
// const handleSubmit = (event) => {
|
||||||
// const handleFileChange = (event) => {
|
// event.preventDefault();
|
||||||
// const file = event.target.files?.[0];
|
// if (fileInputRef.current && fileInputRef.current.files.length > 0) {
|
||||||
// if (file) {
|
// handleFileChange({ target: { files: fileInputRef.current.files } });
|
||||||
// console.log('Selected File:', file);
|
|
||||||
|
|
||||||
// // 예: 파일을 서버에 업로드하거나 처리
|
|
||||||
// const reader = new FileReader();
|
|
||||||
// reader.onload = () => {
|
|
||||||
// console.log('Image Preview URL:', reader.result);
|
|
||||||
// };
|
|
||||||
// reader.readAsDataURL(file);
|
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
|
|
||||||
const handleFileChange = async (event) => {
|
|
||||||
const file = event.target.files[0];
|
|
||||||
if (file) {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('name', file.name);
|
|
||||||
formData.append('file', file);
|
|
||||||
formData.append('split', 'train');
|
|
||||||
|
|
||||||
console.log(formData)
|
|
||||||
|
|
||||||
axios({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'https://api.roboflow.com/dataset/picup/upload',
|
|
||||||
params: {
|
|
||||||
api_key: 's9OJq0UPljSqkPsJY6xP'
|
|
||||||
},
|
|
||||||
data: formData,
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "multipart/form-data"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(function (response) {
|
|
||||||
console.log(response.data);
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
console.log(error.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
if (fileInputRef.current && fileInputRef.current.files.length > 0) {
|
|
||||||
handleFileChange({ target: { files: fileInputRef.current.files } });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TextField
|
<TextField
|
||||||
@ -208,17 +240,28 @@ export default function Search({ ...props }) {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<form style={{ display: 'flex' }} onSubmit={handleSubmit}>
|
<form
|
||||||
<Button variant="contained" sx={{ width: '80%', borderRadius: 0 }} onClick={handleImageSearch}>
|
style={{ display: 'flex' }}
|
||||||
|
onSubmit={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
detectWithRoboflow();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
sx={{ width: '80%', borderRadius: 0 }}
|
||||||
|
onClick={() => document.getElementById('fileInput').click()}
|
||||||
|
>
|
||||||
이미지 찾기
|
이미지 찾기
|
||||||
</Button>
|
</Button>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
capture="camera"
|
capture="camera"
|
||||||
|
id="fileInput"
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
onChange={handleFileChange}
|
|
||||||
style={{ display: 'none' }}
|
style={{ display: 'none' }}
|
||||||
|
onChange={handleFileChange}
|
||||||
/>
|
/>
|
||||||
<button type="submit" style={{ width: '20%', height: '40px', border: '0' }}>
|
<button type="submit" style={{ width: '20%', height: '40px', border: '0' }}>
|
||||||
검색
|
검색
|
||||||
@ -380,13 +423,13 @@ export default function Search({ ...props }) {
|
|||||||
{isLoading ? <Skeleton variant="text" width="200px" /> : product.category}
|
{isLoading ? <Skeleton variant="text" width="200px" /> : product.category}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<Typography variant="subtitle1" color="text.primary" noWrap>
|
{/* <Typography variant="subtitle1" color="text.primary" noWrap>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Skeleton variant="text" width="100px" />
|
<Skeleton variant="text" width="100px" />
|
||||||
) : (
|
) : (
|
||||||
fCurrency(cCurrency(product.priceSale))
|
fCurrency(cCurrency(product.priceSale))
|
||||||
)}
|
)}
|
||||||
</Typography>
|
</Typography> */}
|
||||||
</Stack>
|
</Stack>
|
||||||
</ListItemText>
|
</ListItemText>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -406,6 +449,27 @@ export default function Search({ ...props }) {
|
|||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
<Box
|
||||||
|
className={showModal === true ? 'active' : ''}
|
||||||
|
sx={{
|
||||||
|
height: '100vh',
|
||||||
|
width: '100vw',
|
||||||
|
position: 'fixed',
|
||||||
|
left: 0,
|
||||||
|
top: '-100vh',
|
||||||
|
backgroundColor: '#00000055',
|
||||||
|
zIndex: 1300,
|
||||||
|
transition: 'ease all 0.3s',
|
||||||
|
'&.active': {
|
||||||
|
top: 0,
|
||||||
|
transition: 'ease all 0.3s'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack sx={{ height: '100vh', width: '100vw', justifyContent: 'center', alignItems: 'center' }}>
|
||||||
|
<canvas ref={canvasRef} style={{ width: '90vw' }}></canvas>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user