diff --git a/Pipfile b/Pipfile
index ec2dc07..54251d6 100644
--- a/Pipfile
+++ b/Pipfile
@@ -14,6 +14,7 @@ matplotlib = "*"
plotly = "*"
pandas = "*"
scipy = "==1.8.1"
+scikit-image = "*"
[dev-packages]
diff --git a/Pipfile.lock b/Pipfile.lock
index 0b9eb4b..7283513 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "3428842daebc7c8a255790fde5231377c05479a39d5ce2977f043e58c7c80826"
+ "sha256": "4ce52e44137325bfa984f7d78467dce4463d471bfc344ecd116c2beb2af52d60"
},
"pipfile-spec": 6,
"requires": {
@@ -131,6 +131,14 @@
"index": "pypi",
"version": "==20.1.0"
},
+ "imageio": {
+ "hashes": [
+ "sha256:9bdafe9c5a3d336a187f3f554f3e30bcdbf8a1d7d46f0e4d94e4a535adfb64c7",
+ "sha256:db7010cd10712518819a4187baf61b05988361ea20c23e829918727b27acb977"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==2.22.2"
+ },
"itsdangerous": {
"hashes": [
"sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
@@ -348,6 +356,14 @@
"index": "pypi",
"version": "==3.6.1"
},
+ "networkx": {
+ "hashes": [
+ "sha256:15cdf7f7c157637107ea690cabbc488018f8256fa28242aed0fb24c93c03a06d",
+ "sha256:815383fd52ece0a7024b5fd8408cc13a389ea350cd912178b82eed8b96f82cd3"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==2.8.7"
+ },
"numba": {
"hashes": [
"sha256:0744cf4214ed795eb2df3ed1635d77a6ffcbd990a66a06125548b5fb8ee46323",
@@ -413,7 +429,7 @@
"sha256:f2f390aa4da44454db40a1f0201401f9036e8d578a25f01a6e237cea238337ef",
"sha256:f76025acc8e2114bb664294a07ede0727aa75d63a06d2fae96bf29a81747e4a7"
],
- "markers": "python_version >= '3.10'",
+ "markers": "python_version >= '3.8'",
"version": "==1.23.4"
},
"opencv-python": {
@@ -565,6 +581,37 @@
],
"version": "==2022.5"
},
+ "pywavelets": {
+ "hashes": [
+ "sha256:030670a213ee8fefa56f6387b0c8e7d970c7f7ad6850dc048bd7c89364771b9b",
+ "sha256:058b46434eac4c04dd89aeef6fa39e4b6496a951d78c500b6641fd5b2cc2f9f4",
+ "sha256:231b0e0b1cdc1112f4af3c24eea7bf181c418d37922a67670e9bf6cfa2d544d4",
+ "sha256:23bafd60350b2b868076d976bdd92f950b3944f119b4754b1d7ff22b7acbf6c6",
+ "sha256:3f19327f2129fb7977bc59b966b4974dfd72879c093e44a7287500a7032695de",
+ "sha256:47cac4fa25bed76a45bc781a293c26ac63e8eaae9eb8f9be961758d22b58649c",
+ "sha256:578af438a02a86b70f1975b546f68aaaf38f28fb082a61ceb799816049ed18aa",
+ "sha256:6437af3ddf083118c26d8f97ab43b0724b956c9f958e9ea788659f6a2834ba93",
+ "sha256:64c6bac6204327321db30b775060fbe8e8642316e6bff17f06b9f34936f88875",
+ "sha256:67a0d28a08909f21400cb09ff62ba94c064882ffd9e3a6b27880a111211d59bd",
+ "sha256:71ab30f51ee4470741bb55fc6b197b4a2b612232e30f6ac069106f0156342356",
+ "sha256:7231461d7a8eb3bdc7aa2d97d9f67ea5a9f8902522818e7e2ead9c2b3408eeb1",
+ "sha256:754fa5085768227c4f4a26c1e0c78bc509a266d9ebd0eb69a278be7e3ece943c",
+ "sha256:7ab8d9db0fe549ab2ee0bea61f614e658dd2df419d5b75fba47baa761e95f8f2",
+ "sha256:875d4d620eee655346e3589a16a73790cf9f8917abba062234439b594e706784",
+ "sha256:88aa5449e109d8f5e7f0adef85f7f73b1ab086102865be64421a3a3d02d277f4",
+ "sha256:91d3d393cffa634f0e550d88c0e3f217c96cfb9e32781f2960876f1808d9b45b",
+ "sha256:9cb5ca8d11d3f98e89e65796a2125be98424d22e5ada360a0dbabff659fca0fc",
+ "sha256:ab7da0a17822cd2f6545626946d3b82d1a8e106afc4b50e3387719ba01c7b966",
+ "sha256:ad987748f60418d5f4138db89d82ba0cb49b086e0cbb8fd5c3ed4a814cfb705e",
+ "sha256:d0e56cd7a53aed3cceca91a04d62feb3a0aca6725b1912d29546c26f6ea90426",
+ "sha256:d854411eb5ee9cb4bc5d0e66e3634aeb8f594210f6a1bed96dbed57ec70f181c",
+ "sha256:da7b9c006171be1f9ddb12cc6e0d3d703b95f7f43cb5e2c6f5f15d3233fcf202",
+ "sha256:daf0aa79842b571308d7c31a9c43bc99a30b6328e6aea3f50388cd8f69ba7dbc",
+ "sha256:de7cd61a88a982edfec01ea755b0740e94766e00a1ceceeafef3ed4c85c605cd"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==1.4.1"
+ },
"pyyaml": {
"hashes": [
"sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf",
@@ -611,6 +658,67 @@
"index": "pypi",
"version": "==6.0"
},
+ "scikit-image": {
+ "hashes": [
+ "sha256:03779a7e1736fdf89d83c0ba67d44110496edd736a3bfce61a2b5177a1c8a099",
+ "sha256:0b0a199157ce8487c77de4fde0edc0b42d6d42818881c11f459262351d678b2d",
+ "sha256:19a21a101a20c587a3b611a2cf6f86c35aae9f8d9563279b987e83ee1c9a9790",
+ "sha256:24b5367de1762da6ee126dd8f30cc4e7efda474e0d7d70685433f0e3aa2ec450",
+ "sha256:2a02d1bd0e2b53e36b952bd5fd6118d9ccc3ee51de35705d63d8eb1f2e86adef",
+ "sha256:2f50b923f8099c1045fcde7418d86b206c87e333e43da980f41d8577b9605245",
+ "sha256:32fb88cc36203b99c9672fb972c9ef98635deaa5fc889fe969f3e11c44f22919",
+ "sha256:33dfd463ee6cc509defa279b963829f2230c9e0639ccd3931045be055878eea6",
+ "sha256:3a01372ae4bca223873304b0bff79b9d92446ac6d6177f73d89b45561e2d09d8",
+ "sha256:651de1c2ce1fbee834753b46b8e7d81cb12a5594898babba63ac82b30ddad49d",
+ "sha256:6b6a8f98f2ac9bb73706461fd1dec875f6a5141759ed526850a5a49e90003d19",
+ "sha256:7f9f8a1387afc6c70f2bed007c3854a2d7489f9f7713c242f16f32ee05934bc2",
+ "sha256:84baa3179f3ae983c3a5d81c1e404bc92dcf7daeb41bfe9369badcda3fb22b92",
+ "sha256:8d8917fcf85b987b1f287f823f3a1a7dac38b70aaca759bc0200f3bc292d5ced",
+ "sha256:9439e5294de3f18d6e82ec8eee2c46590231cf9c690da80545e83a0733b7a69e",
+ "sha256:9fb0923a3bfa99457c5e17888f27b3b8a83a3600b4fef317992e7b7234764732",
+ "sha256:a7c3985c68bfe05f7571167ee021d14f5b8d1a4a250c91f0b13be7fb07e6af34",
+ "sha256:a8714348ddd671f819457a797c97d4c672166f093def66d66c3254cbd1d43f83",
+ "sha256:ad5d8000207a264d1a55681a9276e6a739d3f05cf4429004ad00d61d1892235f",
+ "sha256:cc24177de3fdceca5d04807ad9c87d665f0bf01032ed94a9055cd1ed2b3f33e9",
+ "sha256:ce3d2207f253b8eb2c824e30d145a9f07a34a14212d57f3beca9f7e03c383cbe",
+ "sha256:cfbb073f23deb48e0e60c47f8741d8089121d89cc78629ea8c5b51096efc5be7",
+ "sha256:e207c6ce5ce121d7d9b9d2b61b9adca57d1abed112c902d8ffbfdc20fb42c12b",
+ "sha256:fd9dd3994bb6f9f7a35f228323f3c4dc44b3cf2ff15fd72d895216e9333550c6",
+ "sha256:fdf48d9b1f13af69e4e2c78e05067e322e9c8c97463c315cd0ecb47a94e259fc",
+ "sha256:ff3b1025356508d41f4fe48528e509d95f9e4015e90cf158cd58c56dc63e0ac5"
+ ],
+ "index": "pypi",
+ "version": "==0.19.3"
+ },
+ "scipy": {
+ "hashes": [
+ "sha256:02b567e722d62bddd4ac253dafb01ce7ed8742cf8031aea030a41414b86c1125",
+ "sha256:1166514aa3bbf04cb5941027c6e294a000bba0cf00f5cdac6c77f2dad479b434",
+ "sha256:1da52b45ce1a24a4a22db6c157c38b39885a990a566748fc904ec9f03ed8c6ba",
+ "sha256:23b22fbeef3807966ea42d8163322366dd89da9bebdc075da7034cee3a1441ca",
+ "sha256:28d2cab0c6ac5aa131cc5071a3a1d8e1366dad82288d9ec2ca44df78fb50e649",
+ "sha256:2ef0fbc8bcf102c1998c1f16f15befe7cffba90895d6e84861cd6c6a33fb54f6",
+ "sha256:3b69b90c9419884efeffaac2c38376d6ef566e6e730a231e15722b0ab58f0328",
+ "sha256:4b93ec6f4c3c4d041b26b5f179a6aab8f5045423117ae7a45ba9710301d7e462",
+ "sha256:4e53a55f6a4f22de01ffe1d2f016e30adedb67a699a310cdcac312806807ca81",
+ "sha256:6311e3ae9cc75f77c33076cb2794fb0606f14c8f1b1c9ff8ce6005ba2c283621",
+ "sha256:65b77f20202599c51eb2771d11a6b899b97989159b7975e9b5259594f1d35ef4",
+ "sha256:6cc6b33139eb63f30725d5f7fa175763dc2df6a8f38ddf8df971f7c345b652dc",
+ "sha256:70de2f11bf64ca9921fda018864c78af7147025e467ce9f4a11bc877266900a6",
+ "sha256:70ebc84134cf0c504ce6a5f12d6db92cb2a8a53a49437a6bb4edca0bc101f11c",
+ "sha256:83606129247e7610b58d0e1e93d2c5133959e9cf93555d3c27e536892f1ba1f2",
+ "sha256:93d07494a8900d55492401917a119948ed330b8c3f1d700e0b904a578f10ead4",
+ "sha256:9c4e3ae8a716c8b3151e16c05edb1daf4cb4d866caa385e861556aff41300c14",
+ "sha256:9dd4012ac599a1e7eb63c114d1eee1bcfc6dc75a29b589ff0ad0bb3d9412034f",
+ "sha256:9e3fb1b0e896f14a85aa9a28d5f755daaeeb54c897b746df7a55ccb02b340f33",
+ "sha256:a0aa8220b89b2e3748a2836fbfa116194378910f1a6e78e4675a095bcd2c762d",
+ "sha256:d3b3c8924252caaffc54d4a99f1360aeec001e61267595561089f8b5900821bb",
+ "sha256:e013aed00ed776d790be4cb32826adb72799c61e318676172495383ba4570aa4",
+ "sha256:f3e7a8867f307e3359cc0ed2c63b61a1e33a19080f92fe377bc7d49f646f2ec1"
+ ],
+ "index": "pypi",
+ "version": "==1.8.1"
+ },
"setuptools": {
"hashes": [
"sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17",
@@ -635,6 +743,14 @@
"markers": "python_version >= '3.6'",
"version": "==8.1.0"
},
+ "tifffile": {
+ "hashes": [
+ "sha256:50b61ba943b866d191295bc38a00191c9fdab23ece063544c7f1a264e3f6aa8e",
+ "sha256:87f3aee8a0d06b74655269a105de75c1958a24653e1930d523eb516100043503"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==2022.10.10"
+ },
"werkzeug": {
"hashes": [
"sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f",
diff --git a/README.md b/README.md
index c323b8d..cdc9431 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Pyrometry image processing
+# Fire Lab Work
## Interface Screenshots
@@ -8,11 +8,20 @@
## Using the web version
+### Ratio Pyrometry
+
1. Go to [pyro.turtlebasket.ml](https://pyro.turtlebasket.ml).
2. Select an input image.
3. Enter your DSLR camera settings.
4. Click "Generate Heatmap".
+### Projected Object Area
+
+1. Go to [pyro.turtlebasket.ml](https://pyro.turtlebasket.ml).
+2. Navigate to "Object Area".
+3. Select an input image.
+4. Click "Generate Projected Sizes".
+
## Using the local (batch) version
Create a new config file:
diff --git a/flask_frontend.py b/flask_frontend.py
index f119077..5a8e8bb 100644
--- a/flask_frontend.py
+++ b/flask_frontend.py
@@ -1,6 +1,7 @@
from flask import Flask, render_template, request
import numpy as np
from ratio_pyrometry import ratio_pyrometry_pipeline
+from size_projection import get_projected_area
import base64
import cv2 as cv
import plotly.figure_factory as ff
@@ -71,6 +72,19 @@ def projected_area():
return render_template('projected-area.html')
-@app.route('/projected_area_results')
+@app.route('/projected_area_results', methods=['POST'])
def projected_area_results():
- return render_template('projected-area-results.html')
+ f = request.files['file']
+ f_bytes = np.fromstring(f.read(), np.uint8)
+
+ img, dtable = get_projected_area(
+ f_bytes,
+ int(request.form['area_threshold']),
+ int(request.form['min_display_threshold']),
+ )
+
+ return render_template(
+ 'projected-area-results.html',
+ img_b64=img,
+ dtable=dtable
+ )
diff --git a/size_projection.py b/size_projection.py
new file mode 100644
index 0000000..0e693fe
--- /dev/null
+++ b/size_projection.py
@@ -0,0 +1,71 @@
+import base64
+import cv2 as cv
+import numpy as np
+import matplotlib.pyplot as plt
+from skimage import measure, morphology, color, segmentation
+import io
+
+def get_projected_area(image, area_threshold, display_threshold):
+ total_px = image.size
+ total_mm = 60322.46
+
+ output = []
+ original = cv.imdecode(image, cv.IMREAD_UNCHANGED)
+ original = cv.cvtColor(original, cv.COLOR_BGR2RGB)
+
+ img = cv.cvtColor(original, cv.COLOR_BGR2GRAY)
+ _retval, thresh_gray = cv.threshold(img, 200, 255, cv.THRESH_BINARY)
+
+ img = morphology.area_closing(thresh_gray, area_threshold=area_threshold, connectivity=1)
+
+ contours = measure.find_contours(array=img, level=100)
+
+ fig, ax = plt.subplots()
+ ax.imshow(original, cmap=plt.cm.gray, alpha=0.3)
+
+ index = 1
+
+ for contour in contours:
+ area = calculate_area(contour)
+
+ if calculate_area(contour) > display_threshold:
+ ax.plot(contour[:, 1], contour[:, 0], linewidth=0.5, color='orangered')
+
+ cX, cY = center_of_mass(contour)
+ plt.text(cY, cX, index, color='black', fontsize=6)
+
+ output.append((index, round(area / total_px * total_mm, 2)))
+
+ # print(area, total_px)
+
+
+ index += 1
+
+ ax.axis('image')
+ ax.set_xticks([])
+ ax.set_yticks([])
+
+ ax.margins(0)
+
+ my_stringIObytes = io.BytesIO()
+ plt.savefig(my_stringIObytes, format='png', dpi=500, bbox_inches='tight')
+ my_stringIObytes.seek(0)
+ image_arr = base64.b64encode(my_stringIObytes.read()).decode(encoding='utf-8')
+
+ return image_arr, output
+
+def calculate_area(countour):
+ c = np.expand_dims(countour.astype(np.float32), 1)
+ c = cv.UMat(c)
+
+ return cv.contourArea(c)
+
+def center_of_mass(X):
+ x = X[:,0]
+ y = X[:,1]
+ g = (x[:-1]*y[1:] - x[1:]*y[:-1])
+ A = 0.5*g.sum()
+ cx = ((x[:-1] + x[1:])*g).sum()
+ cy = ((y[:-1] + y[1:])*g).sum()
+
+ return 1./(6*A)*np.array([cx,cy])
diff --git a/static/app.css b/static/app.css
index 0944be4..a27de5a 100644
--- a/static/app.css
+++ b/static/app.css
@@ -13,7 +13,7 @@ html {
align-items: center;
padding: 0px 2rem;
background-color: #e0e0e0;
- border-radius: 1rem;
+ border-radius: 0.8rem;
}
.navbar-links {
@@ -45,6 +45,10 @@ html {
width: 32rem;
}
+.image-out-pa {
+ width: 60rem;
+}
+
.legend {
border-spacing: 0px;
border-collapse: collapse;
diff --git a/templates/base.html b/templates/base.html
index c7e685c..ffa751e 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -14,4 +14,5 @@
{% block content required %}
{% endblock %}
+