diff --git a/README.md b/README.md index 647bc0b..1b6a5d8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,19 @@ # Pyrometry image processing +## Developing the web frontend + +To serve in production: + +``` +gunicorn flask_frontend:app +``` + +To autoreload on source file changes: + +``` +gunicorn flask_frontend:app --reload +``` + ## Temperature maps **Grayscale pyrometry:** currently basic; uses grayscale opencv import, then just applies a jet filter. Doesn't yet copy the full impl in the paper. @@ -8,14 +22,14 @@ **Test image:** -![](01-0001.png) +![](examples/01-0001-cropped.png) -**Grayscale pyrometry result:** - -![](01-0001-transformed-grayscale.png) - -**Ratio pyrometry result (with 2x2 convolutional smoothing):** +**Ratio pyrometry result (with convolutional smoothing):** According to general researcher consensus, ratio pyrometry is supposed to be more accurate. -![](01-0001-cropped-transformed-ratio.png) +![](examples/01-0001-cropped-transformed-ratio.png) + +**Grayscale pyrometry result:** + +![](examples/01-0001-transformed-grayscale.png) diff --git a/display_key.html b/display_key.html deleted file mode 100644 index e4d28f5..0000000 --- a/display_key.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - -
ColorTemperature
0°C
- - diff --git a/flask_frontend.py b/flask_frontend.py index 5a21e90..878a126 100644 --- a/flask_frontend.py +++ b/flask_frontend.py @@ -1,16 +1,34 @@ from flask import Flask, render_template, request +import numpy as np +from ratio_pyrometry import ratio_pyrometry_pipeline +import base64 app = Flask(__name__) @app.route('/', methods=['GET']) def index(): - return render_template('index.html') + return render_template('index.jinja2') @app.route('/ratio_pyro', methods=['POST']) def ratio_pyro(): f = request.files['file'] - I_Darkcurrent = 150.5 - exposure_time = 0.500 - f_stop = 2.4 - ISO = 64 - return 200 + f_bytes = np.fromstring(f.read(), np.uint8) + img_orig, img_res, key = ratio_pyrometry_pipeline( + f_bytes, + ISO=float(request.form['iso']), + I_Darkcurrent=float(request.form['i_darkcurrent']), + exposure_time=float(request.form['exposure_time']), + f_stop=float(request.form['f_stop']), + MAX_TEMP=float(request.form['max_temp']), + MIN_TEMP=float(request.form['min_temp']) + ) + + img_orig_bytes = base64.urlsafe_b64encode(img_orig) + img_res_bytes = base64.urlsafe_b64encode(img_res) + + return render_template( + 'results.jinja2', + img_orig_bytes=img_orig_bytes, + img_res_bytes=img_res_bytes, + legend=key + ) diff --git a/ratio_pyrometry.py b/ratio_pyrometry.py index 0d628f9..720b0ab 100644 --- a/ratio_pyrometry.py +++ b/ratio_pyrometry.py @@ -4,25 +4,11 @@ import numpy as np from numba import jit import json -# camera settings -file = '01-0001.png' -I_Darkcurrent = 150.5 -exposure_time = 0.500 -f_stop = 2.4 -ISO = 64 # basically brightness - -# pyrometry config -MAX_TEMP = 1200 -MIN_TEMP = 60 -# original range from paper -# MAX_GR_RATIO = 1200 -# MIN_GR_RATIO = 600 - # Cropping config -x1 = 420 -x2 = 1200 -y1 = 400 -y2 = -1 +# x1 = 420 +# x2 = 1200 +# y1 = 400 +# y2 = -1 # post-processing smoothing_radius = 2 @@ -32,7 +18,15 @@ key_entries = 6 @jit(nopython=True) -def rg_ratio_normalize(imgarr): +def rg_ratio_normalize( + imgarr, + I_Darkcurrent, + f_stop, + exposure_time, + ISO, + MIN_TEMP, + MAX_TEMP +): # set max & min to most extreme values, # work up & down respectively from there tmin = MAX_TEMP @@ -42,8 +36,10 @@ def rg_ratio_normalize(imgarr): for i in range(len(imgarr)): for j in range(len(imgarr[i])): px = imgarr[i][j] - r_norm = normalization_func(px[0]) - g_norm = normalization_func(px[1]) + + # normalize R & G pixels + r_norm = (px[0] - I_Darkcurrent) * (f_stop ** 2) / (ISO * exposure_time) + g_norm = (px[1] - I_Darkcurrent) * (f_stop ** 2) / (ISO * exposure_time) # apply camera calibration func temp_C = pyrometry_calibration_formula(g_norm, r_norm) @@ -62,14 +58,6 @@ def rg_ratio_normalize(imgarr): return imgnew, tmin, tmax -@jit(nopython=True) -def normalization_func(i): - """ - does something to the pixels that i don't understand lol - """ - return (i - I_Darkcurrent) * (f_stop ** 2) / (ISO * exposure_time) - - @jit(nopython=True) def pyrometry_calibration_formula(i_ng, i_nr): """ @@ -84,18 +72,31 @@ def pyrometry_calibration_formula(i_ng, i_nr): (i_ng / i_nr) ** 3 ) + 3753.5 -def ratio_pyrometry_pipeline(file): +def ratio_pyrometry_pipeline( + file_bytes, + # camera settings + I_Darkcurrent: float, + exposure_time: float, + f_stop: float, + ISO: float, + # pyrometry config + MAX_TEMP: float, + MIN_TEMP: float +): # read image & crop - file_name = file.split(".")[0] - file_ext = file.split(".")[1] - img = cv.imread(file) - img = img[y1:y2, x1:x2] - cv.imwrite(f'{file_name}-cropped.{file_ext}', img) + img_orig = cv.imdecode(file_bytes, cv.IMREAD_UNCHANGED) + # img = img[y1:y2, x1:x2] - # img = cv.imread('ember_test.png') - - img, tmin, tmax = rg_ratio_normalize(img) + img, tmin, tmax = rg_ratio_normalize( + img_orig, + I_Darkcurrent, + f_stop, + exposure_time, + ISO, + MIN_TEMP, + MAX_TEMP + ) # build & apply smoothing conv kernel k = [] @@ -107,7 +108,7 @@ def ratio_pyrometry_pipeline(file): # write colormapped image img_jet = cv.applyColorMap(img, cv.COLORMAP_JET) - cv.imwrite(f'{file_name}-cropped-transformed-ratio.{file_ext}', img_jet) + # cv.imwrite(f'{file_name}-cropped-transformed-ratio.{file_ext}', img_jet) # --- Generate temperature key --- @@ -131,3 +132,6 @@ def ratio_pyrometry_pipeline(file): for i in range(len(temps)): c = key_img_jet[0][i] tempkey[temps[i]] = f"rgb({c[0]}, {c[1]}, {c[2]})" + + # original, transformed, legend + return img_orig, img_jet, tempkey diff --git a/templates/base.jinja2 b/templates/base.jinja2 index df292df..eeb7cdf 100644 --- a/templates/base.jinja2 +++ b/templates/base.jinja2 @@ -4,5 +4,6 @@ - {% block content %} + {% block content required %} + {% endblock %} diff --git a/templates/index.jinja2 b/templates/index.jinja2 index 36a4873..940c843 100644 --- a/templates/index.jinja2 +++ b/templates/index.jinja2 @@ -1,7 +1,38 @@ -{% extends "base.html" %} +{% extends "base.jinja2" %} {% block content %} -
- -
+
+

Simple Ratio Pyrometry Interface

+ + +

Camera Settings

+ + + +
+ + + +
+ + + +
+ + + +
+ +

Temperature Settings

+ + + +
+ + + +
+ +
+ +
{% endblock %} diff --git a/templates/results.jinja2 b/templates/results.jinja2 new file mode 100644 index 0000000..a3ac0e6 --- /dev/null +++ b/templates/results.jinja2 @@ -0,0 +1,57 @@ +{% extends "base.jinja2" %} +{% block content %} + + + + + + + + {# Original image #} + + + {# Result image #} + + +
Input ImageResultant Heatmap
+ original image + + result image +
+ +

{{ img_orig_bytes }}

+ +


+ + + + + + + {% for temp, color in legend.items() %} + + + + + {% endfor %} +
ColorTemperature
{{ temp }}°C
+ + + +{% endblock %}