Commit 06d5045c authored by Samarakoon S.M.A.D IT20233808's avatar Samarakoon S.M.A.D IT20233808

Merge branch 'feature/IT20233808/soilBasedCropRecommendation' into 'master'

pest detection component added

See merge request !15
parents 511a4013 ce348831
......@@ -15,7 +15,12 @@ import AgriExpertSolution from './components/agriExpertComponent/AgriExpertSolut
import NutrientSlider from './components/agriExpertComponent/NutrientSelect';
import CustomCrop from './components/recomendationComponentsBySoil/CustomCrop';
import CustomCropSelect from './components/recomendationComponentsBySoil/CustomCropSelect';
import PestDetectOptions from './components/Pest_management/PestDetectOptions';
import uploadPhotoDetect from './components/Pest_management/uploadPhotoDetect';
import DetectByVideo from './components/Pest_management/DetectByVideo'
import AgriExpert from './components/Pest_management/AgriExpert'
import PestControlInfo from './components/Pest_management/PestControlInfo';
import GetInstructions from './components/Pest_management/GetInstructionsl';
export default function App() {
const Stack = createNativeStackNavigator();
......@@ -36,6 +41,12 @@ export default function App() {
<Stack.Screen name='Agri Expert' component={AgriExpertSolution} />
<Stack.Screen name='Test Custom Crop' component={CustomCrop} />
<Stack.Screen name='Custom Crop Select' component={CustomCropSelect} />
<Stack.Screen name="PestDetectOptions" component={PestDetectOptions}/>
<Stack.Screen name="UploadImage" component={uploadPhotoDetect}/>
<Stack.Screen name="CaptureImage" component={DetectByVideo}/>
<Stack.Screen name="AgriExpert" component={AgriExpert}/>
<Stack.Screen name="PestInfo" component={PestControlInfo}/>
<Stack.Screen name="GetInstructions" component={GetInstructions}/>
</Stack.Navigator>
</NavigationContainer>
......
import React from 'react';
import { ViroARScene, ViroARImageMarker, ViroText } from 'react-viro';
const ARScene = () => {
return (
<ViroARScene>
<ViroARImageMarker target="assets\220px-Weisse-Fliege.jpg">
<ViroText
text="Recognized Image!"
position={[0, 0, -1]}
style={{ fontSize: 0.2, color: '#FFFF00' }}
/>
</ViroARImageMarker>
</ViroARScene>
);
};
export default ARScene;
import React, { useState } from "react";
import { View, Text, TextInput, Button, StyleSheet, Image } from "react-native";
import RNPickerSelect from "react-native-picker-select";
export default function AgriExpert() {
const [method, setMethod] = React.useState("");
const [name, setName] = React.useState("");
const [selectedWeather, setSelectedWeather] = useState([]);
const [selectedDuration, setSelectedDuration] = useState([]);
const [selectedDamage, setSelectedDamage] = useState([]);
const handleWeather = (itemValue) => {
setSelectedWeather(itemValue);
};
const handleDamage = (itemValue) => {
setSelectedDamage(itemValue);
};
const handleDuration = (itemValue) => {
setSelectedDuration(itemValue);
};
const handleSubmit = async () => {
try {
const requestBody = {
method,
name,
weather: selectedWeather.split(',').map((w) => w.trim()),
duration: selectedDuration.split(',').map((d) => d.trim()),
damage: selectedDamage.split(',').map((d) => d.trim()),
};
const apiResponse = await fetch('http://192.168.152.59:5000/add_data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody),
}).then(response => response.json)
.then((data)=>{
console.log("Successfuly added")
})
} catch (error) {
console.log('Error:', error);
}
}
return (
<View style={styles.container}>
<Image
source={require("../../assets/backgroundSoilData.jpg")}
style={styles.backgroundImage}
/>
<View style={styles.buttonContainer}>
<Text style={styles.title}>Add Methods</Text>
<Text style={styles.label}>Pest name: </Text>
<TextInput
style={styles.input}
onChangeText={setName}
value={name}
/>
<Text style={styles.label}>Control method: </Text>
<TextInput
style={styles.input}
onChangeText={setMethod}
value={method}
/>
<Text style={styles.label}>Weather: </Text>
<RNPickerSelect
onValueChange={handleWeather}
items={[
{ label: "Sunny", value: "sunny" },
{ label: "Rainy", value: "rainy" },
{ label: "Foggy", value: "foggy" },
]}
placeholder={{
label: "Select options...",
value: null,
}}
value={selectedWeather}
multiple
/>
<Text style={styles.label}>Duration: </Text>
<RNPickerSelect
onValueChange={handleDuration}
items={[
{ label: "Short", value: "short" },
{ label: "Mid", value: "mid" },
{ label: "Long", value: "long" },
]}
placeholder={{
label: "Select options...",
value: null,
}}
value={selectedDuration}
multiple
/>
<Text style={styles.label}>Damage: </Text>
<RNPickerSelect
onValueChange={handleDamage}
items={[
{ label: "Low", value: "low" },
{ label: "Average", value: "average" },
{ label: "High", value: "high" },
]}
placeholder={{
label: "Select options...",
value: null,
}}
value={selectedDamage}
multiple
/>
<Button title="Submit" onPress={handleSubmit} />
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
scrollContainer: {
flexGrow: 1,
justifyContent: "center",
alignItems: "center",
},
backgroundImage: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
},
title: {
fontSize: 24,
fontWeight: "bold",
marginBottom: 50,
},
label: {
fontSize: 18,
fontWeight: "bold",
marginBottom: 0,
textAlign: "left", // Align the text to the left
},
input: {
height: 40,
width: 250,
margin: 12,
borderWidth: 1,
padding: 10,
},
buttonContainer: {
backgroundColor: "rgba(255, 255, 255, 0.8)",
borderRadius: 10,
padding: 20,
justifyContent: "space-between",
alignItems: "center",
width: "80%",
maxWidth: 400,
},
});
import React, { useEffect, useRef, useState } from "react";
import {
View,
Button,
StyleSheet,
Text,
Image,
ActivityIndicator,
} from "react-native";
import { Camera } from "expo-camera";
import firebase from "firebase/compat/app";
import "firebase/compat/storage";
import pestData from './PestData.json';
const firebaseConfig = {
// Add your Firebase configuration here
apiKey: "AIzaSyBX0highSIXvOLxH9Z20CQRyXrGYZj-GfY",
authDomain: "pest-detection-d63bd.firebaseapp.com",
projectId: "pest-detection-d63bd",
storageBucket: "pest-detection-d63bd.appspot.com",
messagingSenderId: "1096191342865",
appId: "1:1096191342865:web:4b2c237166dd4b2d4e34b0",
measurementId: "G-2ZH7JPF0DE",
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
function CameraComponent() {
const cameraRef = useRef(null);
const [icon, setIcon] = useState("");
const [detections, setDetections] = useState([]);
const [selectedImage, setSelectedImage] = useState(null);
const [captured, setCaptured] = useState(false);
const [upload, setUpload] = useState(false);
const [pestName, setPestName] = useState("");
const [pestImage, setPestImage] = useState("");
const [pestMethods, setPestMethods] = useState([]);
const [details, setDetails] = useState(false);
useEffect(() => {
(async () => {
const { status } = await Camera.requestCameraPermissionsAsync();
if (status !== "granted") {
console.error("Camera permission denied");
}
})();
}, []);
const captureImage = async () => {
if (cameraRef.current) {
try {
const photo = await cameraRef.current.takePictureAsync();
setSelectedImage(photo.uri);
setCaptured(true);
} catch (error) {
console.error("Error capturing photo:", error);
}
}
};
const uploadImage = async () => {
if (selectedImage) {
const response = await fetch(selectedImage);
const blob = await response.blob();
const storageRef = firebase.storage().ref();
const imageRef = storageRef.child("images/" + new Date().getTime());
try {
setUpload(true)
await imageRef.put(blob);
const downloadURL = await imageRef.getDownloadURL();
console.log("Firebase Image URL:", downloadURL);
const apiResponse = await fetch("http://192.168.152.59:5000/link", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ image_url: downloadURL }),
});
if (apiResponse.ok) {
const data = await apiResponse.json();
setIcon(`data:image/png;base64,${data.annotated_image}`);
setUpload(false)
setDetections(data.detections);
} else {
console.log("API Error:", apiResponse.status);
}
} catch (error) {
console.log("Error:", error);
}
}
};
function getPestData(pestName) {
if (pestName === 'Mealy Bug') {
setPestName(pestData.pests[0].name);
setPestImage(pestData.pests[0].image);
setPestMethods(pestData.pests[0].methods);
} else if (pestName === 'whitefly') {
setPestName(pestData.pests[1].name);
setPestImage(pestData.pests[1].image);
setPestMethods(pestData.pests[1].methods);
} else if (pestName === 'Ash weevil') {
setPestName(pestData.pests[2].name);
setPestImage(pestData.pests[2].image);
setPestMethods(pestData.pests[2].methods);
} else if (pestName === 'Fruit fly') {
setPestName(pestData.pests[3].name);
setPestImage(pestData.pests[3].image);
setPestMethods(pestData.pests[3].methods);
} else if (pestName === 'Uroleucon compositae') {
setPestName(pestData.pests[4].name);
setPestImage(pestData.pests[4].image);
setPestMethods(pestData.pests[4].methods);
}
setDetails(true);
}
return (
<View style={styles.container}>
<Image source={require('../../assets/backgroundSoilData.jpg')} style={styles.backgroundImage} />
{!details && !icon && !captured && (
<Camera style={styles.camera} ref={cameraRef}>
<Text>Itentified pests and confidence</Text>
</Camera>
)}
{!details && captured && icon == "" && (
<Image
style={{ width: 400, height: 300 }}
source={{ uri: selectedImage }}
/>
)}
{icon && !details &&(
<View style={styles.resultContainer}>
<Image style={styles.resultImage} source={{ uri: icon }} />
<Text style={styles.resultText}>Identified pests and confidence</Text>
{detections.map((item, index) => (
<View key={index} style={styles.detectionItem}>
<Text style={styles.detectionText}>
{index + 1}. {item.class_name} (confidence: {item.confidence})
</Text>
<Button title="View More" onPress={() => getPestData(item.class_name)} />
</View>
))}
<Text style={styles.resultText}>No of objects detected: {detections.length}</Text>
</View>
)}
{!captured && !details && (
<Button
style={styles.button}
title="Capture Photo"
onPress={captureImage}
/>
)}
{captured && !icon && !details && (
<Button
style={styles.button}
title="Upload image"
onPress={uploadImage}
></Button>
)}
{upload && !details && (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#007AFF" />
<Text style={styles.loadingText}>Analyzing...</Text>
</View>
)}
{details && (
<View style={styles.detailsContainer}>
<Text style={styles.title}>Pest Details</Text>
<Text style={styles.label}>Name:</Text>
<Text style={styles.text}>{pestName}</Text>
<Image source={{ uri: pestImage }} style={styles.image} />
<Text style={styles.label}>Control Methods:</Text>
<View style={styles.methodList}>
{pestMethods.map((method, index) => (
<View key={index} style={styles.methodItem}>
<Text style={styles.bulletPoint}></Text>
<Text style={styles.methodText}>{method}</Text>
</View>
))}
</View>
<Button title="Go Back" onPress={() => setDetails(false)} />
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
camera: {
width: 400,
height: 600,
},
backgroundImage: {
flex: 1,
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
opacity: 0.8,
},
buttonContainer: {
backgroundColor: "rgba(255, 255, 255, 0.8)",
borderRadius: 10,
padding: 20,
justifyContent: "space-between",
alignItems: "center",
width: "80%",
maxWidth: 600,
},
button: {
backgroundColor: "#3498db",
borderRadius: 5,
paddingVertical: 10,
paddingHorizontal: 20,
marginBottom: 20,
width: 250,
alignItems: "center",
marginVertical: 20,
},
buttonText: {
color: "black",
fontSize: 16,
fontWeight: "bold",
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
scrollContainer: {
flexGrow: 1,
justifyContent: 'center',
alignItems: 'center',
},
backgroundImage: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 16,
},
image: {
width: 300,
height: 300,
marginVertical: 10,
},
resultContainer: {
width: '100%',
maxWidth: 500,
padding: 0,
borderRadius: 10,
backgroundColor: 'rgba(255, 255, 255, 0.8)',
margin: 0,
alignItems: 'center',
},
resultImage: {
width: 400,
height: 300,
},
resultText: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 8,
},
detectionItem: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 8,
},
detectionText: {
flex: 1,
fontSize: 16,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
loadingText: {
fontSize: 18,
marginTop: 10,
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
marginVertical: 10,
},
button: {
backgroundColor: '#3498db',
borderRadius: 5,
padding: 10,
width: 150,
alignItems: 'center',
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
detailsContainer: {
width: '100%',
maxWidth: 400,
padding: 0,
borderRadius: 10,
backgroundColor: 'rgba(255, 255, 255, 0.8)',
margin: 0,
alignItems: 'center',
},
label: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 8,
},
text: {
fontSize: 16,
marginBottom: 8,
},
methodList: {
width: '100%',
},
methodItem: {
flexDirection: 'row',
alignItems: 'flex-start',
marginBottom: 8,
},
bulletPoint: {
fontSize: 16,
fontWeight: 'bold',
marginRight: 8,
},
methodText: {
fontSize: 16,
},
});
export default CameraComponent;
import React, { useState } from "react";
import { View, Text, TextInput, Button, StyleSheet, Image } from "react-native";
import RNPickerSelect from "react-native-picker-select";
import pestData from './PestData.json';
export default function GetInstructions() {
const [recomdations, setRecomdations] = React.useState([]);
const [value, setValue] = React.useState(false);
const [name, setName] = React.useState("");
const [selectedWeather, setSelectedWeather] = useState([]);
const [selectedDuration, setSelectedDuration] = useState([]);
const [selectedDamage, setSelectedDamage] = useState([]);
const [pestImage, setPestImage] = useState("");
const [pestName, setPestName] = useState("");
const handleWeather = (itemValue) => {
setSelectedWeather(itemValue);
};
const handleDamage = (itemValue) => {
setSelectedDamage(itemValue);
};
const handleDuration = (itemValue) => {
setSelectedDuration(itemValue);
};
function getPestData(pestName) {
if (pestName === 'mealybug') {
setPestName(pestData.pests[0].name);
setPestImage(pestData.pests[0].image);
} else if (pestName === 'whitefly') {
setPestName(pestData.pests[1].name);
setPestImage(pestData.pests[1].image);
} else if (pestName === 'Ash weevil') {
setPestName(pestData.pests[2].name);
setPestImage(pestData.pests[2].image);
} else if (pestName === 'Fruit fly') {
setPestName(pestData.pests[3].name);
setPestImage(pestData.pests[3].image);
} else if (pestName === 'Uroleucon compositae') {
setPestName(pestData.pests[4].name);
setPestImage(pestData.pests[4].image);
}
}
const handleSubmit = async () => {
try {
const requestBody = {
"name": name,
"weather":selectedWeather,
"duration":selectedDuration,
"damage":selectedDamage,
};
const apiResponse = await fetch('http://192.168.152.59:5000/recommendations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody),
})
console.log(requestBody)
if (apiResponse.ok) {
getPestData(name)
const responseData = await apiResponse.json(); // Parse response as JSON
console.log('Response Data:', responseData["Recommended Methods"]);
setRecomdations(responseData["Recommended Methods"])
setValue(true)
} else {
console.error('API request failed:', apiResponse.status);
}
} catch (error) {
console.log('Error:', error);
}
}
return (
<View style={styles.container}>
<Image
source={require("../../assets/backgroundSoilData.jpg")}
style={styles.backgroundImage}
/>
{!value && (
<View style={styles.buttonContainer}>
<Text style={styles.title}>Get Instructions</Text>
<Text style={styles.label}>Pest name: </Text>
<TextInput
style={styles.input}
onChangeText={setName}
value={name}
/>
<Text style={styles.label}>Weather: </Text>
<RNPickerSelect
onValueChange={handleWeather}
items={[
{ label: "Sunny", value: "sunny" },
{ label: "Rainy", value: "rainy" },
{ label: "Foggy", value: "foggy" },
]}
placeholder={{
label: "Select options...",
value: null,
}}
value={selectedWeather}
multiple
/>
<Text style={styles.label}>Duration: </Text>
<RNPickerSelect
onValueChange={handleDuration}
items={[
{ label: "Short", value: "short" },
{ label: "Mid", value: "mid" },
{ label: "Long", value: "long" },
]}
placeholder={{
label: "Select options...",
value: null,
}}
value={selectedDuration}
multiple
/>
<Text style={styles.label}>Damage: </Text>
<RNPickerSelect
onValueChange={handleDamage}
items={[
{ label: "Low", value: "low" },
{ label: "Average", value: "average" },
{ label: "High", value: "high" },
]}
placeholder={{
label: "Select options...",
value: null,
}}
value={selectedDamage}
multiple
/>
<Button title="Submit" onPress={handleSubmit} />
</View>
)}
{value && (
<View style={styles.detailsContainer}>
<Text style={styles.title}>Pest Instructions</Text>
<Text style={styles.label}>Name:</Text>
<Text style={styles.text}>{pestName}</Text>
<Image source={{ uri: pestImage }} style={styles.image} />
<Text style={styles.label}>Control Methods:</Text>
<View style={styles.methodList}>
{recomdations.map((method, index) => (
<View key={index} style={styles.methodItem}>
<Text style={styles.bulletPoint}></Text>
<Text style={styles.methodText}>{method}</Text>
</View>
))}
</View>
<Button title="Go Back" onPress={() => setValue(false)} />
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
scrollContainer: {
flexGrow: 1,
justifyContent: "center",
alignItems: "center",
},
backgroundImage: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
},
title: {
fontSize: 24,
fontWeight: "bold",
marginBottom: 50,
},
label: {
fontSize: 18,
fontWeight: "bold",
marginBottom: 0,
textAlign: "left",
},
input: {
height: 40,
width: 250,
margin: 12,
borderWidth: 1,
padding: 10,
},
buttonContainer: {
backgroundColor: "rgba(255, 255, 255, 0.8)",
borderRadius: 10,
padding: 20,
justifyContent: "space-between",
alignItems: "center",
width: "80%",
maxWidth: 400, // Align the text to the left
},
methodList: {
width: '100%',
},
methodItem: {
flexDirection: 'row',
alignItems: 'flex-start',
marginBottom: 8,
},
bulletPoint: {
fontSize: 16,
fontWeight: 'bold',
marginRight: 8,
},
methodText: {
fontSize: 16,
},
image: {
width: 300,
height: 300,
marginVertical: 10,
},
detailsContainer: {
width: '100%',
maxWidth: 400,
padding: 0,
borderRadius: 10,
backgroundColor: 'rgba(255, 255, 255, 0.8)',
margin: 0,
alignItems: 'center',
},
});
import React, { useState } from 'react';
import { View, Text,Image, ScrollView, StyleSheet } from 'react-native';
import pestData from './PestData.json'
function PestControlInfo({ pestName }) {
const [pestInfo, setPestInfo] = useState(null);
const pest = pestData.pests.find((p) => p.name.toLowerCase() === pestName.toLowerCase());
setPestInfo(pest);
console.log(pest)
return (
<ScrollView>
<View style={styles.container}>
{/* <View>
<Text style={styles.heading}>Name: {pestInfo.name}</Text>
<Image style={styles.image} source={{ uri: pestInfo.image }} />
<Text style={styles.heading}>Control Methods:</Text>
<ul>
{pestInfo.methods.map((method, index) => (
<Text key={index} style={styles.method}>
- {method}
</Text>
))}
</ul>
</View> */}
</View>
</ScrollView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
padding: 20,
},
input: {
borderWidth: 1,
borderColor: '#ccc',
padding: 10,
width: '80%',
marginBottom: 10,
},
heading: {
fontSize: 18,
fontWeight: 'bold',
marginTop: 10,
},
image: {
width: 200,
height: 150,
resizeMode: 'cover',
marginVertical: 10,
},
method: {
marginLeft: 20,
marginBottom: 5,
},
});
export default PestControlInfo;
import {React,useState} from 'react';
import { View, TouchableOpacity, Text, StyleSheet, Image } from 'react-native';
const PestDetectOptions = ({navigation}) => {
return (
<View style={styles.container}>
<Image source={require('../../assets/backgroundSoilData.jpg')} style={styles.backgroundImage} />
<View style={styles.buttonContainer}>
<TouchableOpacity style={styles.button} onPress={() => {navigation.navigate("UploadImage")}}>
<Text style={styles.buttonText}>Upload Image</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => {navigation.navigate("CaptureImage")}}>
<Text style={styles.buttonText}>Capture Image</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => {navigation.navigate("GetInstructions")}}>
<Text style={styles.buttonText}>Get Instructions</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => {navigation.navigate("AgriExpert")}}>
<Text style={styles.buttonText}>AgriExpert</Text>
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
backgroundImage: {
flex: 1,
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
opacity: 0.8,
},
buttonContainer: {
backgroundColor: 'rgba(255, 255, 255, 0.8)',
borderRadius: 10,
padding: 20,
justifyContent: 'space-between',
alignItems: 'center',
width: '80%',
maxWidth: 400,
},
button: {
backgroundColor: '#3498db',
borderRadius: 5,
paddingVertical: 10,
paddingHorizontal: 20,
marginBottom: 10,
width: 250,
alignItems: 'center',
marginVertical: 20,
},
buttonText: {
color: '#fff',
fontSize: 16,
fontWeight: 'bold',
},
});
export default PestDetectOptions;
import React, { useState } from 'react';
import { View, TouchableOpacity, Image, Text, StyleSheet, ActivityIndicator, Button, ScrollView } from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import firebase from 'firebase/compat/app';
import 'firebase/compat/storage';
import pestData from './PestData.json';
const firebaseConfig = {
apiKey: "AIzaSyBX0highSIXvOLxH9Z20CQRyXrGYZj-GfY",
authDomain: "pest-detection-d63bd.firebaseapp.com",
projectId: "pest-detection-d63bd",
storageBucket: "pest-detection-d63bd.appspot.com",
messagingSenderId: "1096191342865",
appId: "1:1096191342865:web:4b2c237166dd4b2d4e34b0",
measurementId: "G-2ZH7JPF0DE"
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
function UploadPhotoDetect() {
const [selectedImage, setSelectedImage] = useState(null);
const [icon, setIcon] = useState("");
const [detections, setDetections] = useState([]);
const [upload, setUpload] = useState(false);
const [details, setDetails] = useState(false);
const [pestName, setPestName] = useState("");
const [pestImage, setPestImage] = useState("");
const [pestMethods, setPestMethods] = useState([]);
const [count, setCount] = useState(0);
const pickImage = async () => {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
console.log('Permission denied');
return;
}
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
if (!result.canceled) {
setSelectedImage(result.assets[0].uri);
}
};
const uploadImage = async () => {
if (selectedImage) {
const response = await fetch(selectedImage);
const blob = await response.blob();
const storageRef = firebase.storage().ref();
const imageRef = storageRef.child('images/' + new Date().getTime());
try {
setUpload(true);
await imageRef.put(blob);
const downloadURL = await imageRef.getDownloadURL();
console.log('Firebase Image URL:', downloadURL);
const apiResponse = await fetch('http://192.168.152.59:5000/link', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ image_url: downloadURL }),
});
if (apiResponse.ok) {
const data = await apiResponse.json();
setIcon(`data:image/png;base64,${data.annotated_image}`);
setUpload(false);
setDetections(data.detections);
} else {
console.log('API Error:', apiResponse.status);
}
} catch (error) {
console.log('Error:', error);
}
}
}
function getPestData(pestName) {
if (pestName === 'Mealy Bug') {
setPestName(pestData.pests[0].name);
setPestImage(pestData.pests[0].image);
setPestMethods(pestData.pests[0].methods);
} else if (pestName === 'whitefly') {
setPestName(pestData.pests[1].name);
setPestImage(pestData.pests[1].image);
setPestMethods(pestData.pests[1].methods);
} else if (pestName === 'Ash weevil') {
setPestName(pestData.pests[2].name);
setPestImage(pestData.pests[2].image);
setPestMethods(pestData.pests[2].methods);
} else if (pestName === 'Fruit fly') {
setPestName(pestData.pests[3].name);
setPestImage(pestData.pests[3].image);
setPestMethods(pestData.pests[3].methods);
} else if (pestName === 'Uroleucon compositae') {
setPestName(pestData.pests[4].name);
setPestImage(pestData.pests[4].image);
setPestMethods(pestData.pests[4].methods);
}
setDetails(true);
}
return (
<View style={styles.container}>
<Image source={require('../../assets/backgroundSoilData.jpg')} style={styles.backgroundImage} />
<ScrollView contentContainerStyle={styles.scrollContainer}>
<Text style={styles.title}>Pest Detection</Text>
{selectedImage && !icon && (
<Image source={{ uri: selectedImage }} style={styles.image} />
)}
{icon && !details && (
<View style={styles.resultContainer}>
<Image style={styles.resultImage} source={{ uri: icon }} />
<Text style={styles.resultText}>Identified pests and confidence</Text>
{detections.map((item, index) => (
<View key={index} style={styles.detectionItem}>
<Text style={styles.detectionText}>
{index + 1}. {item.class_name} (confidence: {item.confidence})
</Text>
<Button title="View More" onPress={() => getPestData(item.class_name)} />
</View>
))}
<Text style={styles.resultText}>No of objects detected: {detections.length}</Text>
</View>
)}
{upload && (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#007AFF" />
<Text style={styles.loadingText}>Analyzing...</Text>
</View>
)}
{!icon && !upload && (
<View style={styles.buttonContainer}>
<TouchableOpacity style={styles.button} title="Pick an image" onPress={pickImage}>
<Text style={styles.buttonText}>Pick a photo</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} title="Upload image" onPress={uploadImage}>
<Text style={styles.buttonText}>Upload photo</Text>
</TouchableOpacity>
</View>
)}
{details && (
<View style={styles.detailsContainer}>
<Text style={styles.title}>Pest Details</Text>
<Text style={styles.label}>Name:</Text>
<Text style={styles.text}>{pestName}</Text>
<Image source={{ uri: pestImage }} style={styles.image} />
<Text style={styles.label}>Control Methods:</Text>
<View style={styles.methodList}>
{pestMethods.map((method, index) => (
<View key={index} style={styles.methodItem}>
<Text style={styles.bulletPoint}></Text>
<Text style={styles.methodText}>{method}</Text>
</View>
))}
</View>
<Button title="Go Back" onPress={() => setDetails(false)} />
</View>
)}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
scrollContainer: {
flexGrow: 1,
justifyContent: 'center',
alignItems: 'center',
},
backgroundImage: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 16,
},
image: {
width: 300,
height: 300,
marginVertical: 10,
},
resultContainer: {
width: '100%',
maxWidth: 500,
padding: 0,
borderRadius: 10,
backgroundColor: 'rgba(255, 255, 255, 0.8)',
margin: 0,
alignItems: 'center',
},
resultImage: {
width: 400,
height: 300,
},
resultText: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 8,
},
detectionItem: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 8,
},
detectionText: {
flex: 1,
fontSize: 16,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
loadingText: {
fontSize: 18,
marginTop: 10,
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
marginVertical: 10,
},
button: {
backgroundColor: '#3498db',
borderRadius: 5,
padding: 10,
width: 150,
alignItems: 'center',
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
detailsContainer: {
width: '100%',
maxWidth: 400,
padding: 0,
borderRadius: 10,
backgroundColor: 'rgba(255, 255, 255, 0.8)',
margin: 0,
alignItems: 'center',
},
label: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 8,
},
text: {
fontSize: 16,
marginBottom: 8,
},
methodList: {
width: '100%',
},
methodItem: {
flexDirection: 'row',
alignItems: 'flex-start',
marginBottom: 8,
},
bulletPoint: {
fontSize: 16,
fontWeight: 'bold',
marginRight: 8,
},
methodText: {
fontSize: 16,
},
});
export default UploadPhotoDetect;
......@@ -6,7 +6,7 @@ const HomePage = ({ navigation }) => {
const handleOptionSelect = (option) => {
if (option === 'pestDisease') {
navigation.navigate('PestDiseasePage');
navigation.navigate('PestDetectOptions');
} else if (option === 'soilData') {
navigation.navigate('Soil Data Options');
} else if (option === 'weatherData') {
......@@ -82,4 +82,4 @@ const styles = StyleSheet.create({
},
});
export default HomePage;
export default HomePage;
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -25,7 +25,11 @@
"react-native-screens": "~3.20.0",
"react-native-snap-carousel": "^3.9.1",
"react-native-svg": "^13.9.0",
"react-native-web": "~0.18.11"
"react-native-web": "~0.18.11",
"expo-camera": "~13.4.2",
"expo-image-picker": "~14.3.2",
"react-native-multiple-select": "^0.5.12",
"react-native-picker-select": "^8.1.0"
},
"devDependencies": {
"@babel/core": "^7.20.0"
......
......@@ -2888,6 +2888,11 @@
prompts "^2.4.0"
semver "^6.3.0"
"@react-native-picker/picker@^1.8.3":
version "1.16.8"
resolved "https://registry.yarnpkg.com/@react-native-picker/picker/-/picker-1.16.8.tgz#2126ca54d4a5a3e9ea5e3f39ad1e6643f8e4b3d4"
integrity sha512-pacdQDX6V6EmjF+HoiIh6u++qx4mTK0WnhgUHRc01B+Qt5eoeUwseBqmqfTSXTx/aHDEd6PiIw7UGvKgFoqgFQ==
"@react-native-picker/picker@^2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@react-native-picker/picker/-/picker-2.5.1.tgz#dfa13d5b97bfbedf1f7e7c608181a82f1d58b351"
......@@ -5613,6 +5618,13 @@ expo-asset@~8.9.1:
path-browserify "^1.0.0"
url-parse "^1.5.9"
expo-camera@~13.4.2:
version "13.4.4"
resolved "https://registry.yarnpkg.com/expo-camera/-/expo-camera-13.4.4.tgz#e01ead31a3150398d37e94c307f6937480680690"
integrity sha512-7k54APbpSulUDR2CrD5SrmKjCdfdg4tqKRpbBOKc2J2MIBHhunExU77435JDYSejHRY5bfRHZsEp3yKwR862uw==
dependencies:
invariant "^2.2.4"
expo-constants@~14.2.0, expo-constants@~14.2.1:
version "14.2.1"
resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-14.2.1.tgz#b5b6b8079d2082c31ccf2cbc7cf97a0e83c229c3"
......@@ -5635,6 +5647,18 @@ expo-font@~11.1.1:
dependencies:
fontfaceobserver "^2.1.0"
expo-image-loader@~4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/expo-image-loader/-/expo-image-loader-4.3.0.tgz#d897b4d4f1838faa8291c36f00b99c2b36a6ac5c"
integrity sha512-2kqJIO+oYM8J3GbvTUHLqTSpt1dLpOn/X0eB4U4RTuzz/faj8l/TyQELsMBLlGAkweNUuG9LqznbaBz+WuSFEw==
expo-image-picker@~14.3.2:
version "14.3.2"
resolved "https://registry.yarnpkg.com/expo-image-picker/-/expo-image-picker-14.3.2.tgz#5ae2f36fe518a10c8fe82e5ff2ee735c14817cfc"
integrity sha512-xr/YeQMIYheXecWP033F2SPwpBlBR5xVCx7YSfSCTH8Y9pw7Z886agqKGbS9QBVGlzJ5qecJktZ6ASSzeslDVg==
dependencies:
expo-image-loader "~4.3.0"
expo-keep-awake@~12.0.1:
version "12.0.1"
resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-12.0.1.tgz#19c5ab55391394ded3f6c262b0707c7140658a11"
......@@ -8898,7 +8922,7 @@ prompts@^2.3.2, prompts@^2.4.0:
kleur "^3.0.3"
sisteransi "^1.0.5"
prop-types@*, prop-types@^15.6.1:
prop-types@*, prop-types@^15.6.1, prop-types@^15.7.2:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
......@@ -9103,6 +9127,21 @@ react-native-gradle-plugin@^0.71.18:
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.18.tgz#20ef199bc85be32e45bb6cc069ec2e7dcb1a74a6"
integrity sha512-7F6bD7B8Xsn3JllxcwHhFcsl9aHIig47+3eN4IHFNqfLhZr++3ElDrcqfMzugM+niWbaMi7bJ0kAkAL8eCpdWg==
react-native-multiple-select@^0.5.12:
version "0.5.12"
resolved "https://registry.yarnpkg.com/react-native-multiple-select/-/react-native-multiple-select-0.5.12.tgz#be9204f49bc1bb734c40422a89acc173959bcd70"
integrity sha512-lFw0u798/2qHr4TwDdxMtReRtsNOCC2SWPzWHRGKE4XcBiUll0hHhke7iqQg4xJdfo46C/h69f1ZXphDOjZY3A==
dependencies:
prop-types "^15.7.2"
react-native-picker-select@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/react-native-picker-select/-/react-native-picker-select-8.1.0.tgz#667a5442f783f4bcfd3f65880c6926155fd2c39c"
integrity sha512-iLsLv2OEWpXnQMDYJS6du5Cl1HTHy887n60Yp5OOiMny0TDB9w5CfxTUYWtpsvJJrUa/Yrv+1NMQiJy7IA4ETw==
dependencies:
"@react-native-picker/picker" "^1.8.3"
lodash.isequal "^4.5.0"
react-native-safe-area-context@4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.5.0.tgz#9208313236e8f49e1920ac1e2a2c975f03aed284"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment