ksvmuralidhar commited on
Commit
530f5ca
1 Parent(s): 9c21c9e

Upload 15 files

Browse files
Dockerfile ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+ WORKDIR /webapp
3
+ COPY . .
4
+ RUN pip install --upgrade pip
5
+ RUN pip install --no-cache-dir -r requirements.txt
6
+ CMD ["gunicorn", "-b", "0.0.0.0:7860", "--timeout", "120", "app:app"]
7
+ EXPOSE 7860
app.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from flask import Flask, render_template, request
3
+ from flask_cors import cross_origin, CORS
4
+ import tensorflow.lite as lite
5
+ from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
6
+ from utils.make_upload_dir import make_upload_dir
7
+ from tensorflow.keras.utils import load_img, save_img, img_to_array
8
+ from numpy import array, round
9
+ from utils.delete_file import delete_file
10
+ from requests import get
11
+
12
+
13
+ app = Flask(__name__, template_folder='templates', static_folder='static')
14
+ CORS(app)
15
+
16
+ CLASS_INDICES = {'Bean': 0,
17
+ 'Bitter_Gourd': 1,
18
+ 'Bottle_Gourd': 2,
19
+ 'Brinjal': 3,
20
+ 'Broccoli': 4,
21
+ 'Cabbage': 5,
22
+ 'Capsicum': 6,
23
+ 'Carrot': 7,
24
+ 'Cauliflower': 8,
25
+ 'Cucumber': 9,
26
+ 'Papaya': 10,
27
+ 'Potato': 11,
28
+ 'Pumpkin': 12,
29
+ 'Radish': 13,
30
+ 'Tomato': 14}
31
+
32
+ interpreter = lite.Interpreter(model_path=os.path.join("models", "vegetable_classification_model_mnet.tflite"))
33
+
34
+
35
+ def predict(test_image):
36
+ interpreter.allocate_tensors()
37
+
38
+ input_details = interpreter.get_input_details()[0]
39
+ output_details = interpreter.get_output_details()[0]
40
+
41
+ test_image = test_image.astype(input_details["dtype"])
42
+ interpreter.set_tensor(input_details["index"], test_image)
43
+ interpreter.invoke()
44
+ output = interpreter.get_tensor(output_details["index"])[0]
45
+
46
+ prediction = [*CLASS_INDICES.keys()][output.argmax()]
47
+ probability = round(output.max() * 100, 2)
48
+ result = f'{prediction} ({probability}%)'
49
+ return result
50
+
51
+
52
+ @app.route("/")
53
+ @cross_origin()
54
+ def index():
55
+ """
56
+ displays the index.html page
57
+ """
58
+ display_image = os.path.join("static", "white.png")
59
+ delete_file(os.path.join('.', 'static', 'uploads'))
60
+ delete_file(os.path.join('.', 'static', 'output', 'display.jpg'))
61
+ return render_template("index.html", display_image=display_image)
62
+
63
+
64
+ @app.route("/", methods=["POST"])
65
+ @cross_origin()
66
+ def file_prediction():
67
+ upload_file_path = ""
68
+ result = ''
69
+ error = ""
70
+ try:
71
+ upload_file_path = os.path.join('.', 'static', 'uploads')
72
+ make_upload_dir(upload_file_path)
73
+ upload_filename = "input.jpg"
74
+ upload_file_path = os.path.join(upload_file_path, upload_filename)
75
+
76
+ file_url = request.form['fileinput']
77
+ headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'}
78
+ r = get(file_url, headers=headers)
79
+ with open(upload_file_path, "wb") as file:
80
+ file.write(r.content)
81
+
82
+ test_image = load_img(upload_file_path, color_mode="rgb", target_size=(224, 224))
83
+ test_image = img_to_array(test_image)
84
+ test_image = preprocess_input(test_image)
85
+ test_image = array([test_image])
86
+
87
+ display_image = os.path.join('.', 'static', 'output', 'display.jpg')
88
+ save_img(path=display_image, x=test_image[0])
89
+
90
+ result = predict(test_image)
91
+ delete_file(upload_file_path)
92
+
93
+ except Exception as e:
94
+ # raise
95
+ result = ''
96
+ error = e
97
+ display_image = os.path.join("static", "white.png")
98
+ delete_file(upload_file_path)
99
+
100
+ return render_template("index.html", result=result, error=error, display_image=display_image)
101
+
102
+
103
+ if __name__ == "__main__":
104
+ app.run(host="0.0.0.0", port=5002)
models/vegetable_classification_model_mnet.tflite ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:646ea12cef64a1b4bca597811ec7c21b6f7da0eb6ff4d567207e165184e2dffb
3
+ size 21413256
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ tensorflow-cpu==2.12.0
2
+ numpy==1.22.4
3
+ flask==2.2.2
4
+ flask_cors==3.0.10
5
+ gunicorn==20.1.0
6
+ Pillow==9.5.0
7
+ requests==2.30.0
static/output/display.jpg ADDED
static/styles.css ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ html, body {
2
+ min-height: 100%;
3
+ }
4
+ body, div, form, input, select, p {
5
+ padding: 0;
6
+ margin: 0;
7
+ outline: none;
8
+ font-family: Roboto, Arial, sans-serif;
9
+ font-size: 14px;
10
+ color: #666;
11
+ line-height: 22px;
12
+ }
13
+ h1 {
14
+ position: absolute;
15
+ margin: 0;
16
+ font-size: 28px;
17
+ color: #fff;
18
+ z-index: 2;
19
+ }
20
+ h2 {
21
+ font-weight: 400;
22
+ }
23
+ .testbox {
24
+ display: flex;
25
+ justify-content: center;
26
+ align-items: center;
27
+ height: inherit;
28
+ padding: 20px;
29
+ }
30
+ .testbox1 {
31
+ display: flex;
32
+ justify-content: center;
33
+ align-items: center;
34
+ height: inherit;
35
+ padding: 5px;
36
+ }
37
+ form {
38
+ width: 30%;
39
+ padding: 20px;
40
+ border-radius: 6px;
41
+ background: #fff;
42
+ box-shadow: 0 0 20px 0 #095484;
43
+ }
44
+ .banner {
45
+ position: relative;
46
+ height: 80px;
47
+ background-size: cover;
48
+ display: flex;
49
+ justify-content: center;
50
+ align-items: center;
51
+ text-align: center;
52
+ }
53
+
54
+ .banner::after {
55
+ content: "";
56
+ background-color: rgba(0, 0, 0, 0.4);
57
+ position: absolute;
58
+ width: 100%;
59
+ height: 100%;
60
+ }
61
+ input, select {
62
+ margin-bottom: 2px;
63
+ border: 1px solid #ccc;
64
+ border-radius: 3px;
65
+ }
66
+ input {
67
+ width: calc(100% - 10px);
68
+ padding: 5px;
69
+ }
70
+ select {
71
+ width: 100%;
72
+ padding: 7px 0;
73
+ background: transparent;
74
+ }
75
+ .item:hover p, .item:hover i, .question:hover p, .question label:hover, input:hover::placeholder, a {
76
+ color: #095484;
77
+ }
78
+ .item input:hover, .item select:hover {
79
+ border: 1px solid transparent;
80
+ box-shadow: 0 0 6px 0 #095484;
81
+ color: #095484;
82
+ }
83
+ .item {
84
+ position: relative;
85
+ margin: 10px 0;
86
+ }
87
+
88
+
89
+ .btn-block {
90
+ margin-top: 10px;
91
+ text-align: center;
92
+ }
93
+ button {
94
+ width: 150px;
95
+ padding: 10px;
96
+ border: none;
97
+ border-radius: 5px;
98
+ background: #095484;
99
+ font-size: 16px;
100
+ color: #fff;
101
+ cursor: pointer;
102
+ }
103
+ button:hover {
104
+ background: #0666a3;
105
+ }
106
+ ul {
107
+ list-style-type: none;
108
+ margin: 0;
109
+ padding: 0;
110
+ overflow: hidden;
111
+ background-color: #333;
112
+ }
113
+
114
+ li {
115
+ float: left;
116
+ }
117
+
118
+ li a {
119
+ display: block;
120
+ color: white;
121
+ text-align: center;
122
+ padding: 14px 16px;
123
+ text-decoration: none;
124
+ }
125
+
126
+ /* Change the link color to #111 (black) on hover */
127
+ li a:hover {
128
+ background-color: #111;
129
+
130
+ li {
131
+ border-right: 1px solid #bbb;
132
+ }
133
+
134
+ li:last-child {
135
+ border-right: none;
136
+ }
static/uploads/1283.jpg ADDED
static/white.png ADDED
templates/index.html ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--sourced and modified from https://www.w3docs.com/learn-html/html-form-templates.html -->
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <title>Vegetable Classifier</title>
6
+ <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
7
+ <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
8
+ <link rel="stylesheet" href="static/styles.css">
9
+ </head>
10
+ <body>
11
+ <div class="testbox">
12
+ <form action="/" method="POST" enctype="multipart/form-data">
13
+ <div class="banner">
14
+ <h1>Vegetable Classifier</h1>
15
+ </div>
16
+ <h5>Detectable Vegetables: Broad Bean, Bitter Gourd, Bottle Gourd, Green Round Brinjal, Broccoli, Cabbage, Capsicum, Carrot,
17
+ Cauliflower, Cucumber, Raw Papaya, Potato, Green Pumpkin, Radish, Tomato</h5>
18
+ <h5>The model is trained on <a href="https://www.kaggle.com/datasets/misrakahmed/vegetable-image-dataset" target="_blank">images</a> clicked using a mobile phone camera.</h5>
19
+ <p>Please paste the image URL of a vegetable<sup style="color: red;">*</sup></p>
20
+ <div class="item">
21
+
22
+ <input type="text" name="fileinput" id="fileinput" autocomplete="off" required/>
23
+ </div>
24
+
25
+
26
+ <div class="btn-block">
27
+ <button type="submit" href="/file_input">Submit</button>
28
+ </div>
29
+ <div class="item">
30
+ <p style="color: red;">{{error}}</p>
31
+ </div>
32
+ </form>
33
+
34
+ </div>
35
+ <div class="testbox1">
36
+ {{result}}
37
+ </div>
38
+ <div class="testbox1">
39
+ <img src={{display_image}} />
40
+ </div>
41
+
42
+
43
+ </body>
44
+ </html>
utils/__init__.py ADDED
File without changes
utils/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (160 Bytes). View file
 
utils/__pycache__/delete_file.cpython-310.pyc ADDED
Binary file (425 Bytes). View file
 
utils/__pycache__/make_upload_dir.cpython-310.pyc ADDED
Binary file (461 Bytes). View file
 
utils/delete_file.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from os import path
2
+ from shutil import rmtree
3
+
4
+
5
+ def delete_file(path_: str):
6
+ if path.exists(path_):
7
+ rmtree(path=path_, ignore_errors=True)
utils/make_upload_dir.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from os import path, makedirs
2
+ from shutil import rmtree
3
+
4
+
5
+ def make_upload_dir(path_: str):
6
+ if path.exists(path_):
7
+ rmtree(path=path_, ignore_errors=True)
8
+ makedirs(path_)