업로드!

This commit is contained in:
익희 김 2025-01-20 04:08:17 +09:00
parent 4d92cc2b61
commit 2bf1c54e7a
2 changed files with 198 additions and 11 deletions

View File

@ -10,12 +10,13 @@ import Typography from '@mui/material/Typography';
import SearchIcon from '@mui/icons-material/Search';
import TextField from '@mui/material/TextField';
import Skeleton from '@mui/material/Skeleton';
import { InputAdornment, Stack, Button } from '@mui/material';
import { InputAdornment, Stack, Button, Modal, IconButton } from '@mui/material';
import MenuList from '@mui/material/MenuList';
import MenuItem from '@mui/material/MenuItem';
import ListItemIcon from '@mui/material/ListItemIcon';
import CircularProgress from '@mui/material/CircularProgress';
import Divider from '@mui/material/Divider';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
// components
import NoDataFound from 'src/illustrations/dataNotFound';
@ -28,6 +29,65 @@ import { useCurrencyFormatter } from 'src/hooks/formatCurrency';
// api
import * as api from 'src/services';
const axios = require('axios');
const getImageUrl = async (ids) => {
const requestOptions = {
method: 'GET',
redirect: 'follow'
};
try {
const responses = await Promise.all(
ids.map(async (id) => {
const response = await fetch(
`https://api.roboflow.com/picup/picup/images/${id}?api_key=s9OJq0UPljSqkPsJY6xP`,
requestOptions
);
if (!response.ok) {
throw new Error(`Error fetching image for ID: ${id}, Status: ${response.status}`);
}
return response.json(); // JSON
})
);
return responses; //
} catch (error) {
console.error('Error fetching image URLs:', error);
return null; // null
}
};
const searchImages = async (imageBase64) => {
const myHeaders = new Headers();
myHeaders.append('Content-Type', 'application/json');
const raw = JSON.stringify({
like_image: 'MV09CPgMSn9uhQ5D2nl5',
limit: 3,
in_dataset: true
});
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
try {
const response = await fetch(
'https://api.roboflow.com/picup/picup/search?api_key=s9OJq0UPljSqkPsJY6xP',
requestOptions
);
const result = await response.json();
return result; //
} catch (error) {
console.error('Error fetching images:', error);
throw error;
}
};
Search.propTypes = {
onClose: PropTypes.func.isRequired,
mobile: PropTypes.bool.isRequired
@ -56,6 +116,9 @@ export default function Search({ ...props }) {
const router = useRouter();
const [search, setSearch] = React.useState('');
const [image, setImage] = React.useState(null);
const [imagesResultID, setImagesResultID] = React.useState(null);
const [roboFlowUrlLists, setRoboFlowUrlLists] = React.useState([]);
const { data: filters, isLoading: filtersLoading } = useQuery(['get-search-filters'], () => api.getSearchFilters());
const { mutate, isLoading } = useMutation('search', api.search, {
@ -108,21 +171,48 @@ export default function Search({ ...props }) {
}
};
//
const handleFileChange = (event) => {
const handleFileChange = async (event) => {
const file = event.target.files?.[0];
if (file) {
console.log('Selected File:', file);
// :
const reader = new FileReader();
reader.onload = () => {
console.log('Image Preview URL:', reader.result);
reader.onloadend = async () => {
const base64Image = reader.result.split(',')[1]; // base64
setImage(reader.result);
};
reader.readAsDataURL(file);
}
};
const objectDetect = async (image) => {
try {
const result = await searchImages(image);
// id
const imageIds = result.results.map((r) => r.id);
//
setImagesResultID(imageIds);
console.log('Image IDs:', imageIds); //
} catch (error) {
console.error('Error in image search:', error);
}
};
React.useEffect(() => {
if (imagesResultID && imagesResultID.length > 0) {
getImageUrl(imagesResultID).then((url) => {
setRoboFlowUrlLists(url);
});
}
}, [imagesResultID]);
React.useEffect(() => {
if (roboFlowUrlLists) {
console.log(roboFlowUrlLists);
}
}, [roboFlowUrlLists]);
return (
<>
<TextField
@ -167,7 +257,9 @@ export default function Search({ ...props }) {
}
}}
/>
<Button variant='contained' sx={{ width: '100%', borderRadius: 0 }} onClick={handleImageSearch}>이미지 검색</Button>
<Button variant="contained" sx={{ width: '100%', borderRadius: 0 }} onClick={handleImageSearch}>
이미지 검색
</Button>
<input
type="file"
accept="image/*"
@ -332,13 +424,13 @@ export default function Search({ ...props }) {
{isLoading ? <Skeleton variant="text" width="200px" /> : product.category}
</Typography>
</div>
<Typography variant="subtitle1" color="text.primary" noWrap>
{/* <Typography variant="subtitle1" color="text.primary" noWrap>
{isLoading ? (
<Skeleton variant="text" width="100px" />
) : (
fCurrency(cCurrency(product.priceSale))
)}
</Typography>
</Typography> */}
</Stack>
</ListItemText>
</MenuItem>
@ -347,6 +439,63 @@ export default function Search({ ...props }) {
</>
)}
</Box>{' '}
{roboFlowUrlLists &&
roboFlowUrlLists.map((i, index) => (
<MenuList
key={`search-by-images-${i.image.annotation.key}-${index.toString()}`}
sx={{
pt: 0,
mt: 1,
overflow: 'auto',
px: 1,
li: {
borderRadius: '8px',
border: `1px solid transparent`,
'&:hover, &.Mui-focusVisible, &.Mui-selected ': {
border: (theme) => `1px solid ${theme.palette.primary.main}`,
bgcolor: (theme) => alpha(theme.palette.primary.main, 0.16),
h6: {
color: 'primary.main'
}
},
'&.active': {
border: (theme) => `1px solid ${theme.palette.primary.main}`,
bgcolor: (theme) => alpha(theme.palette.primary.main, 0.16),
h6: {
color: 'primary.main'
}
}
}
}}
autoFocusItem={!focus}
>
<MenuItem>
<ListItemIcon>
<img
alt="이미지"
src={i.image.urls.original}
style={{ width: '40px', height: '40px', borderRadius: '100%' }}
/>
</ListItemIcon>
<ListItemText>
<Stack direction="row" gap={1} alignItems={'center'} justifyContent={'space-between'}>
<div>
<Typography variant="subtitle1" color="text.primary" noWrap>
Object Data Set {index}
</Typography>
<Typography variant="body2" color="text.secondary" noWrap>
{i.image.tags.map((i) => {
return i;
})}
{` `}
<span>{i.image.r * 100}%</span>
</Typography>
</div>
</Stack>
</ListItemText>
</MenuItem>
</MenuList>
))}
{multiSelect && (
<Stack gap={1} direction={'row'} p={1} justifyContent={'end'}>
<Button variant="outlined" color="primary" onClick={() => handleSave(selectedProducts)}>
@ -358,6 +507,42 @@ export default function Search({ ...props }) {
</Stack>
)}
</Box>
{/* 이미지 미리보기 렌더링 */}
{image && (
<Modal
open={image}
sx={{ height: '100vh', width: '100vw', display: 'flex', justifyContent: 'center', alignItems: 'center' }}
>
<Box sx={{ position: 'relative' }}>
<Box mt={2} display="flex" justifyContent="center">
<IconButton
sx={{ position: 'absolute;', right: 0, top: 10, mixBlendMode: 'difference' }}
onClick={() => {
setImage(null);
}}
>
<CloseRoundedIcon fontSize="small" />
</IconButton>
<img
src={image}
style={{
maxWidth: '100%',
maxHeight: '300px',
borderRadius: '8px',
border: '1px solid #ddd'
}}
/>
<Button
sx={{ position: 'absolute', bottom: 0, left: '50%', transform: 'translate(-50%, 0px)' }}
onClick={() => objectDetect(image)}
>
이미지 상품 검색
</Button>
</Box>
</Box>
</Modal>
)}
</>
);
}

View File

@ -12,6 +12,8 @@ import { varFadeInRight } from '../animate';
// react dropzone
import { useDropzone } from 'react-dropzone';
const DropZoneStyle = styled('div')(({ theme }) => ({
outline: 'none',
display: 'flex',