Pawel_Mar commited on
Commit
49ae8dc
·
1 Parent(s): af51f55

initial working app

Browse files
Files changed (3) hide show
  1. .gitignore +189 -0
  2. app.py +194 -0
  3. requirements.txt +6 -0
.gitignore ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Created by .ignore support plugin (hsz.mobi)
2
+ ### Python template
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ env/
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .coverage
43
+ .coverage.*
44
+ .cache
45
+ nosetests.xml
46
+ coverage.xml
47
+ *,cover
48
+ .hypothesis/
49
+
50
+ # Translations
51
+ *.mo
52
+ *.pot
53
+
54
+ # Django stuff:
55
+ *.log
56
+ local_settings.py
57
+
58
+ # Flask stuff:
59
+ instance/
60
+ .webassets-cache
61
+
62
+ # Scrapy stuff:
63
+ .scrapy
64
+
65
+ # Sphinx documentation
66
+ docs/_build/
67
+
68
+ # PyBuilder
69
+ target/
70
+
71
+ # IPython Notebook
72
+ .ipynb_checkpoints
73
+
74
+ # pyenv
75
+ .python-version
76
+
77
+ # celery beat schedule file
78
+ celerybeat-schedule
79
+
80
+ # dotenv
81
+ .env
82
+
83
+ # virtualenv
84
+ venv/
85
+ ENV/
86
+
87
+ # Spyder project settings
88
+ .spyderproject
89
+
90
+ # Rope project settings
91
+ .ropeproject
92
+ ### VirtualEnv template
93
+ # Virtualenv
94
+ # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
95
+ [Bb]in
96
+ [Ii]nclude
97
+ [Ll]ib
98
+ [Ll]ib64
99
+ [Ll]ocal
100
+ [Ss]cripts
101
+ pyvenv.cfg
102
+ .venv
103
+ pip-selfcheck.json
104
+
105
+ ### JetBrains template
106
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
107
+ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
108
+
109
+ # User-specific stuff
110
+ .idea/**/workspace.xml
111
+ .idea/**/tasks.xml
112
+ .idea/**/usage.statistics.xml
113
+ .idea/**/dictionaries
114
+ .idea/**/shelf
115
+
116
+ # AWS User-specific
117
+ .idea/**/aws.xml
118
+
119
+ # Generated files
120
+ .idea/**/contentModel.xml
121
+
122
+ # Sensitive or high-churn files
123
+ .idea/**/dataSources/
124
+ .idea/**/dataSources.ids
125
+ .idea/**/dataSources.local.xml
126
+ .idea/**/sqlDataSources.xml
127
+ .idea/**/dynamic.xml
128
+ .idea/**/uiDesigner.xml
129
+ .idea/**/dbnavigator.xml
130
+
131
+ # Gradle
132
+ .idea/**/gradle.xml
133
+ .idea/**/libraries
134
+
135
+ # Gradle and Maven with auto-import
136
+ # When using Gradle or Maven with auto-import, you should exclude module files,
137
+ # since they will be recreated, and may cause churn. Uncomment if using
138
+ # auto-import.
139
+ # .idea/artifacts
140
+ # .idea/compiler.xml
141
+ # .idea/jarRepositories.xml
142
+ # .idea/modules.xml
143
+ # .idea/*.iml
144
+ # .idea/modules
145
+ # *.iml
146
+ # *.ipr
147
+
148
+ # CMake
149
+ cmake-build-*/
150
+
151
+ # Mongo Explorer plugin
152
+ .idea/**/mongoSettings.xml
153
+
154
+ # File-based project format
155
+ *.iws
156
+
157
+ # IntelliJ
158
+ out/
159
+
160
+ # mpeltonen/sbt-idea plugin
161
+ .idea_modules/
162
+
163
+ # JIRA plugin
164
+ atlassian-ide-plugin.xml
165
+
166
+ # Cursive Clojure plugin
167
+ .idea/replstate.xml
168
+
169
+ # SonarLint plugin
170
+ .idea/sonarlint/
171
+
172
+ # Crashlytics plugin (for Android Studio and IntelliJ)
173
+ com_crashlytics_export_strings.xml
174
+ crashlytics.properties
175
+ crashlytics-build.properties
176
+ fabric.properties
177
+
178
+ # Editor-based Rest Client
179
+ .idea/httpRequests
180
+
181
+ # Android studio 3.1+ serialized cache file
182
+ .idea/caches/build_file_checksums.ser
183
+
184
+ # idea folder, uncomment if you don't need it
185
+ .idea
186
+
187
+ venv
188
+ models
189
+ media-directory/**
app.py ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import cv2
3
+ from PIL import Image
4
+ import pandas as pd
5
+ import streamlit as st
6
+ from ultralytics import YOLO
7
+ from streamlit_image_comparison import image_comparison
8
+ from ultralytics.utils.ops import scale_image
9
+ import numpy as np
10
+
11
+ model = YOLO('models/last.pt')
12
+
13
+ st.title("Image Segmentation with YOLOv8: A Web Integration")
14
+ st.subheader("Implementing for Image Segmentation and Object Detection")
15
+ st.write("Image segmentation is a critical task in computer vision that involves dividing an image into multiple "
16
+ "segments or regions. YOLOv8 is a state-of-the-art deep learning model that can be used for "
17
+ "image segmentation and object detection. In this web app, we will implement an interesting example "
18
+ "using YOLOv8 for image segmentation. We can simply drop an image, View the identified segment "
19
+ "a piece, a whole and the distribution of the identified segments. The essence of this application "
20
+ "is to build a practical understanding and implementation of the powerful and light YOLOv8 "
21
+ "for image segmentation and object detection")
22
+
23
+ url = "https://github.com/AkanimohOD19A/img-segmentation"
24
+ link = f'<a href="{url}">This sample app was heavily based on code shared by Akan Daniel. Huge credits to him.</a>'
25
+ st.markdown(link, unsafe_allow_html=True)
26
+
27
+ def save_uploadedfile(uploadedfile):
28
+ with open(os.path.join("./media-directory/", "captured_picture.jpg"), "wb") as f:
29
+ f.write(uploadedfile.getbuffer())
30
+
31
+ def convert_to_jpg(uploaded_image):
32
+ im = Image.open(uploaded_image)
33
+ if im.mode in ("RGBA", "P"):
34
+ im = im.convert("RGB")
35
+ uploaded_image_path = os.path.join(parent_media_path, "uploaded_image.jpg")
36
+ im.save(uploaded_image_path)
37
+
38
+
39
+ def overlay(image, mask, color, alpha, resize=None):
40
+ """Combines image and its segmentation mask into a single image.
41
+
42
+ Params:
43
+ image: Training image. np.ndarray,
44
+ mask: Segmentation mask. np.ndarray,
45
+ color: Color for segmentation mask rendering. tuple[int, int, int] = (255, 0, 0)
46
+ alpha: Segmentation mask's transparency. float = 0.5,
47
+ resize: If provided, both image and its mask are resized before blending them together.
48
+ tuple[int, int] = (1024, 1024))
49
+
50
+ Returns:
51
+ image_combined: The combined image. np.ndarray
52
+
53
+ """
54
+ # color = color[::-1]
55
+ colored_mask = np.expand_dims(mask, 0).repeat(3, axis=0)
56
+ colored_mask = np.moveaxis(colored_mask, 0, -1)
57
+ masked = np.ma.MaskedArray(image, mask=colored_mask, fill_value=color)
58
+ image_overlay = masked.filled()
59
+
60
+ if resize is not None:
61
+ image = cv2.resize(image.transpose(1, 2, 0), resize)
62
+ image_overlay = cv2.resize(image_overlay.transpose(1, 2, 0), resize)
63
+
64
+ image_combined = cv2.addWeighted(image, 1 - alpha, image_overlay, alpha, 0)
65
+
66
+ return image_combined
67
+
68
+ st.divider()
69
+
70
+ st.markdown('')
71
+ st.markdown('##### Segmented Pieces')
72
+
73
+ ## Placeholder Image
74
+ parent_media_path = "media-directory"
75
+ img_file = './media-directory/example_input.png'
76
+
77
+ ## Application States
78
+ APPLICATION_MODE = st.sidebar.selectbox("Our Options",
79
+ ["Take Picture", "Upload Picture"]
80
+ )
81
+
82
+ ## captured_picture Image
83
+ if APPLICATION_MODE == "Take Picture":
84
+ st.sidebar.write(
85
+ """
86
+ A computer aided application that segments your input image, built on
87
+ the powerful YOLOv8 object detection algorithm developed by *ultralytics*.
88
+
89
+ Simply take a captured_picture and it gets segmentated in real time.
90
+ """
91
+ )
92
+ picture = st.camera_input("Take a picture")
93
+ st.markdown('')
94
+ if picture:
95
+ st.sidebar.divider()
96
+ st.sidebar.image(picture, caption="captured_picture")
97
+ if st.button("Segment!"):
98
+ ## Function to save image
99
+ save_uploadedfile(picture)
100
+ st.sidebar.success("Saved File")
101
+ captured_picture_img = os.path.join(parent_media_path, "/captured_picture.jpg")
102
+ st.write("Click on **Clear photo** to retake picture")
103
+ img_file = './media-directory/captured_picture.jpg'
104
+ st.divider()
105
+
106
+ elif APPLICATION_MODE == "Upload Picture":
107
+ st.sidebar.write(
108
+ """
109
+ A computer aided application that segments your input image, built on
110
+ the powerful YOLOv8 object detection algorithm developed by *ultralytics*.
111
+
112
+ Simply drop your image and it gets segmentated in real time.
113
+ """
114
+ )
115
+ st.sidebar.divider()
116
+ # uploaded_file = st.sidebar.file_uploader("Upload your Image here", type=['png', 'jpeg', 'jpg'])
117
+ uploaded_file = st.sidebar.file_uploader("Drop a JPG/PNG file", accept_multiple_files=False, type=['jpg', 'png'])
118
+ if uploaded_file is not None and uploaded_file.type != ".jpg":
119
+ convert_to_jpg(uploaded_file)
120
+ if uploaded_file is not None:
121
+ file_details = {"FileName": uploaded_file.name, "FileType": uploaded_file.type}
122
+ new_file_name = "uploaded_image.jpg"
123
+ with open(os.path.join(parent_media_path, new_file_name), "wb") as f:
124
+ f.write(uploaded_file.getbuffer())
125
+ img_file = os.path.join(parent_media_path, new_file_name)
126
+ st.sidebar.success("File saved successfully")
127
+ print(f"File saved successfully to {os.path.abspath(os.path.join(parent_media_path, new_file_name))}")
128
+ else:
129
+ st.sidebar.write("You are using a placeholder image, Upload your Image (.jpg for now) to explore")
130
+
131
+ # def make_segmentation(img_file):
132
+ results = model(img_file)
133
+ img = cv2.imread(img_file)
134
+ names_list = []
135
+ for result in results:
136
+ boxes = result.boxes.cpu().numpy()
137
+ # segmentation
138
+ masks = result.masks.data.cpu().numpy() # masks, (N, H, W)
139
+ h, w, _ = img.shape
140
+
141
+ numCols = len(masks)
142
+ if numCols > 0:
143
+ cols = st.columns(numCols)
144
+ else:
145
+ print(f"Number of Boxes found: {numCols}")
146
+ st.warning("Unable to id Distinct items - Please retry with a clearer Image")
147
+ for mask in masks:
148
+ mask = cv2.resize(mask, (w, h))
149
+ img = overlay(img, mask, color=(0, 255, 0), alpha=0.3)
150
+ # st.image(rect)
151
+ # render image-comparison
152
+
153
+ st.markdown('')
154
+ st.markdown('##### Slider of Uploaded Image and Segments')
155
+ image_comparison(
156
+ img1=img_file,
157
+ img2=img,
158
+ label1="Actual Image",
159
+ label2="Segmented Image",
160
+ width=700,
161
+ starting_position=50,
162
+ show_labels=True,
163
+ make_responsive=True,
164
+ in_memory=True
165
+ )
166
+ # for i, box in enumerate(boxes):
167
+ # r = box.xyxy[0].astype(int)
168
+ # crop = img[r[1]:r[3], r[0]:r[2]]
169
+ # predicted_name = result.names[int(box.cls[0])]
170
+ # names_list.append(predicted_name)
171
+ # with cols[i]:
172
+ # st.write(str(predicted_name) + ".jpg")
173
+ # st.image(crop)
174
+
175
+ st.sidebar.divider()
176
+ st.sidebar.markdown('')
177
+ st.sidebar.markdown('#### Distribution of identified items')
178
+
179
+ # Boolean to resize the dataframe, stored as a session state variable
180
+ st.sidebar.checkbox("Use container width", value=False, key="use_container_width")
181
+ if len(names_list) > 0:
182
+ df_x = pd.DataFrame(names_list)
183
+ summary_table = df_x[0].value_counts().rename_axis('unique_values').reset_index(name='counts')
184
+ st.sidebar.dataframe(summary_table, use_container_width=st.session_state.use_container_width)
185
+ else:
186
+ st.sidebar.warning("Unable to id Distinct items - Please retry with a clearer Image")
187
+
188
+ st.markdown('')
189
+ st.markdown('')
190
+ st.markdown('')
191
+ st.markdown('')
192
+ st.markdown('')
193
+ st.markdown('')
194
+ st.sidebar.divider()
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ opencv-python-headless
2
+ streamlit-image-comparison
3
+ pandas
4
+ ultralytics
5
+ streamlit
6
+ Pillow