Edamam API and dish volume estimation
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
from APIs.aichat import *
|
||||||
|
from APIs.edamam import *
|
||||||
@@ -0,0 +1,937 @@
|
|||||||
|
import os
|
||||||
|
import requests
|
||||||
|
from typing import Dict, Any, Optional
|
||||||
|
|
||||||
|
EDAMAM_APP_ID__FOOD = os.getenv("EDAMAM_APP_ID__FOOD", None)
|
||||||
|
EDAMAM_APP_KEY__FOOD = os.getenv("EDAMAM_APP_KEY__FOOD", None)
|
||||||
|
|
||||||
|
class EdamamAPI:
|
||||||
|
"""Wrapper around Edamam Food Database API 2.0 (Vision & Nutrients)"""
|
||||||
|
|
||||||
|
BASE_URL = "https://api.edamam.com/api/vision/v1/nutrients"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def analyze_dish_image(self, image_file_path: str):
|
||||||
|
url = "https://api.edamam.com/api/vision/v1/nutrients"
|
||||||
|
|
||||||
|
# Query parameters as specified by the YAML schema
|
||||||
|
params = {
|
||||||
|
"app_id": EDAMAM_APP_ID__FOOD,
|
||||||
|
"app_key": EDAMAM_APP_KEY__FOOD,
|
||||||
|
"beta": "true" # Recommended since vision is in Beta
|
||||||
|
}
|
||||||
|
print("params:", params)
|
||||||
|
|
||||||
|
# Specify the media type in the header
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "image/jpeg"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read and send the raw binary bytes directly in data (NOT files= or json=)
|
||||||
|
with open(image_file_path, "rb") as image_file:
|
||||||
|
raw_image_bytes = image_file.read()
|
||||||
|
|
||||||
|
response = requests.post(
|
||||||
|
url,
|
||||||
|
params=params,
|
||||||
|
headers=headers,
|
||||||
|
data=raw_image_bytes
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"Edamam API response : {response.json()}")
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
# Returns something like:
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"combined": {
|
||||||
|
"problems": [],
|
||||||
|
"recipe": {
|
||||||
|
"calories": 306,
|
||||||
|
"cautions": [
|
||||||
|
"GLUTEN",
|
||||||
|
"WHEAT",
|
||||||
|
"MILK",
|
||||||
|
"SULFITES",
|
||||||
|
"FODMAP"
|
||||||
|
],
|
||||||
|
"dietLabels": [],
|
||||||
|
"healthLabels": [
|
||||||
|
"EGG_FREE",
|
||||||
|
"PEANUT_FREE",
|
||||||
|
"TREE_NUT_FREE",
|
||||||
|
"SOY_FREE",
|
||||||
|
"FISH_FREE",
|
||||||
|
"SHELLFISH_FREE",
|
||||||
|
"CRUSTACEAN_FREE",
|
||||||
|
"CELERY_FREE",
|
||||||
|
"MUSTARD_FREE",
|
||||||
|
"SESAME_FREE",
|
||||||
|
"LUPINE_FREE",
|
||||||
|
"MOLLUSK_FREE",
|
||||||
|
"ALCOHOL_FREE"
|
||||||
|
],
|
||||||
|
"ingredientLines": [
|
||||||
|
"90 g (3 oz) Beef chunks",
|
||||||
|
"100 g (0.75 cup) Potatoes, cubed",
|
||||||
|
"40 g (0.33 cup) Carrots, sliced",
|
||||||
|
"30 g (0.25 cup) Green beans",
|
||||||
|
"120 g (0.5 cup) Brown gravy or stew sauce",
|
||||||
|
"Salt and pepper to taste"
|
||||||
|
],
|
||||||
|
"label": "Beef Stew with Vegetables (Frozen Meal)",
|
||||||
|
"totalDaily": {
|
||||||
|
"CA": {
|
||||||
|
"label": "Calcium",
|
||||||
|
"quantity": 9.808827779627787,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"CHOCDF": {
|
||||||
|
"label": "Carbs",
|
||||||
|
"quantity": 9.07220373540042,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"CHOCDF.net": {
|
||||||
|
"label": "Carbohydrates (net)",
|
||||||
|
"quantity": 0.0,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"CHOLE": {
|
||||||
|
"label": "Cholesterol",
|
||||||
|
"quantity": 20.837056709550403,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"ENERC_KCAL": {
|
||||||
|
"label": "Energy",
|
||||||
|
"quantity": 13.100053025164515,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"FASAT": {
|
||||||
|
"label": "Saturated",
|
||||||
|
"quantity": 17.148508115376796,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"FAT": {
|
||||||
|
"label": "Fat",
|
||||||
|
"quantity": 14.902089676480887,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"FE": {
|
||||||
|
"label": "Iron",
|
||||||
|
"quantity": 21.951689781236098,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"FIBTG": {
|
||||||
|
"label": "Fiber",
|
||||||
|
"quantity": 13.858671762525935,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"FOLDFE": {
|
||||||
|
"label": "Folate equivalent (total)",
|
||||||
|
"quantity": 10.817828789332737,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"K": {
|
||||||
|
"label": "Potassium",
|
||||||
|
"quantity": 28.904445650775536,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"MG": {
|
||||||
|
"label": "Magnesium",
|
||||||
|
"quantity": 15.863016599088612,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"NA": {
|
||||||
|
"label": "Sodium",
|
||||||
|
"quantity": 60.46248,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"NIA": {
|
||||||
|
"label": "Niacin (B3)",
|
||||||
|
"quantity": 66.37252070251446,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"P": {
|
||||||
|
"label": "Phosphorus",
|
||||||
|
"quantity": 25.034580972170218,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"PROCNT": {
|
||||||
|
"label": "Protein",
|
||||||
|
"quantity": 21.91938193709794,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"RIBF": {
|
||||||
|
"label": "Riboflavin (B2)",
|
||||||
|
"quantity": 73.88477475545037,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"THIA": {
|
||||||
|
"label": "Thiamin (B1)",
|
||||||
|
"quantity": 84.12049444050538,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"TOCPHA": {
|
||||||
|
"label": "Vitamin E",
|
||||||
|
"quantity": 12.990953399638641,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITA_RAE": {
|
||||||
|
"label": "Vitamin A",
|
||||||
|
"quantity": 45.87938825251855,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITB12": {
|
||||||
|
"label": "Vitamin B12",
|
||||||
|
"quantity": 113.07016020542191,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITB6A": {
|
||||||
|
"label": "Vitamin B6",
|
||||||
|
"quantity": 90.1530888403073,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITC": {
|
||||||
|
"label": "Vitamin C",
|
||||||
|
"quantity": 35.18207820897409,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITD": {
|
||||||
|
"label": "Vitamin D",
|
||||||
|
"quantity": 13.66228503481425,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITK1": {
|
||||||
|
"label": "Vitamin K",
|
||||||
|
"quantity": 27.534449511962567,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"ZN": {
|
||||||
|
"label": "Zinc",
|
||||||
|
"quantity": 55.091388643252344,
|
||||||
|
"unit": "%"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"totalNutrients": {
|
||||||
|
"CA": {
|
||||||
|
"label": "Calcium",
|
||||||
|
"quantity": 127.51476113516124,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"CHOCDF": {
|
||||||
|
"label": "Carbs",
|
||||||
|
"quantity": 26.573051753721295,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"CHOCDF.net": {
|
||||||
|
"label": "Carbohydrates (net)",
|
||||||
|
"quantity": 21.30675648396144,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"CHOLE": {
|
||||||
|
"label": "Cholesterol",
|
||||||
|
"quantity": 73.23964970198097,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"ENERC_KCAL": {
|
||||||
|
"label": "Energy",
|
||||||
|
"quantity": 306.9669925121675,
|
||||||
|
"unit": "kcal"
|
||||||
|
},
|
||||||
|
"FAMS": {
|
||||||
|
"label": "Monounsaturated",
|
||||||
|
"quantity": 5.622055495052523,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FAPU": {
|
||||||
|
"label": "Polyunsaturated",
|
||||||
|
"quantity": 1.5770619917608195,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FASAT": {
|
||||||
|
"label": "Saturated",
|
||||||
|
"quantity": 4.0183241641356675,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FAT": {
|
||||||
|
"label": "Fat",
|
||||||
|
"quantity": 11.639773878137946,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FATRN": {
|
||||||
|
"label": "Trans",
|
||||||
|
"quantity": 0.24391676668519283,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FE": {
|
||||||
|
"label": "Iron",
|
||||||
|
"quantity": 3.9513041606224975,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"FIBTG": {
|
||||||
|
"label": "Fiber",
|
||||||
|
"quantity": 5.266295269759856,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FOLAC": {
|
||||||
|
"label": "Folic acid",
|
||||||
|
"quantity": 18.024043373983595,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"FOLDFE": {
|
||||||
|
"label": "Folate equivalent (total)",
|
||||||
|
"quantity": 43.271315157330946,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"FOLFD": {
|
||||||
|
"label": "Folate (food)",
|
||||||
|
"quantity": 40.54129806334046,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"K": {
|
||||||
|
"label": "Potassium",
|
||||||
|
"quantity": 982.7511521263683,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"MG": {
|
||||||
|
"label": "Magnesium",
|
||||||
|
"quantity": 66.62466971617216,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"NA": {
|
||||||
|
"label": "Sodium",
|
||||||
|
"quantity": 906.9372000000001,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"NIA": {
|
||||||
|
"label": "Niacin (B3)",
|
||||||
|
"quantity": 10.619603312402313,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"P": {
|
||||||
|
"label": "Phosphorus",
|
||||||
|
"quantity": 312.93226215212775,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"PROCNT": {
|
||||||
|
"label": "Protein",
|
||||||
|
"quantity": 25.68129586205237,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"RIBF": {
|
||||||
|
"label": "Riboflavin (B2)",
|
||||||
|
"quantity": 0.9605020718208549,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"SUGAR": {
|
||||||
|
"label": "Sugars",
|
||||||
|
"quantity": 8.053516658227332,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"SUGAR.added": {
|
||||||
|
"label": "Sugars, added",
|
||||||
|
"quantity": 2.3940423830596225,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"Sugar.alcohol": {
|
||||||
|
"label": "Sugar alcohol",
|
||||||
|
"quantity": 0.0,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"THIA": {
|
||||||
|
"label": "Thiamin (B1)",
|
||||||
|
"quantity": 1.0094459332860646,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"TOCPHA": {
|
||||||
|
"label": "Vitamin E",
|
||||||
|
"quantity": 1.9486430099457963,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"VITA_RAE": {
|
||||||
|
"label": "Vitamin A",
|
||||||
|
"quantity": 412.914494272667,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"VITB12": {
|
||||||
|
"label": "Vitamin B12",
|
||||||
|
"quantity": 2.7136838449301255,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"VITB6A": {
|
||||||
|
"label": "Vitamin B6",
|
||||||
|
"quantity": 1.5326025102852243,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"VITC": {
|
||||||
|
"label": "Vitamin C",
|
||||||
|
"quantity": 31.66387038807668,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"VITD": {
|
||||||
|
"label": "Vitamin D",
|
||||||
|
"quantity": 2.73245700696285,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"VITK1": {
|
||||||
|
"label": "Vitamin K",
|
||||||
|
"quantity": 33.04133941435508,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"WATER": {
|
||||||
|
"label": "Water",
|
||||||
|
"quantity": 321.1285604946806,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"ZN": {
|
||||||
|
"label": "Zinc",
|
||||||
|
"quantity": 6.060052750757758,
|
||||||
|
"unit": "mg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"totalWeight": 390.7575715150228,
|
||||||
|
"translations": [
|
||||||
|
{
|
||||||
|
"id": "EGG_FREE",
|
||||||
|
"label": "Egg-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "PEANUT_FREE",
|
||||||
|
"label": "Peanut-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "TREE_NUT_FREE",
|
||||||
|
"label": "Tree-Nut-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SOY_FREE",
|
||||||
|
"label": "Soy-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "FISH_FREE",
|
||||||
|
"label": "Fish-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SHELLFISH_FREE",
|
||||||
|
"label": "Shellfish-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "CRUSTACEAN_FREE",
|
||||||
|
"label": "Crustacean-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "CELERY_FREE",
|
||||||
|
"label": "Celery-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "MUSTARD_FREE",
|
||||||
|
"label": "Mustard-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SESAME_FREE",
|
||||||
|
"label": "Sesame-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "LUPINE_FREE",
|
||||||
|
"label": "Lupine-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "MOLLUSK_FREE",
|
||||||
|
"label": "Mollusk-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ALCOHOL_FREE",
|
||||||
|
"label": "Alcohol-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "GLUTEN",
|
||||||
|
"label": "Gluten",
|
||||||
|
"type": "caution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "WHEAT",
|
||||||
|
"label": "Wheat",
|
||||||
|
"type": "caution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "MILK",
|
||||||
|
"label": "Milk",
|
||||||
|
"type": "caution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SULFITES",
|
||||||
|
"label": "Sulfites",
|
||||||
|
"type": "caution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "FODMAP",
|
||||||
|
"label": "FODMAP",
|
||||||
|
"type": "caution"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"uri": "http://www.edamam.com/ontologies/edamam.owl#recipe_e59b15e71cd34bf4b7c02c2f545e40f3",
|
||||||
|
"yield": 1.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dishes": [
|
||||||
|
{
|
||||||
|
"problems": [],
|
||||||
|
"recipe": {
|
||||||
|
"calories": 306,
|
||||||
|
"cautions": [
|
||||||
|
"GLUTEN",
|
||||||
|
"WHEAT",
|
||||||
|
"MILK",
|
||||||
|
"SULFITES",
|
||||||
|
"FODMAP"
|
||||||
|
],
|
||||||
|
"dietLabels": [],
|
||||||
|
"healthLabels": [
|
||||||
|
"EGG_FREE",
|
||||||
|
"PEANUT_FREE",
|
||||||
|
"TREE_NUT_FREE",
|
||||||
|
"SOY_FREE",
|
||||||
|
"FISH_FREE",
|
||||||
|
"SHELLFISH_FREE",
|
||||||
|
"CRUSTACEAN_FREE",
|
||||||
|
"CELERY_FREE",
|
||||||
|
"MUSTARD_FREE",
|
||||||
|
"SESAME_FREE",
|
||||||
|
"LUPINE_FREE",
|
||||||
|
"MOLLUSK_FREE",
|
||||||
|
"ALCOHOL_FREE"
|
||||||
|
],
|
||||||
|
"ingredientLines": [
|
||||||
|
"90 g (3 oz) Beef chunks",
|
||||||
|
"100 g (0.75 cup) Potatoes, cubed",
|
||||||
|
"40 g (0.33 cup) Carrots, sliced",
|
||||||
|
"30 g (0.25 cup) Green beans",
|
||||||
|
"120 g (0.5 cup) Brown gravy or stew sauce",
|
||||||
|
"Salt and pepper to taste"
|
||||||
|
],
|
||||||
|
"label": "Beef Stew with Vegetables (Frozen Meal)",
|
||||||
|
"totalDaily": {
|
||||||
|
"CA": {
|
||||||
|
"label": "Calcium",
|
||||||
|
"quantity": 9.808827779627787,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"CHOCDF": {
|
||||||
|
"label": "Carbs",
|
||||||
|
"quantity": 9.07220373540042,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"CHOCDF.net": {
|
||||||
|
"label": "Carbohydrates (net)",
|
||||||
|
"quantity": 0.0,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"CHOLE": {
|
||||||
|
"label": "Cholesterol",
|
||||||
|
"quantity": 20.837056709550403,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"ENERC_KCAL": {
|
||||||
|
"label": "Energy",
|
||||||
|
"quantity": 13.100053025164515,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"FASAT": {
|
||||||
|
"label": "Saturated",
|
||||||
|
"quantity": 17.148508115376796,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"FAT": {
|
||||||
|
"label": "Fat",
|
||||||
|
"quantity": 14.902089676480887,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"FE": {
|
||||||
|
"label": "Iron",
|
||||||
|
"quantity": 21.951689781236098,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"FIBTG": {
|
||||||
|
"label": "Fiber",
|
||||||
|
"quantity": 13.858671762525935,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"FOLDFE": {
|
||||||
|
"label": "Folate equivalent (total)",
|
||||||
|
"quantity": 10.817828789332737,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"K": {
|
||||||
|
"label": "Potassium",
|
||||||
|
"quantity": 28.904445650775536,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"MG": {
|
||||||
|
"label": "Magnesium",
|
||||||
|
"quantity": 15.863016599088612,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"NA": {
|
||||||
|
"label": "Sodium",
|
||||||
|
"quantity": 60.46248,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"NIA": {
|
||||||
|
"label": "Niacin (B3)",
|
||||||
|
"quantity": 66.37252070251446,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"P": {
|
||||||
|
"label": "Phosphorus",
|
||||||
|
"quantity": 25.034580972170218,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"PROCNT": {
|
||||||
|
"label": "Protein",
|
||||||
|
"quantity": 21.91938193709794,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"RIBF": {
|
||||||
|
"label": "Riboflavin (B2)",
|
||||||
|
"quantity": 73.88477475545037,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"THIA": {
|
||||||
|
"label": "Thiamin (B1)",
|
||||||
|
"quantity": 84.12049444050538,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"TOCPHA": {
|
||||||
|
"label": "Vitamin E",
|
||||||
|
"quantity": 12.990953399638641,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITA_RAE": {
|
||||||
|
"label": "Vitamin A",
|
||||||
|
"quantity": 45.87938825251855,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITB12": {
|
||||||
|
"label": "Vitamin B12",
|
||||||
|
"quantity": 113.07016020542191,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITB6A": {
|
||||||
|
"label": "Vitamin B6",
|
||||||
|
"quantity": 90.1530888403073,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITC": {
|
||||||
|
"label": "Vitamin C",
|
||||||
|
"quantity": 35.18207820897409,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITD": {
|
||||||
|
"label": "Vitamin D",
|
||||||
|
"quantity": 13.66228503481425,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"VITK1": {
|
||||||
|
"label": "Vitamin K",
|
||||||
|
"quantity": 27.534449511962567,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
"ZN": {
|
||||||
|
"label": "Zinc",
|
||||||
|
"quantity": 55.091388643252344,
|
||||||
|
"unit": "%"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"totalNutrients": {
|
||||||
|
"CA": {
|
||||||
|
"label": "Calcium",
|
||||||
|
"quantity": 127.51476113516124,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"CHOCDF": {
|
||||||
|
"label": "Carbs",
|
||||||
|
"quantity": 26.573051753721295,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"CHOCDF.net": {
|
||||||
|
"label": "Carbohydrates (net)",
|
||||||
|
"quantity": 21.30675648396144,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"CHOLE": {
|
||||||
|
"label": "Cholesterol",
|
||||||
|
"quantity": 73.23964970198097,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"ENERC_KCAL": {
|
||||||
|
"label": "Energy",
|
||||||
|
"quantity": 306.9669925121675,
|
||||||
|
"unit": "kcal"
|
||||||
|
},
|
||||||
|
"FAMS": {
|
||||||
|
"label": "Monounsaturated",
|
||||||
|
"quantity": 5.622055495052523,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FAPU": {
|
||||||
|
"label": "Polyunsaturated",
|
||||||
|
"quantity": 1.5770619917608195,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FASAT": {
|
||||||
|
"label": "Saturated",
|
||||||
|
"quantity": 4.0183241641356675,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FAT": {
|
||||||
|
"label": "Fat",
|
||||||
|
"quantity": 11.639773878137946,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FATRN": {
|
||||||
|
"label": "Trans",
|
||||||
|
"quantity": 0.24391676668519283,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FE": {
|
||||||
|
"label": "Iron",
|
||||||
|
"quantity": 3.9513041606224975,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"FIBTG": {
|
||||||
|
"label": "Fiber",
|
||||||
|
"quantity": 5.266295269759856,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"FOLAC": {
|
||||||
|
"label": "Folic acid",
|
||||||
|
"quantity": 18.024043373983595,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"FOLDFE": {
|
||||||
|
"label": "Folate equivalent (total)",
|
||||||
|
"quantity": 43.271315157330946,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"FOLFD": {
|
||||||
|
"label": "Folate (food)",
|
||||||
|
"quantity": 40.54129806334046,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"K": {
|
||||||
|
"label": "Potassium",
|
||||||
|
"quantity": 982.7511521263683,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"MG": {
|
||||||
|
"label": "Magnesium",
|
||||||
|
"quantity": 66.62466971617216,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"NA": {
|
||||||
|
"label": "Sodium",
|
||||||
|
"quantity": 906.9372000000001,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"NIA": {
|
||||||
|
"label": "Niacin (B3)",
|
||||||
|
"quantity": 10.619603312402313,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"P": {
|
||||||
|
"label": "Phosphorus",
|
||||||
|
"quantity": 312.93226215212775,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"PROCNT": {
|
||||||
|
"label": "Protein",
|
||||||
|
"quantity": 25.68129586205237,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"RIBF": {
|
||||||
|
"label": "Riboflavin (B2)",
|
||||||
|
"quantity": 0.9605020718208549,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"SUGAR": {
|
||||||
|
"label": "Sugars",
|
||||||
|
"quantity": 8.053516658227332,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"SUGAR.added": {
|
||||||
|
"label": "Sugars, added",
|
||||||
|
"quantity": 2.3940423830596225,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"Sugar.alcohol": {
|
||||||
|
"label": "Sugar alcohol",
|
||||||
|
"quantity": 0.0,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"THIA": {
|
||||||
|
"label": "Thiamin (B1)",
|
||||||
|
"quantity": 1.0094459332860646,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"TOCPHA": {
|
||||||
|
"label": "Vitamin E",
|
||||||
|
"quantity": 1.9486430099457963,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"VITA_RAE": {
|
||||||
|
"label": "Vitamin A",
|
||||||
|
"quantity": 412.914494272667,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"VITB12": {
|
||||||
|
"label": "Vitamin B12",
|
||||||
|
"quantity": 2.7136838449301255,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"VITB6A": {
|
||||||
|
"label": "Vitamin B6",
|
||||||
|
"quantity": 1.5326025102852243,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"VITC": {
|
||||||
|
"label": "Vitamin C",
|
||||||
|
"quantity": 31.66387038807668,
|
||||||
|
"unit": "mg"
|
||||||
|
},
|
||||||
|
"VITD": {
|
||||||
|
"label": "Vitamin D",
|
||||||
|
"quantity": 2.73245700696285,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"VITK1": {
|
||||||
|
"label": "Vitamin K",
|
||||||
|
"quantity": 33.04133941435508,
|
||||||
|
"unit": "\u00b5g"
|
||||||
|
},
|
||||||
|
"WATER": {
|
||||||
|
"label": "Water",
|
||||||
|
"quantity": 321.1285604946806,
|
||||||
|
"unit": "g"
|
||||||
|
},
|
||||||
|
"ZN": {
|
||||||
|
"label": "Zinc",
|
||||||
|
"quantity": 6.060052750757758,
|
||||||
|
"unit": "mg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"totalWeight": 390.7575715150228,
|
||||||
|
"translations": [
|
||||||
|
{
|
||||||
|
"id": "EGG_FREE",
|
||||||
|
"label": "Egg-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "PEANUT_FREE",
|
||||||
|
"label": "Peanut-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "TREE_NUT_FREE",
|
||||||
|
"label": "Tree-Nut-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SOY_FREE",
|
||||||
|
"label": "Soy-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "FISH_FREE",
|
||||||
|
"label": "Fish-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SHELLFISH_FREE",
|
||||||
|
"label": "Shellfish-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "CRUSTACEAN_FREE",
|
||||||
|
"label": "Crustacean-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "CELERY_FREE",
|
||||||
|
"label": "Celery-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "MUSTARD_FREE",
|
||||||
|
"label": "Mustard-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SESAME_FREE",
|
||||||
|
"label": "Sesame-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "LUPINE_FREE",
|
||||||
|
"label": "Lupine-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "MOLLUSK_FREE",
|
||||||
|
"label": "Mollusk-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ALCOHOL_FREE",
|
||||||
|
"label": "Alcohol-Free",
|
||||||
|
"type": "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "GLUTEN",
|
||||||
|
"label": "Gluten",
|
||||||
|
"type": "caution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "WHEAT",
|
||||||
|
"label": "Wheat",
|
||||||
|
"type": "caution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "MILK",
|
||||||
|
"label": "Milk",
|
||||||
|
"type": "caution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SULFITES",
|
||||||
|
"label": "Sulfites",
|
||||||
|
"type": "caution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "FODMAP",
|
||||||
|
"label": "FODMAP",
|
||||||
|
"type": "caution"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"uri": "http://www.edamam.com/ontologies/edamam.owl#recipe_e59b15e71cd34bf4b7c02c2f545e40f3",
|
||||||
|
"yield": 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
+11
-1
@@ -3,8 +3,13 @@ import base64
|
|||||||
import uuid
|
import uuid
|
||||||
from flask import Flask, request, jsonify
|
from flask import Flask, request, jsonify
|
||||||
from pymongo import MongoClient
|
from pymongo import MongoClient
|
||||||
from tools.aichat import generate
|
from APIs import generate, EdamamAPI
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, '..')
|
||||||
|
try:
|
||||||
from shared import config
|
from shared import config
|
||||||
|
except ImportError:
|
||||||
|
from ..shared import config
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@@ -94,6 +99,11 @@ def device_network():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"error": f"Database error: {str(e)}"}), 500
|
return jsonify({"error": f"Database error: {str(e)}"}), 500
|
||||||
|
|
||||||
|
@app.route("/debug", methods=["GET"])
|
||||||
|
def debug():
|
||||||
|
image_path = "microwaveDish.jpg"
|
||||||
|
edamam = EdamamAPI()
|
||||||
|
return edamam.analyze_dish_image(image_path)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(debug=config.DEBUG)
|
app.run(debug=config.DEBUG)
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 133 KiB |
@@ -0,0 +1,129 @@
|
|||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
from typing import Dict, Any, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class MicrowaveDishAnalyzer:
|
||||||
|
"""
|
||||||
|
Estimates food dish volume from top-down camera images and dish height,
|
||||||
|
and cross-validates physical volume against Edamam AI mass estimates.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Constant scale ratio: Centimeters per Pixel.
|
||||||
|
# TODO : Replace this value once your camera calibration is complete.
|
||||||
|
CM_PER_PIXEL: float = 0.05 # Example: 1 pixel = 0.05 cm
|
||||||
|
|
||||||
|
def __init__(self, cm_per_pixel: Optional[float] = None):
|
||||||
|
if cm_per_pixel is not None:
|
||||||
|
self.cm_per_pixel = cm_per_pixel
|
||||||
|
else:
|
||||||
|
self.cm_per_pixel = self.CM_PER_PIXEL
|
||||||
|
|
||||||
|
def calculate_surface_area_cm2(self, image_path: str) -> float:
|
||||||
|
"""
|
||||||
|
Segments the food/dish from the background and returns surface area in cm².
|
||||||
|
"""
|
||||||
|
image = cv2.imread(image_path)
|
||||||
|
if image is None:
|
||||||
|
raise FileNotFoundError(f"Image could not be loaded from path: {image_path}")
|
||||||
|
|
||||||
|
# 1. Convert to grayscale & blur to reduce noise
|
||||||
|
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
||||||
|
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
|
||||||
|
|
||||||
|
# 2. Otsu thresholding to segment foreground (dish) from background (turntable)
|
||||||
|
_, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
|
||||||
|
|
||||||
|
# 3. Find contours
|
||||||
|
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||||||
|
if not contours:
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
# 4. Assume the largest contour corresponds to the dish/food area
|
||||||
|
largest_contour = max(contours, key=cv2.contourArea)
|
||||||
|
area_pixels = cv2.contourArea(largest_contour)
|
||||||
|
|
||||||
|
# 5. Convert pixels² to cm² using scale ratio squared
|
||||||
|
area_cm2 = area_pixels * (self.cm_per_pixel ** 2)
|
||||||
|
return float(area_cm2)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_shape_factor(food_label: str) -> float:
|
||||||
|
"""
|
||||||
|
Selects geometric correction factor (k_shape) based on container/food shape:
|
||||||
|
- Bowls/Soups: ~0.60 (paraboloid)
|
||||||
|
- Drinks/Mugs: ~0.95 (cylinder)
|
||||||
|
- Flat plates/solid foods: ~0.85 (truncated cone / disk)
|
||||||
|
"""
|
||||||
|
label = food_label.lower()
|
||||||
|
if any(w in label for w in ["soup", "chili", "stew", "curry", "bowl"]):
|
||||||
|
return 0.60
|
||||||
|
elif any(w in label for w in ["coffee", "tea", "milk", "water", "beverage", "mug"]):
|
||||||
|
return 0.95
|
||||||
|
elif any(w in label for w in ["bread", "cake", "muffin"]):
|
||||||
|
return 0.80
|
||||||
|
return 0.85 # Default factor for plated meals
|
||||||
|
|
||||||
|
def estimate_volume(
|
||||||
|
self, image_path: str, height_cm: float, food_label: str = ""
|
||||||
|
) -> Dict[str, float]:
|
||||||
|
"""
|
||||||
|
Computes total physical volume in cm³ (mL).
|
||||||
|
Volume = Area (cm²) * Height (cm) * Shape Factor
|
||||||
|
"""
|
||||||
|
area_cm2 = self.calculate_surface_area_cm2(image_path)
|
||||||
|
k_shape = self._get_shape_factor(food_label)
|
||||||
|
volume_cm3 = area_cm2 * height_cm * k_shape
|
||||||
|
|
||||||
|
return {
|
||||||
|
"surface_area_cm2": round(area_cm2, 2),
|
||||||
|
"height_cm": round(height_cm, 2),
|
||||||
|
"shape_factor": k_shape,
|
||||||
|
"volume_cm3": round(volume_cm3, 2),
|
||||||
|
}
|
||||||
|
|
||||||
|
def reconcile_mass(
|
||||||
|
self, edamam_mass_g: float, volume_cm3: float, food_label: str = ""
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Cross-validates Edamam's visual mass against physical volume using expected density.
|
||||||
|
Returns the most physically accurate mass estimate in grams.
|
||||||
|
"""
|
||||||
|
if volume_cm3 <= 0:
|
||||||
|
return {
|
||||||
|
"final_mass_g": edamam_mass_g,
|
||||||
|
"status": "unvalidated_zero_volume",
|
||||||
|
"calculated_density": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
calculated_density = edamam_mass_g / volume_cm3
|
||||||
|
label = food_label.lower()
|
||||||
|
|
||||||
|
# Expected food densities (g/cm³)
|
||||||
|
if any(w in label for w in ["bread", "popcorn", "cake"]):
|
||||||
|
expected_density = 0.35
|
||||||
|
elif any(w in label for w in ["soup", "beverage", "water", "milk"]):
|
||||||
|
expected_density = 1.0
|
||||||
|
else:
|
||||||
|
expected_density = 0.92 # Average cooked meal (water + fats + carbs)
|
||||||
|
|
||||||
|
# Plausibility bounds (±35% variance around expected density)
|
||||||
|
min_density = expected_density * 0.65
|
||||||
|
max_density = expected_density * 1.35
|
||||||
|
|
||||||
|
if min_density <= calculated_density <= max_density:
|
||||||
|
# Edamam estimate is physically realistic
|
||||||
|
final_mass = edamam_mass_g
|
||||||
|
status = "validated_edamam_mass"
|
||||||
|
else:
|
||||||
|
# Edamam misjudged scale — fallback to Volume * Expected Density
|
||||||
|
final_mass = volume_cm3 * expected_density
|
||||||
|
status = "reconciled_via_volume_density"
|
||||||
|
|
||||||
|
return {
|
||||||
|
"final_mass_g": round(final_mass, 2),
|
||||||
|
"raw_edamam_mass_g": edamam_mass_g,
|
||||||
|
"calculated_density_g_cm3": round(calculated_density, 3),
|
||||||
|
"expected_density_g_cm3": expected_density,
|
||||||
|
"status": status,
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Dict, Any, Optional
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DishThermalState:
|
||||||
|
food_name: str
|
||||||
|
macronutrients: Dict[str, float] # grams of water, fat, protein, carbs
|
||||||
|
estimated_mass_g: float
|
||||||
|
initial_temp_c: float
|
||||||
|
volume_cm3: Optional[float] = None
|
||||||
|
|
||||||
|
class MicrowaveThermalEngine:
|
||||||
|
"""Calculates cook parameters based on physical properties"""
|
||||||
|
|
||||||
|
DEFAULT_EFFICIENCY = 0.70 # ~70% magnetron efficiency
|
||||||
|
TARGET_TEMP_C = 74.0 # Safe food temperature
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def estimate_specific_heat(macros: Dict[str, float], total_weight_g: float) -> float:
|
||||||
|
"""Estimates Cp in J/(g*C) based on macro composition"""
|
||||||
|
if total_weight_g <= 0:
|
||||||
|
return 3.5 # Fallback average for mixed meals
|
||||||
|
|
||||||
|
w_water = macros.get("water_g", total_weight_g * 0.7) / total_weight_g
|
||||||
|
w_protein = macros.get("protein_g", 0.0) / total_weight_g
|
||||||
|
w_fat = macros.get("fat_g", 0.0) / total_weight_g
|
||||||
|
w_carbs = macros.get("carbs_g", 0.0) / total_weight_g
|
||||||
|
|
||||||
|
return (4.184 * w_water) + (1.71 * w_protein) + (1.67 * w_fat) + (1.42 * w_carbs)
|
||||||
|
|
||||||
|
def calculate_cook_plan(self, state: DishThermalState, microwave_wattage: int) -> Dict[str, Any]:
|
||||||
|
cp = self.estimate_specific_heat(state.macronutrients, state.estimated_mass_g)
|
||||||
|
delta_t = max(0.0, self.TARGET_TEMP_C - state.initial_temp_c)
|
||||||
|
|
||||||
|
# Q = m * c_p * delta_t
|
||||||
|
required_joules = state.estimated_mass_g * cp * delta_t
|
||||||
|
effective_power_watts = microwave_wattage * self.DEFAULT_EFFICIENCY
|
||||||
|
|
||||||
|
total_seconds = required_joules / effective_power_watts if effective_power_watts > 0 else 0
|
||||||
|
|
||||||
|
# Determine duty cycle / power level recommendations
|
||||||
|
power_level = 100
|
||||||
|
if state.initial_temp_c < 0: # Frozen food requires defrost cycle to prevent edge-cooking
|
||||||
|
power_level = 50
|
||||||
|
total_seconds *= 1.4
|
||||||
|
|
||||||
|
return {
|
||||||
|
"cook_time_seconds": round(total_seconds),
|
||||||
|
"recommended_power_level_pct": power_level,
|
||||||
|
"estimated_specific_heat": round(cp, 2),
|
||||||
|
"energy_joules": round(required_joules)
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
Flask==3.0.2
|
Flask==3.0.2
|
||||||
pymongo==4.6.1
|
pymongo==4.6.1
|
||||||
gunicorn==21.2.0
|
gunicorn==21.2.0
|
||||||
|
opencv-python-headless
|
||||||
Reference in New Issue
Block a user