├── .gitignore
├── results
├── object_counts_per_interval.csv
├── objects_over_time_d.png
├── objects_by_class_over_time.png
├── object_counts_by_class_per_interval.csv
└── predictions.csv
├── requirements.txt
├── LICENSE
├── README.md
└── main.py
/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/results/object_counts_per_interval.csv:
--------------------------------------------------------------------------------
1 | minutes,0
2 | 0:00,21
3 | 5:00,29
4 | 10:00,19
5 | 15:00,39
6 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | matplotlib==3.7.1
2 | opencv_python==4.7.0.72
3 | pandas==2.0.2
4 | Requests==2.31.0
5 |
--------------------------------------------------------------------------------
/results/objects_over_time_d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboflow/inference-dashboard-example/HEAD/results/objects_over_time_d.png
--------------------------------------------------------------------------------
/results/objects_by_class_over_time.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboflow/inference-dashboard-example/HEAD/results/objects_by_class_over_time.png
--------------------------------------------------------------------------------
/results/object_counts_by_class_per_interval.csv:
--------------------------------------------------------------------------------
1 | minutes,AB Bohne,BM Bohne,BM Gemahlen,BW Bohne,BW Gemahlen,Barista CB,Barista CC,CC Vollmundig 36Pads,CFino Bohne,Colombia BBBohne,Colombia BBGemahlen,Discount Price,Empty Shelf,Espresso Aromatisch,Espresso Kraftig,FM 36Pads,FM Bohne,LG Gemahlen,Price,SM Gemahlen,Simo EsElegant,Simo EsKraft,Simo KaffeeBW,Simo KaffeeKraft,Simo KaffeeMild
2 | 0:00,0,0,1,0,2,1,1,2,0,0,0,0,0,2,0,1,0,1,0,3,1,0,0,3,3
3 | 5:00,0,0,1,0,1,0,2,1,0,0,0,2,2,2,0,1,0,0,7,3,1,1,1,1,3
4 | 10:00,0,0,1,1,2,0,0,1,0,0,0,0,1,0,0,1,0,1,6,2,0,0,0,2,1
5 | 15:00,1,1,1,2,2,1,0,3,1,2,6,0,0,2,3,1,1,1,0,4,0,0,0,5,2
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Roboflow
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🤖 Video Inference Dashboard Example
2 | Roboflow's inference server to analyze video streams. This project extracts insights from video frames at defined intervals and generates informative visualizations and CSV outputs.
3 |
4 | ## 📦 Use Case: Smart Inventory Monitoring
5 |
6 | Factories & stores can:
7 |
8 | - Save time
9 | - Count items at intervals, avoiding stockouts.
10 | - Restock efficiently using data.
11 | - Enhance operations
12 |
13 | ## 📈 Result
14 |
15 | This is counting products on shelf, every 5 minutes, categorically and in total.
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | 
27 |
28 |
29 |
30 | 
31 |
32 | ## ⚙️ Requirements
33 |
34 | Make sure you have docker installed. Learn more about building, pulling, and running the Roboflow Inference Docker Image in our [documentation](https://roboflow.github.io/inference/quickstart/docker/).
35 |
36 | ## 🔍 Installation
37 |
38 | ### **⌗ 1 Start inference server**
39 | x86 CPU:
40 |
41 | ```bash
42 | docker run --net=host roboflow/roboflow-inference-server-cpu:latest
43 | ```
44 | NVIDIA GPU
45 | ```bash
46 | docker run --network=host --gpus=all roboflow/roboflow-inference-server-gpu:latest
47 | ```
48 |
49 | ### **⌗ 2 Setup and Run**
50 | ```python
51 | git clone https://github.com/roboflow/inference-dashboard-example.git
52 | cd inference-dashboard-example
53 | pip install -r requirements.txt
54 | ```
55 |
56 | ```python
57 | python main.py --dataset_id [YOUR_DATASET_ID] --api_key [YOUR_API_KEY] --video_path [PATH_TO_VIDEO] --interval_minutes [INTERVAL_IN_MINUTES]
58 |
59 | """
60 | --dataset_id: Your dataset name on Roboflow.
61 | --version_id: The version ID for inference (default: 1).
62 | --api_key: Your API key on Roboflow.
63 | --video_path: Path to the video file for analysis.
64 | --interval_minutes: Interval in minutes to extract predictions (default: 1).
65 | """
66 | ```
67 |
68 | ## 🦾 Feedback & Contributions
69 |
70 | Feel free to open an issue, submit a PR, or share your feedback. All contributions are welcome!
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import cv2
2 | import pandas as pd
3 | import pickle
4 | import requests
5 | import matplotlib.pyplot as plt
6 | import argparse
7 | import os
8 |
9 |
10 | def parse_args():
11 | parser = argparse.ArgumentParser(description="Process video and extract insights")
12 | parser.add_argument("--dataset_id", help="Dataset ID (required)")
13 | parser.add_argument("--version_id", default="1", help="Version ID (default: 1)")
14 | parser.add_argument("--api_key", help="API key (required)")
15 | parser.add_argument("--video_path", help="Path to the video (required)")
16 | parser.add_argument("--interval_minutes", type=int, default=1, help="Interval in seconds (default: 60)")
17 | return parser.parse_args()
18 |
19 |
20 | def extract_frames(video_path, interval_minutes):
21 | cap = cv2.VideoCapture(video_path)
22 | frames = []
23 | timestamps = []
24 | fps = int(cap.get(cv2.CAP_PROP_FPS))
25 | frame_count = 0
26 |
27 | while cap.isOpened():
28 | ret, frame = cap.read()
29 | if not ret:
30 | break
31 | if frame_count % (fps * interval_minutes) == 0:
32 | frames.append(frame)
33 | timestamps.append(frame_count / fps)
34 | frame_count += 1
35 | cap.release()
36 | return frames, timestamps
37 |
38 |
39 | def fetch_predictions(base_url, frames, timestamps, dataset_id, version_id, api_key, confidence=0.5):
40 | headers = {"Content-Type": "application/x-www-form-urlencoded"}
41 | df_rows = []
42 | for idx, frame in enumerate(frames):
43 | numpy_data = pickle.dumps(frame)
44 | res = requests.post(
45 | f"{base_url}/{dataset_id}/{version_id}",
46 | data=numpy_data,
47 | headers=headers,
48 | params={"api_key": api_key, "confidence": confidence, "image_type": "numpy"}
49 | )
50 | predictions = res.json()
51 |
52 | for pred in predictions['predictions']:
53 | time_interval = f"{int(timestamps[idx] // 60)}:{int(timestamps[idx] % 60):02}"
54 | row = {
55 | "timestamp": time_interval,
56 | "time": predictions['time'],
57 | "x": pred["x"],
58 | "y": pred["y"],
59 | "width": pred["width"],
60 | "height": pred["height"],
61 | "pred_confidence": pred["confidence"],
62 | "class": pred["class"]
63 | }
64 | df_rows.append(row)
65 |
66 | df = pd.DataFrame(df_rows)
67 | df['seconds'] = df['timestamp'].str.split(':').apply(lambda x: int(x[0])*60 + int(x[1]))
68 | df = df.sort_values(by="seconds")
69 | return df
70 |
71 | def plot_and_save(data, title, filename, ylabel, stacked=False, legend_title=None, legend_loc=None, legend_bbox=None):
72 | plt.style.use('dark_background')
73 | data.plot(kind='bar', stacked=stacked, figsize=(15,7))
74 | plt.title(title)
75 | plt.ylabel(ylabel)
76 | plt.xlabel('Timestamp (in minutes:seconds)')
77 |
78 | if legend_title:
79 | plt.legend(title=legend_title, loc=legend_loc, bbox_to_anchor=legend_bbox)
80 |
81 | plt.tight_layout()
82 | plt.savefig(filename)
83 |
84 | def main():
85 | args = parse_args()
86 | base_url = "http://localhost:9001"
87 | video_path = args.video_path
88 | dataset_id = args.dataset_id
89 | version_id = args.version_id
90 | api_key = args.api_key
91 | interval_minutes = args.interval_minutes * 60
92 |
93 |
94 | frames, timestamps = extract_frames(video_path, interval_minutes)
95 | df = fetch_predictions(base_url, frames, timestamps, dataset_id, version_id, api_key)
96 |
97 | if not os.path.exists("results"):
98 | os.makedirs("results")
99 |
100 | #saving predictions response to csv
101 | df.to_csv("results/predictions.csv", index=False)
102 |
103 | # Transform timestamps to minutes and group
104 | df['minutes'] = df['timestamp'].str.split(':').apply(lambda x: int(x[0]) * 60 + int(x[1]))
105 | object_counts_per_interval = df.groupby('minutes').size().sort_index()
106 | object_counts_per_interval.index = object_counts_per_interval.index.map(lambda x: f"{x // 60}:{x % 60:02}")
107 | object_counts_per_interval.to_csv("results/object_counts_per_interval.csv")
108 |
109 | # Quick insights
110 | print(f"Total unique objects detected: {df['class'].nunique()}")
111 | print(f"Most frequently detected object: {df['class'].value_counts().idxmax()}")
112 | print(f"Time interval with the most objects detected: {object_counts_per_interval.idxmax()}")
113 | print(f"Time interval with the least objects detected: {object_counts_per_interval.idxmin()}")
114 |
115 | plot_and_save(object_counts_per_interval, 'Number of Objects Detected Over Time', "results/objects_over_time_d.png", 'Number of Objects')
116 |
117 | # Group by timestamp and class, then sort by minutes
118 | objects_by_class_per_interval = df.groupby(['minutes', 'class']).size().unstack(fill_value=0).sort_index()
119 | objects_by_class_per_interval.index = objects_by_class_per_interval.index.map(lambda x: f"{x // 60}:{x % 60:02}")
120 | objects_by_class_per_interval.to_csv("results/object_counts_by_class_per_interval.csv")
121 |
122 | plot_and_save(objects_by_class_per_interval, 'Number of Objects Detected Over Time by Class', "results/objects_by_class_over_time.png", 'Number of Objects', True, "Object Class", "center left", (1, 0.5))
123 |
124 |
125 | if __name__ == "__main__":
126 | main()
127 |
--------------------------------------------------------------------------------
/results/predictions.csv:
--------------------------------------------------------------------------------
1 | timestamp,time,x,y,width,height,pred_confidence,class,seconds
2 | 0:00,0.02328695193864405,295.5,410.0,73.0,46.0,0.9734150767326355,SM Gemahlen,0
3 | 0:00,0.02328695193864405,227.5,126.5,77.0,101.0,0.5063759088516235,Espresso Aromatisch,0
4 | 0:00,0.02328695193864405,286.0,331.0,76.0,48.0,0.5837204456329346,BW Gemahlen,0
5 | 0:00,0.02328695193864405,252.0,235.5,30.0,65.0,0.6269301772117615,Simo EsElegant,0
6 | 0:00,0.02328695193864405,225.0,235.5,30.0,65.0,0.7168950438499451,Simo KaffeeMild,0
7 | 0:00,0.02328695193864405,309.0,234.0,30.0,68.0,0.7224994897842407,Simo KaffeeKraft,0
8 | 0:00,0.02328695193864405,148.0,495.0,68.0,42.0,0.760189414024353,BW Gemahlen,0
9 | 0:00,0.02328695193864405,192.0,402.0,44.0,58.0,0.7835189700126648,CC Vollmundig 36Pads,0
10 | 0:00,0.02328695193864405,148.5,127.5,83.0,105.0,0.8120909333229065,Barista CC,0
11 | 0:00,0.02328695193864405,144.0,237.0,32.0,64.0,0.8398640751838684,Simo KaffeeMild,0
12 | 0:00,0.02328695193864405,80.5,129.0,83.0,102.0,0.6889695525169373,Barista CB,0
13 | 0:00,0.02328695193864405,304.5,124.0,77.0,106.0,0.8629286289215088,Espresso Aromatisch,0
14 | 0:00,0.02328695193864405,236.5,404.5,49.0,57.0,0.8730306029319763,CC Vollmundig 36Pads,0
15 | 0:00,0.02328695193864405,293.5,546.5,75.0,37.0,0.8773476481437683,SM Gemahlen,0
16 | 0:00,0.02328695193864405,133.0,331.0,76.0,48.0,0.9221301674842834,BM Gemahlen,0
17 | 0:00,0.02328695193864405,197.0,236.5,30.0,65.0,0.923898458480835,Simo KaffeeKraft,0
18 | 0:00,0.02328695193864405,211.0,330.5,72.0,49.0,0.9258190989494324,LG Gemahlen,0
19 | 0:00,0.02328695193864405,116.5,237.0,31.0,64.0,0.9260269999504089,Simo KaffeeMild,0
20 | 0:00,0.02328695193864405,141.5,400.0,57.0,58.0,0.9351334571838379,FM 36Pads,0
21 | 0:00,0.02328695193864405,170.5,237.0,29.0,64.0,0.9723898768424988,Simo KaffeeKraft,0
22 | 0:00,0.02328695193864405,290.0,506.0,76.0,36.0,0.8612465858459473,SM Gemahlen,0
23 | 5:00,0.01930748496670276,167.0,449.5,64.0,65.0,0.7176361083984375,Empty Shelf,300
24 | 5:00,0.01930748496670276,196.5,331.5,37.0,15.0,0.6675833463668823,Price,300
25 | 5:00,0.01930748496670276,253.5,401.5,37.0,13.0,0.6592211723327637,Price,300
26 | 5:00,0.01930748496670276,224.5,234.0,41.0,14.0,0.6565319895744324,Price,300
27 | 5:00,0.01930748496670276,226.0,177.0,66.0,100.0,0.6547722816467285,Barista CC,300
28 | 5:00,0.01930748496670276,331.5,483.0,35.0,12.0,0.623317301273346,Price,300
29 | 5:00,0.01930748496670276,228.0,488.0,36.0,14.0,0.5418887734413147,Discount Price,300
30 | 5:00,0.01930748496670276,229.0,291.5,28.0,63.0,0.611021876335144,Simo KaffeeMild,300
31 | 5:00,0.01930748496670276,156.0,231.0,46.0,16.0,0.6082651019096375,Price,300
32 | 5:00,0.01930748496670276,359.0,237.5,40.0,15.0,0.5633571147918701,Discount Price,300
33 | 5:00,0.01930748496670276,320.5,604.5,33.0,15.0,0.5268151760101318,Price,300
34 | 5:00,0.01930748496670276,201.0,291.0,28.0,64.0,0.726374089717865,Simo KaffeeMild,300
35 | 5:00,0.01930748496670276,157.5,173.5,71.0,99.0,0.6134111881256104,Barista CC,300
36 | 5:00,0.01930748496670276,356.5,182.5,63.0,93.0,0.7265565395355225,Espresso Aromatisch,300
37 | 5:00,0.01930748496670276,282.0,292.0,26.0,62.0,0.8455964922904968,Simo EsKraft,300
38 | 5:00,0.01930748496670276,157.0,173.5,70.0,99.0,0.7499425411224365,Espresso Aromatisch,300
39 | 5:00,0.01930748496670276,170.5,371.0,79.0,50.0,0.9368743300437927,SM Gemahlen,300
40 | 5:00,0.01930748496670276,308.0,292.0,26.0,62.0,0.9308812022209167,Simo KaffeeBW,300
41 | 5:00,0.01930748496670276,150.5,333.0,37.0,14.0,0.7439377903938293,Price,300
42 | 5:00,0.01930748496670276,252.0,370.0,74.0,50.0,0.8929466009140015,BM Gemahlen,300
43 | 5:00,0.01930748496670276,175.0,585.0,74.0,44.0,0.8909624218940735,BW Gemahlen,300
44 | 5:00,0.01930748496670276,228.0,446.0,56.0,66.0,0.8851510286331177,FM 36Pads,300
45 | 5:00,0.01930748496670276,334.0,291.5,26.0,61.0,0.913595974445343,Simo KaffeeKraft,300
46 | 5:00,0.01930748496670276,253.0,580.0,68.0,42.0,0.8637905716896057,SM Gemahlen,300
47 | 5:00,0.01930748496670276,256.0,535.0,68.0,40.0,0.8416116833686829,SM Gemahlen,300
48 | 5:00,0.01930748496670276,172.0,290.5,30.0,65.0,0.8308530449867249,Simo KaffeeMild,300
49 | 5:00,0.01930748496670276,282.5,444.5,51.0,59.0,0.7668347954750061,CC Vollmundig 36Pads,300
50 | 5:00,0.01930748496670276,323.0,365.5,68.0,53.0,0.7589477896690369,Empty Shelf,300
51 | 5:00,0.01930748496670276,256.5,292.0,27.0,62.0,0.875664472579956,Simo EsElegant,300
52 | 10:00,0.019086454063653946,132.5,187.5,27.0,13.0,0.6754971146583557,Price,600
53 | 10:00,0.019086454063653946,178.5,276.5,11.0,13.0,0.5182544589042664,Price,600
54 | 10:00,0.019086454063653946,147.5,273.0,11.0,12.0,0.5438727140426636,Price,600
55 | 10:00,0.019086454063653946,156.5,488.0,49.0,40.0,0.6187127232551575,BW Gemahlen,600
56 | 10:00,0.019086454063653946,161.0,275.0,10.0,12.0,0.6505646109580994,Price,600
57 | 10:00,0.019086454063653946,201.0,242.5,20.0,59.0,0.6649411916732788,Simo KaffeeMild,600
58 | 10:00,0.019086454063653946,237.0,283.0,10.0,12.0,0.665515661239624,Price,600
59 | 10:00,0.019086454063653946,207.0,466.0,52.0,46.0,0.6719003915786743,SM Gemahlen,600
60 | 10:00,0.019086454063653946,130.5,271.5,13.0,11.0,0.6970708966255188,Price,600
61 | 10:00,0.019086454063653946,150.0,374.0,44.0,68.0,0.8394197821617126,BW Bohne,600
62 | 10:00,0.019086454063653946,183.0,240.5,16.0,57.0,0.7613373398780823,Empty Shelf,600
63 | 10:00,0.019086454063653946,178.5,138.5,53.0,87.0,0.7642428874969482,FM 36Pads,600
64 | 10:00,0.019086454063653946,276.0,403.5,44.0,57.0,0.7769483327865601,CC Vollmundig 36Pads,600
65 | 10:00,0.019086454063653946,221.5,244.5,21.0,61.0,0.8210639953613281,Simo KaffeeKraft,600
66 | 10:00,0.019086454063653946,160.5,449.0,47.0,42.0,0.8282526135444641,BW Gemahlen,600
67 | 10:00,0.019086454063653946,153.0,310.5,48.0,45.0,0.8882850408554077,SM Gemahlen,600
68 | 10:00,0.019086454063653946,263.5,324.5,57.0,47.0,0.9415959715843201,LG Gemahlen,600
69 | 10:00,0.019086454063653946,202.5,317.0,53.0,46.0,0.9598554968833923,BM Gemahlen,600
70 | 10:00,0.019086454063653946,129.0,236.5,18.0,55.0,0.7537198662757874,Simo KaffeeKraft,600
71 | 15:00,0.02036092197522521,417.0,498.0,56.0,32.0,0.7214412689208984,SM Gemahlen,900
72 | 15:00,0.02036092197522521,387.0,135.0,50.0,74.0,0.7167350649833679,Espresso Kraftig,900
73 | 15:00,0.02036092197522521,426.0,290.0,40.0,46.0,0.7129066586494446,BM Bohne,900
74 | 15:00,0.02036092197522521,448.0,351.0,20.0,46.0,0.7053572535514832,Simo KaffeeKraft,900
75 | 15:00,0.02036092197522521,491.0,351.5,22.0,47.0,0.6946369409561157,Simo KaffeeKraft,900
76 | 15:00,0.02036092197522521,175.0,132.5,58.0,79.0,0.6903895139694214,Barista CB,900
77 | 15:00,0.02036092197522521,444.5,135.5,59.0,73.0,0.6891908049583435,Espresso Aromatisch,900
78 | 15:00,0.02036092197522521,258.5,405.5,37.0,41.0,0.5880886912345886,CC Vollmundig 36Pads,900
79 | 15:00,0.02036092197522521,192.0,495.0,56.0,34.0,0.6340433359146118,Colombia BBGemahlen,900
80 | 15:00,0.02036092197522521,228.0,134.0,48.0,74.0,0.6322517991065979,Espresso Kraftig,900
81 | 15:00,0.02036092197522521,305.0,405.0,34.0,40.0,0.7298151254653931,Colombia BBBohne,900
82 | 15:00,0.02036092197522521,360.5,406.5,37.0,41.0,0.5838360786437988,Colombia BBBohne,900
83 | 15:00,0.02036092197522521,428.5,350.0,21.0,46.0,0.580676257610321,Simo KaffeeKraft,900
84 | 15:00,0.02036092197522521,222.5,404.5,37.0,41.0,0.5801262855529785,CC Vollmundig 36Pads,900
85 | 15:00,0.02036092197522521,431.0,406.5,34.0,39.0,0.5607403516769409,BW Bohne,900
86 | 15:00,0.02036092197522521,366.0,352.0,20.0,44.0,0.5419747233390808,Simo KaffeeKraft,900
87 | 15:00,0.02036092197522521,227.5,294.0,39.0,44.0,0.6355602145195007,AB Bohne,900
88 | 15:00,0.02036092197522521,277.0,350.5,42.0,47.0,0.735442578792572,CC Vollmundig 36Pads,900
89 | 15:00,0.02036092197522521,334.5,132.5,55.0,81.0,0.7932676076889038,Espresso Kraftig,900
90 | 15:00,0.02036092197522521,396.5,405.0,35.0,42.0,0.7885718941688538,CFino Bohne,900
91 | 15:00,0.02036092197522521,407.0,350.0,20.0,46.0,0.5279561281204224,Simo KaffeeMild,900
92 | 15:00,0.02036092197522521,473.5,499.5,57.0,33.0,0.9718591570854187,BW Gemahlen,900
93 | 15:00,0.02036092197522521,477.0,294.5,62.0,37.0,0.9579463601112366,BM Gemahlen,900
94 | 15:00,0.02036092197522521,471.5,533.0,57.0,30.0,0.9537693858146667,BW Gemahlen,900
95 | 15:00,0.02036092197522521,376.0,294.0,58.0,40.0,0.9221926927566528,LG Gemahlen,900
96 | 15:00,0.02036092197522521,362.0,498.5,56.0,29.0,0.9153338074684143,SM Gemahlen,900
97 | 15:00,0.02036092197522521,469.5,351.5,21.0,47.0,0.9023809432983398,Simo KaffeeKraft,900
98 | 15:00,0.02036092197522521,248.0,496.0,56.0,32.0,0.896979033946991,Colombia BBGemahlen,900
99 | 15:00,0.02036092197522521,386.0,351.0,20.0,44.0,0.8924118280410767,Simo KaffeeMild,900
100 | 15:00,0.02036092197522521,470.0,406.0,40.0,44.0,0.8901169300079346,BW Bohne,900
101 | 15:00,0.02036092197522521,360.5,529.0,55.0,32.0,0.8545306921005249,SM Gemahlen,900
102 | 15:00,0.02036092197522521,304.0,497.5,56.0,33.0,0.8462991118431091,Colombia BBGemahlen,900
103 | 15:00,0.02036092197522521,232.5,351.5,45.0,47.0,0.8362724781036377,FM 36Pads,900
104 | 15:00,0.02036092197522521,505.0,223.0,56.0,68.0,0.8173805475234985,FM Bohne,900
105 | 15:00,0.02036092197522521,248.0,527.0,54.0,32.0,0.8024320602416992,Colombia BBGemahlen,900
106 | 15:00,0.02036092197522521,248.0,464.0,56.0,32.0,0.7905616164207458,Colombia BBGemahlen,900
107 | 15:00,0.02036092197522521,362.0,464.0,58.0,26.0,0.7885833382606506,SM Gemahlen,900
108 | 15:00,0.02036092197522521,503.5,133.5,59.0,79.0,0.7408873438835144,Espresso Aromatisch,900
109 | 15:00,0.02036092197522521,304.5,465.5,57.0,33.0,0.5043758153915405,Colombia BBGemahlen,900
110 |
--------------------------------------------------------------------------------