响应上传图片并设置新的 ref
2020-10-10
834
我想上传一张图片,显示预览,并将其用于 mobilenet 机器学习模型中,据我了解,这需要我将它作为参考。因此,我希望:
- 上传图片
- 设置引用
- 使用该引用作为预览
- 在 ML 模型中使用该引用
我可以像这样上传图片(没有问题):
const UploadButton = ({ handleNewFile, text }) => (
<label htmlFor='upload-file'>
<input style={{ display: 'none' }} id='upload-file' name='upload-file' type='file' accept='image/*' onChange={handleNewFile} />
<Fab variant='extended' color='primary' style={{ marginBottom: '.5rem' }} component='span'>
<UploadIcon />
{text}
</Fab>
</label>
)
我的句柄更改:
const handleNewFile = e => {
const [file] = e.target.files
console.log('file', file)
// this settting fileRef.current doesn't work, it's not the element like I need
fileRef.current = file
// mobile net model
model.classify(fileRef.current).then(pred => {
setPrediction(pred[0].className)
})
}
我最初为图片设置了 src,但没有上传功能,并且没有问题,但现在我需要允许用户上传,我不知道如何在上传后正确设置此引用。
<img ref={fileRef} />
如何在上传后设置引用?
1个回答
答案: 不要使用 refs,你不需要
我在下面粘贴了整个代码,但总而言之,使用
new FileReader()
和
new Image()
并从
img.onLoad
函数中的
this
对象中访问它。
import React, { useState, useEffect } from 'react'
import { Grid, Typography, Fab } from '@material-ui/core'
import { Loading } from 'Components/QueryHandling'
import UploadIcon from '@material-ui/icons/Publish'
const UploadButton = ({ handleNewFile, text }) => (
<label htmlFor='upload-file'>
<input style={{ display: 'none' }} id='upload-file' name='upload-file' type='file' accept='image/*' onChange={handleNewFile} />
<Fab variant='extended' color='primary' style={{ margin: '1em' }} component='span'>
<UploadIcon />
{text}
</Fab>
</label>
)
const ImageThumb = ({ image }) => {
return <img src={URL.createObjectURL(image)} alt={image.name} style={{ margin: '2rem', maxHeight: 300 }} />
}
const Prediction = ({ className, probability }) => (
<Typography variant='body1'>
{className} ({Math.round(probability * 100)}%){' '}
</Typography>
)
export default function Predictor({ content }) {
const [model, setModel] = useState(null)
const [img, setImg] = useState(null)
const [modelLoaded, setModelLoaded] = useState(false)
const [predictions, setPredictions] = useState(null)
const headerText = modelLoaded ? (Array.isArray(predictions) ? 'Results' : 'Upload Image') : 'Loading Model'
const uploadText = Array.isArray(predictions) ? 'Upload New Image' : 'Upload Image'
useEffect(() => {
const loadMobileNet = async () => {
if (window.mobilenet) {
const net = await window.mobilenet.load()
setModel(net)
setModelLoaded(true)
} else {
setTimeout(loadMobileNet(), 1000)
}
}
loadMobileNet()
}, [])
const classifyImage = async file => {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = function(e) {
const img = new Image()
img.src = e.target.result
img.onload = function() {
const w = this.width
const h = this.height
model.classify(this).then(preds => {
setPredictions(preds)
})
// optionally resolve height and width
resolve([h, w])
}
}
reader.readAsDataURL(file)
})
}
const handleNewFile = e => {
const [file] = e.target.files
setImg(file)
classifyImage(file)
}
return (
<Grid>
<Typography variant='h3' align='center'>
{headerText}
</Typography>
{img && <ImageThumb image={img} />}
{Array.isArray(predictions) && predictions.map((p, i) => <Prediction key={i} {...p} />)}
{modelLoaded ? <UploadButton handleNewFile={handleNewFile} text={uploadText} /> : <Loading />}
</Grid>
)
}
Kevin Danikowski
2020-10-12