-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApp.js
More file actions
194 lines (169 loc) · 5.26 KB
/
App.js
File metadata and controls
194 lines (169 loc) · 5.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/**
* An extremely silly React Native + Tensorflow App for identifying squirrels.
*/
import React, {Component} from 'react';
import { Platform, StyleSheet, Text, View, Image } from 'react-native';
import ImagePicker from 'react-native-image-picker';
import { TfImageRecognition } from 'react-native-tensorflow';
import Header from './src/components/Header';
import Button from './src/components/Button';
const GRAPH_FILE = './assets/retrained_graph.pb'
const LABEL_FILE = './assets/retrained_labels.txt'
const IMAGE_MEAN = 128 // settings from TF for Poets
const IMAGE_STD = 128 // // settings from TF for Poets
const SQ_ORANGE = '#FF8700';
const SQ_BLUE = '#00B6FF';
type Props = {};
export default class App extends Component<Props> {
constructor() {
super()
this.initImage = require('./assets/squirrel2.jpg');
this.goodCircle = require('./assets/circle_squirrel.png');
this.badCircle = require('./assets/circle_notsquirrel.png');
this.state = {photo: this.initImage,
result: "",
confidence: "",
topCircle: this.goodCircle,
topColor: SQ_BLUE};
// need to explicitly bind in order to be able to call this.setState inside askForPhoto
// otherwise, setState doesn't know what "this" is (JS way of handling static vs instance functions)
this.askForPhoto = this.askForPhoto.bind(this);
}
componentDidMount() {
this.recognizeImage();
}
askForPhoto() {
var RNFS = require('react-native-fs');
const imagePickerOptions = {
title: 'Select Photo',
customButtons: [],
storageOptions: {
cameraRoll: true,
waitUntilSaved: true,
path: 'images',
}
};
ImagePicker.showImagePicker(imagePickerOptions, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
console.log("response.uri is:" + response.uri);
RNFS.exists(response.uri)
.then( (exists) => {
if (exists) {
// Handle library picker
this.setState({photo: {uri: response.uri}}, ()=>{this.recognizeImage();});
} else {
// Handle photo taken from camera
RNFS.stat(response.uri).then((statResult) => {
// console.log("real path: " + statResult.originalFilepath)
var realPath = "file://" + statResult.originalFilepath
this.setState({photo: {uri: realPath}}, ()=>{this.recognizeImage();});
}).catch((err) => {console.log("RNFS.stat() caught exception: " + err)} );
}
}).catch((err) => {console.log("RNFS.exists() caught exception: " + err)} );
}
});
}
processResult(firstResult) {
if (firstResult == "squirrel") {
this.setState({
result: "SQUIRREL!",
topColor: SQ_ORANGE,
topCircle: this.goodCircle})
}
else {
this.setState({
result: "Not squirrel :(",
topColor: SQ_BLUE,
topCircle: this.badCircle})
}
}
async recognizeImage() {
try {
const tfImageRecognition = new TfImageRecognition({
model: require(GRAPH_FILE),
labels: require(LABEL_FILE),
imageMean: IMAGE_MEAN,
imageStd: IMAGE_STD
});
const results = await tfImageRecognition.recognize({
image: this.state.photo,
inputName: "input", //Optional, defaults to "input"
inputSize: 224, //Optional, defaults to 224
outputName: "final_result", //Optional, defaults to "output"
maxResults: 3, //Optional, defaults to 3
threshold: 0.1, //Optional, defaults to 0.1
})
this.processResult(results[0].name)
// const confidenceText = "Confidence: " + results[0].confidence
await tfImageRecognition.close()
} catch(err) {
alert(err)
}
}
render() {
return (
<View style={styles.container}>
<Header
headerText={this.state.result}
customHeaderColor={this.state.topColor}/>
<View style={styles.imageContainer}>
<Image source={this.state.photo}
style={styles.imageStyle}
resizeMode={'cover'} />
</View>
<View style={styles.buttonContainer}>
<Button
whenPressed={() => this.askForPhoto()}>
Take / Choose Photo
</Button>
</View>
<View style={styles.circleContainer}>
<Image source={this.state.topCircle} style={styles.topCircle} />
</View>
<Text style={styles.results}>{this.state.result}</Text>
<Text style={styles.results}>{this.state.confidence}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
},
topCircle: {
width: 80,
height: 80,
borderWidth: 2,
borderColor: '#FFFFFF',
borderRadius: 999,
},
circleContainer: {
top: 60, // todo: replace with calc based on screen size
left: 165, // todo: replace with calc based on screen size
position: 'absolute',
},
imageStyle: {
width: '100%',
height: '100%',
},
imageContainer: {
flex: 7,
},
buttonContainer: {
flex: 1,
alignContent: 'center',
backgroundColor: '#00B6FF',
},
results: {
display: 'none',
textAlign: 'center',
},
});