ahmadalfian's picture
Update app.py
bc1b244 verified
import os
import torch
from torchvision import models, transforms
from PIL import Image
import streamlit as st
from huggingface_hub import hf_hub_download
import requests
import pandas as pd
api_usda = os.getenv("usdaapikey")
api_openai = os.getenv("openaikeys")
st.set_page_config(
page_title="AI-Based Fruit and Nutrition Prediction Model for Healthy Food Alternatives",
page_icon="🍎",
layout="wide",
initial_sidebar_state="expanded"
)
st.markdown(
"""
<style>
.css-18e3th9 {
background-color: #f0f2f6;
color: #000000;
}
.css-1lcbz8d {
background-color: #F63366;
}
.highlight {
color: #FF0000;
font-weight: bold;
}
</style>
""", unsafe_allow_html=True
)
st.sidebar.title("Navigation")
add_sidebar_selectbox = st.sidebar.selectbox(
"Go to",
('Home', 'Dataset', 'Model Description', 'Prediction', 'Contact')
)
def home():
st.write('''
# Final Project AI Engineering
Hello, I'm Ahmad Alfian Faisal. This is the deployed result of my AI project, a deep learning model, which is part of my Final Project for the AI Engineering SkillAcademy at Ruangguru. If you have any questions or feedback, feel free to reach out to me via [LinkedIn](www.linkedin.com/in/ahmadalfianfaisal).
''')
st.write('''
### AI-Based Fruit and Nutrition Prediction Model for Healthy Food Alternatives
This project emphasizes the importance of easy access to nutritional information, particularly in the face of fast food dominance, which is often low in nutrients and poses health risks. Using deep learning technology, this model can detect fruits or vegetables and quickly provide accurate nutritional information. It makes it easier for people to compare the nutritional content of healthy foods with fast foods, supporting the global trend of AI in creating more efficient and affordable health solutions.
''')
st.image("gambar_buah_home.jpg", width=800)
def dataset():
"""
Display the dataset information used in this project.
"""
st.title("Datasets Used")
st.subheader("1. Fruit and Vegetable Image Dataset")
st.markdown("""
- **Source**: [Kaggle - Fruit and Vegetable Image Recognition](https://www.kaggle.com/datasets/kritikseth/fruit-and-vegetable-image-recognition)
- **Purpose**: This dataset is used to train the deep learning model to detect and classify fruits and vegetables based on images.
- **Description**: The dataset contains thousands of labeled images of fruits and vegetables in various categories (e.g., apple, banana, tomato).
- **Total Classes**: 36 classes of fruits and vegetables.
- **Dataset Split**:
- **Train**: 100 images per category.
- **Validation**: 10 images per category.
- **Test**: 10 images per category.
""")
st.subheader("2. Nutritional Information Dataset")
st.markdown("""
- **Source**: [USDA FoodData Central](https://fdc.nal.usda.gov/index.html)
- **Purpose**: This dataset provides nutritional information related to the fruits and vegetables detected by the model.
- **Description**: It contains nutritional data for various types of foods, including calories, proteins, fats, carbohydrates, and other essential nutrients.
- **Government Agency**: The data is provided by the U.S. Government (USDA), which manages agricultural and food policies in the United States.
- **FoodData Central**: This is the database that provides detailed nutritional information for different foods and agricultural products.
- **API**: We use the USDA API to dynamically fetch nutritional data based on the fruits and vegetables detected by the model.
""")
st.subheader("3. Health Benefits Information Dataset")
st.markdown("""
- **Source**: The health benefits information is retrieved through the OpenAI API using an API key.
- **Purpose**: This dataset provides health benefits information related to the consumption of the detected fruits and vegetables.
- **Process**: Using the OpenAI API to retrieve information about the health benefits of fruits and vegetables in text format, which can be dynamically called based on model predictions.
- **Description**: Each fruit or vegetable detected by the model returns information regarding its health benefits, based on data from the API.
""")
def model_description():
st.title("Model Description")
st.markdown("""
In this project, we use three fine-tuned models for classifying images of fruits and vegetables:
**SqueezeNet1_1**, **DenseNet121**, and **MobileNet_V2**.
SqueezeNet1_1 is known for its small size and efficiency, while DenseNet121 excels at detecting deep features due to its dense architecture.
MobileNet_V2 is designed for high performance on resource-limited devices, making it an ideal choice for mobile applications.
""")
hyperparameters = {
"Hyperparameter": ["Transformations", "Data Loader", "Optimizer", "Learning Rate", "Loss Function", "Epochs"],
"Value": [
"Resize (224, 224), ToTensor, Normalize (mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])",
"Batch Size: 32",
"Adam",
"0.001",
"Cross Entropy Loss",
"20"
]
}
hyperparam_df = pd.DataFrame(hyperparameters)
st.subheader("Hyperparameters Used in the Models")
st.table(hyperparam_df)
st.header("Training Accuracy Results")
col1, col2, col3 = st.columns(3)
with col1:
st.image("train_acc_squeezenet.png", caption="SqueezeNet1_1 Training Accuracy", use_column_width=True)
with col2:
st.image("train_acc_densenet.png", caption="DenseNet121 Training Accuracy", use_column_width=True)
with col3:
st.image("train_acc_mobilenet.png", caption="MobileNet_V2 Training Accuracy", use_column_width=True)
st.header("Training Loss Results")
col1, col2, col3 = st.columns(3)
with col1:
st.image("train_loss_squeezenet.png", caption="SqueezeNet1_1 Training Loss", use_column_width=True)
with col2:
st.image("train_loss_densenet.png", caption="DenseNet121 Training Loss", use_column_width=True)
with col3:
st.image("train_loss_mobilenet.png", caption="MobileNet_V2 Training Loss", use_column_width=True)
def prediction():
if api_usda is None or api_openai is None:
st.error("Unable to use the APIs because the API keys are not set.")
return
def load_model(model_name):
if model_name == "DenseNet":
model_path = hf_hub_download(repo_id="ahmadalfian/fruits_vegetables_classifier",
filename="densenet_finetuned.pth")
model = models.densenet121(pretrained=False)
num_classes = 36
model.classifier = torch.nn.Linear(in_features=1024, out_features=num_classes)
elif model_name == "MobileNet":
model_path = hf_hub_download(repo_id="ahmadalfian/fruits_vegetables_classifier",
filename="mobilenet_finetuned.pth")
model = models.mobilenet_v2(pretrained=False)
num_classes = 36
model.classifier[1] = torch.nn.Linear(in_features=1280, out_features=num_classes)
elif model_name == "SqueezeNet":
model_path = hf_hub_download(repo_id="ahmadalfian/fruits_vegetables_classifier",
filename="squeezenet1_finetuned.pth")
model = models.squeezenet1_1(pretrained=False)
num_classes = 36
model.classifier[1] = torch.nn.Conv2d(512, num_classes, kernel_size=(1, 1), stride=(1, 1))
else:
raise ValueError("Model not supported.")
model.load_state_dict(torch.load(model_path, map_location=torch.device('cpu')))
model.eval()
return model
def get_health_benefits(food_name):
api_url = "https://api.openai.com/v1/chat/completions"
headers = {
"Authorization": f"Bearer {api_openai}",
"Content-Type": "application/json"
}
prompt = f"Give a 2-4 sentence health benefit of consuming {food_name}. Focus only on the health benefits like disease prevention or improving overall health. Do not mention nutritional content like vitamins, minerals, or other nutrients."
data = {
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant that provides health benefits of food."
},
{
"role": "user",
"content": prompt
}
],
"max_tokens": 150
}
try:
response = requests.post(api_url, headers=headers, json=data)
if response.status_code == 200:
result = response.json()
if 'choices' in result and len(result['choices']) > 0:
return result['choices'][0]['message']['content']
else:
return "No health benefits found in response."
else:
return f"Error: {response.status_code} - {response.text}"
except requests.exceptions.RequestException as e:
return f"Request failed: {e}"
def process_image(image):
if image.mode == 'RGBA':
image = image.convert('RGB')
print("Image converted from RGBA to RGB.")
preprocess = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
img_tensor = preprocess(image)
print(f"Image tensor shape: {img_tensor.shape}")
return img_tensor.unsqueeze(0)
def classify_image(model, image):
img_tensor = process_image(image)
print(f"Image tensor shape after unsqueeze: {img_tensor.shape}")
model.eval()
with torch.no_grad():
outputs = model(img_tensor)
print(f"Model output shape: {outputs.shape}")
probabilities = torch.nn.functional.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
return predicted.item(), confidence.item()
def get_nutrition_info(food_name):
url = "https://api.nal.usda.gov/fdc/v1/foods/search"
params = {
"query": food_name,
"pageSize": 1,
"api_key": api_usda
}
response = requests.get(url, params=params)
data = response.json()
if "foods" in data and len(data["foods"]) > 0:
food = data["foods"][0]
nutrients_totals = {
"Energy": 0,
"Carbohydrate, by difference": 0,
"Fiber, total dietary": 0,
"Vitamin C, total ascorbic acid": 0
}
for nutrient in food['foodNutrients']:
nutrient_name = nutrient['nutrientName']
nutrient_value = nutrient['value']
if nutrient_name in nutrients_totals:
nutrients_totals[nutrient_name] += nutrient_value
return nutrients_totals
else:
return None
label_to_food = {
0: "apple",
1: "banana",
2: "beetroot",
3: "bell pepper",
4: "cabbage",
5: "capsicum",
6: "carrot",
7: "cauliflower",
8: "chilli pepper",
9: "corn",
10: "cucumber",
11: "eggplant",
12: "garlic",
13: "ginger",
14: "grapes",
15: "jalapeno",
16: "kiwi",
17: "lemon",
18: "lettuce",
19: "mango",
20: "onion",
21: "orange",
22: "paprika",
23: "pear",
24: "peas",
25: "pineapple",
26: "pomegranate",
27: "potato",
28: "radish",
29: "soy beans",
30: "spinach",
31: "sweetcorn",
32: "sweet potato",
33: "tomato",
34: "turnip",
35: "watermelon",
}
st.markdown("## 🍎 Fruit and Vegetable Classifier")
st.markdown("Upload an image of a fruit or vegetable, and I will classify it for you!")
st.sidebar.header("Model Settings")
model_name = st.sidebar.selectbox("Select Model", ("DenseNet", "SqueezeNet", "MobileNet"))
confidence_threshold = st.sidebar.number_input("Set Confidence Threshold", min_value=0.0, max_value=1.0, value=0.5,
step=0.01)
uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"])
predict_button = st.sidebar.button("Predict")
if uploaded_file is not None and predict_button:
with st.spinner("Processing the image..."):
image = Image.open(uploaded_file)
model = load_model(model_name)
label, confidence = classify_image(model, image)
food_name = label_to_food.get(label, "Unknown Food")
nutrition_info = get_nutrition_info(food_name)
health_benefits = get_health_benefits(food_name)
col1, col2 = st.columns([1, 2])
with col1:
st.image(image, caption='Uploaded Image', width=250)
with col2:
st.write(f"**Prediction**: {food_name.capitalize()}")
st.write(f"**Confidence**: {confidence:.4f}")
if confidence < confidence_threshold:
st.markdown(
f"<p class='highlight'>Confidence is below the threshold of {confidence_threshold:.2f}.</p>",
unsafe_allow_html=True)
else:
st.write(f"Confidence exceeds the threshold of {confidence_threshold:.2f}")
if nutrition_info:
st.write("### Nutrition Info:")
data = {
"Nutrient": ["Energy (kcal)", "Carbohydrate (g)", "Fiber (g)", "Vitamin C (mg)"],
"Value": [
f"{nutrition_info['Energy']:.2f}",
f"{nutrition_info['Carbohydrate, by difference']:.2f}",
f"{nutrition_info['Fiber, total dietary']:.2f}",
f"{nutrition_info['Vitamin C, total ascorbic acid']:.2f}"
]
}
df = pd.DataFrame(data)
st.dataframe(df)
else:
st.write("Nutritional information not found.")
if confidence >= confidence_threshold:
st.write("### Health Benefits:")
st.write(health_benefits)
def contact():
st.header('About Me')
st.image('foto_profil.jpeg', width=500)
st.write('''
Hello, I’m Ahmad Alfian Faisal, a graduate from the Mining Engineering department at Universitas Hasanuddin. Since my university days, I’ve had a strong interest in data, particularly in Data Science and AI Engineering. To deepen my knowledge and skills in this field, I joined the AI Engineering SkillAcademy by Ruangguru.
As part of this program, I completed a Final Project, which serves as my capstone to apply the knowledge I have gained. I’m very excited to pursue a career in the data science and AI field, and I’m eager to contribute meaningfully to this area.
''')
st.write('''
**Contact Me**
- [LinkedIn]("www.linkedin.com/in/ahmadalfianfaisal")
- [Instagram]("https://instagram.com/ahmad.alfian.faisal?igshid=NzZlODBkYWE4Ng==")
''')
if add_sidebar_selectbox == 'Home':
home()
elif add_sidebar_selectbox == 'Dataset':
dataset()
elif add_sidebar_selectbox == 'Model Description':
model_description()
elif add_sidebar_selectbox == 'Prediction':
prediction()
elif add_sidebar_selectbox == 'Contact':
contact()