我试图使用React制作一个简单的图像上传器并将其与IBM Watson集成以进行面部检测,只需在图像的面上绘制一个正方形。
所以,这是我的Index.js。
import React from 'react';
import PropTypes from 'prop-types';
import './index.css';
import FlipMove from 'react-flip-move';
import UploadIcon from './UploadIcon.svg';
const VisualRecognitionV3 = require('watson-deve`enter code here`loper-cloud/visual-recognition/v3');
const visualRecognition = new VisualRecognitionV3({
version: '2018-03-19',
iam_apikey: '{j3YBm86Ep4cNupisk1a7xhcokOMpPO5LYHwdTJcjfw9k}'
});
const styles = {
display: "flex",
alignItems: "center",
justifyContent: "center",
flexWrap: "wrap",
width: "100%"
};
class ReactImageUploadComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
pictures: [],
files: [],
notAcceptedFileType: [],
notAcceptedFileSize: []
};
this.inputElement = '';
this.onDropFile = this.onDropFile.bi`enter code here`nd(this);
this.triggerFileUpload = this.triggerFileUpload.bind(this);
}
/*
On button click, trigger input file to open
*/
triggerFileUpload() {
this.inputElement.click();
}
/*
Handle file validation
*/
onDropFile(e, pictureFiles, pictureDataURLs) {
const files = e.target.files;
const _this = this;
visualRecognition.detectFaces({image_file: pictureFiles[0]}, function(err, response){
if (err){
console.log(err);
} else {
console.log(JSON.stringify(response, null, 2));
}
});
// Iterate over all uploaded files
for (let i = 0; i < files.length; i++) {
let f = files[i];
// Check for file extension
if (!this.hasExtension(f.name)) {
const newArray = _this.state.notAcceptedFileType.slice();
newArray.push(f.name);
_this.setState({notAcceptedFileType: newArray});
continue;
}
// Check for file size
if(f.size > this.props.maxFileSize) {
const newArray = _this.state.notAcceptedFileSize.slice();
newArray.push(f.name);
_this.setState({notAcceptedFileSize: newArray});
continue;
}
const reader = new FileReader();
// Read the image via FileReader API and save image result in state.
reader.onload = (function () {
return function (e) {
// Add the file name to the data URL
let dataURL = e.target.result;
dataURL = dataURL.replace(";base64", `;name=${f.name};base64`);
if (_this.props.singleImage === true) {
_this.setState({pictures: [dataURL], files: [f]}, () => {
_this.props.onChange(_this.state.files, _this.state.pictures);
});
} else if (_this.state.pictures.indexOf(dataURL) === -1) {
const newArray = _this.state.pictures.slice();
newArray.push(dataURL);
const newFiles = _this.state.files.slice();
newFiles.push(f);
_this.setState({pictures: newArray, files: newFiles}, () => {
_this.props.onChange(_this.state.files, _this.state.pictures);
});
}
};
})(f);
reader.readAsDataURL(f);
}
}
/*
Render the upload icon
*/
renderIcon() {
if (this.props.withIcon) {
return <img src={UploadIcon} className="uploadIcon" alt="Upload Icon" />;
}
}
/*
Render label
*/
renderLabel() {
if (this.props.withLabel) {
return <p className={this.props.labelClass} style={this.props.labelStyles}>{this.props.label}</p>
}
}
/*
Check file extension (onDropFile)
*/
hasExtension(fileName) {
const pattern = '(' + this.props.imgExtension.join('|').replace(/\./g, '\\.') + ')$';
return new RegExp(pattern, 'i').test(fileName);
}
/*
Remove the image from state
*/
removeImage(picture) {
const removeIndex = this.state.pictures.findIndex(e => e === picture);
const filteredPictures = this.state.pictures.filter((e, index) => index !== removeIndex);
const filteredFiles = this.state.files.filter((e, index) => index !== removeIndex);
this.setState({pictures: filteredPictures, files: filteredFiles}, () => {
this.props.onChange(this.state.files, this.state.pictures);
});
}
/*
Check if any errors && render
*/
renderErrors() {
let notAccepted = '';
if (this.state.notAcceptedFileType.length > 0) {
notAccepted = this.state.notAcceptedFileType.map((error, index) => {
return (
<div className={'errorMessage ' + this.props.errorClass} key={index} style={this.props.errorStyle}>
* {error} {this.props.fileTypeError}
</div>
)
});
}
if (this.state.notAcceptedFileSize.length > 0) {
notAccepted = this.state.notAcceptedFileSize.map((error, index) => {
return (
<div className={'errorMessage ' + this.props.errorClass} key={index} style={this.props.errorStyle}>
* {error} {this.props.fileSizeError}
</div>
)
});
}
return notAccepted;
}
/*
Render preview images
*/
renderPreview() {
return (
<div className="uploadPicturesWrapper">
<FlipMove enterAnimation="fade" leaveAnimation="fade" style={styles}>
{this.renderPreviewPictures()}
</FlipMove>
</div>
);
}
renderPreviewPictures() {
return this.state.pictures.map((picture, index) => {
return (
<div key={index} className="uploadPictureContainer">
<div className="deleteImage" onClick={() => this.removeImage(picture)}>X</div>
<img src={picture} className="uploadPicture" alt="preview"/>
</div>
);
});
}
render() {
return (
<div className={"fileUploader " + this.props.className} style={this.props.style}>
<div className="fileContainer">
{this.renderIcon()}
{this.renderLabel()}
<div className="errorsContainer">
{this.renderErrors()}
</div>
<button
type={this.props.buttonType}
className={"chooseFileButton " + this.props.buttonClassName}
style={this.props.buttonStyles}
onClick={this.triggerFileUpload}
>
{this.props.buttonText}
</button>
<input
type="file"
ref={input => this.inputElement = input}
name={this.props.name}
multiple="multiple"
onChange={this.onDropFile}
accept={this.props.accept}
/>
{ this.props.withPreview ? this.renderPreview() : null }
</div>
</div>
)
}
}
ReactImageUploadComponent.defaultProps = {
className: '',
buttonClassName: "",
buttonStyles: {},
withPreview: false,
accept: "image/*",
name: "",
withIcon: true,
buttonText: "Escolher Imagem",
buttonType: "submit",
withLabel: true,
label: "Tamanho máximo de arquivo: 5mb, formatos aceitos: jpg,gif,png",
labelStyles: {},
labelClass: "",
imgExtension: ['.jpg', '.gif', '.png'],
maxFileSize: 5242880,
fileSizeError: " arquivo muito grande",
fileTypeError: " extenção de arquivo não suportada",
errorClass: "",
style: {},
errorStyle: {},
singleImage: false,
onChange: () => {}
};
ReactImageUploadComponent.propTypes = {
style: PropTypes.object,
className: PropTypes.string,
onChange: PropTypes.func,
onDelete: PropTypes.func,
buttonClassName: PropTypes.string,
buttonStyles: PropTypes.object,
buttonType: PropTypes.string,
withPreview: PropTypes.bool,
accept: PropTypes.string,
name: PropTypes.string,
withIcon: PropTypes.bool,
buttonText: PropTypes.string,
withLabel: PropTypes.bool,
label: PropTypes.string,
labelStyles: PropTypes.object,
labelClass: PropTypes.string,
imgExtension: PropTypes.array,
maxFileSize: PropTypes.number,
fileSizeError: PropTypes.string,
fileTypeError: PropTypes.string,
errorClass: PropTypes.string,
errorStyle: PropTypes.object,
singleImage: PropTypes.bool
};
export default ReactImageUploadComponent;
&#13;
我已经尝试过一些来自网络的教程和示例,但没有成功。 问题是,我如何应用Watson在上传图像的表面周围画一个正方形?
答案 0 :(得分:0)
1)我不知道你试图用const steps
做什么,但它没有任何意义。您的React应用程序中不需要npm install
命令。我也没有看到在字符串中包含一堆JavaScript的任何目的。
2)在您使用App
组件底部的实际ImageUploader
课程内部,您没有按照上面steps
的建议进行操作,并且包括onChange
方法。从我在ImageUploader
组件文档中可以看到的内容,就是您在用户上传图像后用于执行某个操作的内容。
3)您尚未尝试将IBM Watson API实际集成到此代码中。显然,这将是实现既定目标的关键一步。在发布问题之前,你应该自己做一个真诚的尝试。
无论如何,您需要做的基本想法是,在用户上传图片后,您向Watson的图片识别API发出API请求:https://www.ibm.com/watson/developercloud/visual-recognition/api/v3/node.html?node#detect-faces
您需要与他们建立一个帐户并获取开发人员密钥(对于极少数的请求,它应该是免费的)。然后,您将要使用npm install --save watson-developer-cloud
安装他们的API(注意:正如我上面提到的,这不属于您的代码,就像您现在所拥有的;这意味着要从您的终端/ shell运行项目目录。
在文件的顶部,您将包含SDK的require
语句:
const VisualRecognitionV3 = require('watson-developer-cloud/visual-recognition/v3');
使用您的API密钥创建SDK的实例:
const visualRecognition = new VisualRecognitionV3({
version: '2018-03-19',
iam_apikey: '{iam_api_key}'
});
最后,一旦用户上传图像,您可以使用图像文件作为参数调用相应的函数:
visualRecognition.detectFaces({image_file: file}, function(err, response) {
if (err)
console.log(err);
else
console.log(JSON.stringify(response, null, 2))
});
将所有内容放在一起,您的应用可能看起来像这样:
import React from 'react';
import ImageUploader from 'react-images-upload';
const VisualRecognitionV3 = require('watson-developer-cloud/visual-recognition/v3');
const visualRecognition = new VisualRecognitionV3({
version: '2018-03-19',
iam_apikey: '{iam_api_key}'
});
class App extends React.Component {
constructor(props) {
super(props);
this.onDrop = this.onDrop.bind(this);
}
onDrop(pictureFiles, pictureDataURLs) {
visualRecognition.detectFaces({image_file: pictureFiles[0]}, function(err, response) {
if (err) {
console.log(err);
} else
console.log(JSON.stringify(response, null, 2));
}
});
}
render() {
return (
<ImageUploader
withIcon={true}
buttonText='Escolher Imagens'
onChange={this.onDrop}
imgExtension={['.jpg', '.gif', '.png', '.gif']}
maxFileSize={5242880}
/>
);
}
}
我没有测试过这段代码,所以IBM Watson SDK可能会遇到pictureFile [0]格式的问题(而且我也不确定pictureFiles是否是一个数组,但是你应该很容易检查一下React- Images-Uploader组件,以查看是什么数据结构)。但是,无论如何,这是基本的想法。
顺便说一句,此代码的输出将在JavaScript开发人员控制台中,它将打印出图像中面部周围方形的尺寸和坐标,但此代码不会绘制它为了你。这是另一项任务,有很多方法可以做,你可以在别处问。但是在这里你将获得面部的坐标,形状和大小,然后它们只需要绘制。