restructure
BIN
examples/pyrometry/01-0001-cropped-edge-detection.png
Normal file
|
After Width: | Height: | Size: 263 KiB |
BIN
examples/pyrometry/01-0001-cropped-transformed-ratio.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
examples/pyrometry/01-0001-cropped.png
Normal file
|
After Width: | Height: | Size: 513 KiB |
BIN
examples/pyrometry/01-0001-transformed-grayscale.png
Normal file
|
After Width: | Height: | Size: 986 KiB |
BIN
examples/pyrometry/01-0001.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
examples/pyrometry/01-0002-cropped-transformed-ratio.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
examples/pyrometry/01-0002-cropped.png
Normal file
|
After Width: | Height: | Size: 414 KiB |
BIN
examples/pyrometry/01-0002.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
examples/pyrometry/01-0003-cropped.png
Normal file
|
After Width: | Height: | Size: 354 KiB |
BIN
examples/pyrometry/01-0003.png
Normal file
|
After Width: | Height: | Size: 841 KiB |
22
examples/pyrometry/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
## Issues
|
||||
|
||||
### Values too high
|
||||
|
||||
This is supposed to be 1200°C, but is yielding much higher values:
|
||||
|
||||
```
|
||||
|
||||
DSC1022 (Dennis Calibration Image, 1200°C)
|
||||
|
||||
RED GREEN RNORM GNORM G_n/R_n RES TEMP
|
||||
252 84 28.14 8.79 0.3123 2007.8543287627099
|
||||
252 77 28.14 7.98 0.2837 1904.7813013618734
|
||||
231 67 25.72 6.83 0.2656 1837.354974958358
|
||||
215 61 23.88 6.14 0.2571 1805.2478789012494
|
||||
182 48 20.08 4.64 0.2312 1704.0179576792798
|
||||
103 17 10.98 1.07 0.0976 1098.5597969276637
|
||||
97 15 10.29 0.84 0.0817 1015.7460683439863
|
||||
63 6 6.37 -0.2 -0.0307 dropped
|
||||
|
||||
```
|
||||
BIN
examples/pyrometry/_DSC1022 (1)-edge-detection.png
Normal file
|
After Width: | Height: | Size: 9.7 MiB |
BIN
examples/pyrometry/_DSC1022 (1).png
Normal file
|
After Width: | Height: | Size: 15 MiB |
8
examples/pyrometry/base64_test.py
Normal file
@@ -0,0 +1,8 @@
|
||||
import base64
|
||||
import cv2 as cv
|
||||
|
||||
img = cv.imread('01-0001-cropped.png')
|
||||
|
||||
print(img[0:100])
|
||||
|
||||
# print(base64.b64encode(img).decode()[0:5_000])
|
||||
27
examples/pyrometry/edge_detection.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# MONOCHROME EDGE DETECTION
|
||||
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
# edge-detection kernel amplification
|
||||
AMPLIFIER=9
|
||||
|
||||
MIN_INTENSITY=100
|
||||
|
||||
# file = '01-0001-cropped.png'
|
||||
file = 'streaktest.png'
|
||||
file_name = file.split(".")[0]
|
||||
file_ext = file.split(".")[1]
|
||||
|
||||
img = cv.imread(file)
|
||||
|
||||
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
||||
|
||||
kernel = np.array([
|
||||
[-1, -1, -1],
|
||||
[-1, AMPLIFIER, -1],
|
||||
[-1, -1, -1],
|
||||
])
|
||||
img = cv.filter2D(src=img, ddepth=-1, kernel=kernel)
|
||||
|
||||
cv.imwrite(f'{file_name}-edge-detection.{file_ext}', img)
|
||||
103
examples/pyrometry/formula_testing.py
Normal file
@@ -0,0 +1,103 @@
|
||||
import math
|
||||
|
||||
rg_value_sets = {
|
||||
"firebrand_test.png": [
|
||||
(219, 7),
|
||||
(227, 14),
|
||||
(166, 14),
|
||||
(197, 10),
|
||||
(230, 25),
|
||||
(228, 17),
|
||||
(218, 17),
|
||||
(221, 15),
|
||||
(210, 22),
|
||||
(229, 17),
|
||||
],
|
||||
|
||||
"streaktest.png": [
|
||||
(50, 11),
|
||||
(51, 12),
|
||||
(52, 10),
|
||||
(240, 115),
|
||||
(254, 127),
|
||||
],
|
||||
|
||||
"ember_orange.png": [
|
||||
(240, 147),
|
||||
(235, 102),
|
||||
(223, 103),
|
||||
(232, 103),
|
||||
(103, 34),
|
||||
(128, 47),
|
||||
(92, 27),
|
||||
],
|
||||
|
||||
"test5.png": [
|
||||
(164, 49),
|
||||
(177, 57),
|
||||
(181, 58),
|
||||
(156, 46),
|
||||
(150, 41),
|
||||
(151, 44),
|
||||
],
|
||||
|
||||
"DSC1022 (Dennis Calibration Image, 1200°C)": [
|
||||
(252, 84),
|
||||
(252, 77),
|
||||
(231, 67),
|
||||
(215, 61),
|
||||
(182, 48),
|
||||
(103, 17),
|
||||
(97, 15),
|
||||
(63, 6),
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
# Settings
|
||||
I_Darkcurrent = 7.7
|
||||
exposure_time = 0.500
|
||||
f_stop = 2.4
|
||||
ISO = 100 # basically brightness
|
||||
|
||||
def pyrometry_calibration_formula(i_ng, i_nr):
|
||||
"""
|
||||
Given the green-red ratio, calculates an approximate temperature
|
||||
in Celsius.
|
||||
"""
|
||||
try:
|
||||
return (
|
||||
362.73 * math.log10(i_ng/i_nr) ** 3 +
|
||||
2186.7 * math.log10(i_ng/i_nr) ** 2 +
|
||||
4466.5 * math.log10(i_ng / i_nr) +
|
||||
3753.5
|
||||
)
|
||||
except:
|
||||
return 'dropped'
|
||||
|
||||
|
||||
def tprint(*items):
|
||||
for item in items:
|
||||
print(item, end="\t")
|
||||
print()
|
||||
|
||||
|
||||
def grtemp(px):
|
||||
r_norm = (px[0] - I_Darkcurrent) * (f_stop ** 2) / (ISO * exposure_time)
|
||||
g_norm = (px[1] - I_Darkcurrent) * (f_stop ** 2) / (ISO * exposure_time)
|
||||
res = pyrometry_calibration_formula(g_norm, r_norm)
|
||||
tprint(
|
||||
px[0],
|
||||
px[1],
|
||||
# round(px[0] / px[1], 2),
|
||||
round(r_norm, 2),
|
||||
round(g_norm, 2),
|
||||
round(g_norm / r_norm, 4),
|
||||
res,
|
||||
)
|
||||
|
||||
for (key, val) in rg_value_sets.items():
|
||||
print(f"\n{key}\n")
|
||||
tprint('RED', 'GREEN', 'RNORM', 'GNORM', 'G_n/R_n', 'RES TEMP')
|
||||
for rg in val:
|
||||
grtemp(rg)
|
||||
12
examples/pyrometry/grayscale_pyrometry.py
Normal file
@@ -0,0 +1,12 @@
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
img = cv.imread('01-0001.png', 0)
|
||||
|
||||
kernel = np.array([
|
||||
[1.3]
|
||||
])
|
||||
img = cv.filter2D(src=img, ddepth=-1, kernel=kernel)
|
||||
|
||||
img = cv.applyColorMap(img, cv.COLORMAP_JET)
|
||||
cv.imwrite('01-0001-transformed-grayscale.png', img)
|
||||
138
examples/pyrometry/ratio_pyrometry.py
Normal file
@@ -0,0 +1,138 @@
|
||||
import math
|
||||
import cv2 as cv
|
||||
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
|
||||
|
||||
# post-processing
|
||||
smoothing_radius = 2
|
||||
|
||||
# temperature key generation
|
||||
key_entries = 6
|
||||
|
||||
|
||||
@jit(nopython=True)
|
||||
def rg_ratio_normalize(imgarr):
|
||||
# set max & min to most extreme values,
|
||||
# work up & down respectively from there
|
||||
tmin = MAX_TEMP
|
||||
tmax = 0
|
||||
|
||||
imgnew = 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])
|
||||
|
||||
# apply camera calibration func
|
||||
temp_C = pyrometry_calibration_formula(g_norm, r_norm)
|
||||
|
||||
# remove pixels outside calibration range
|
||||
if MAX_TEMP != None and temp_C > MAX_TEMP or MIN_TEMP != None and temp_C < MIN_TEMP:
|
||||
temp_C = 0
|
||||
|
||||
# update min & max
|
||||
if temp_C < tmin and temp_C >= 0:
|
||||
tmin = temp_C
|
||||
if temp_C > tmax:
|
||||
tmax = temp_C
|
||||
|
||||
imgnew[i][j] = [temp_C, temp_C, temp_C]
|
||||
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):
|
||||
"""
|
||||
Given the green-red ratio, calculates an approximate temperature
|
||||
in Celsius.
|
||||
"""
|
||||
return 362.73 * math.log10(
|
||||
(i_ng/i_nr) ** 3
|
||||
) + 2186.7 * math.log10(
|
||||
(i_ng/i_nr) ** 2
|
||||
) + 4466.5 * math.log10(
|
||||
(i_ng / i_nr)
|
||||
) + 3753.5
|
||||
|
||||
|
||||
# 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 = cv.imread('ember_test.png')
|
||||
|
||||
img, tmin, tmax = rg_ratio_normalize(img)
|
||||
|
||||
print(f"min: {tmin}°C")
|
||||
print(f"max: {tmax}°C")
|
||||
|
||||
# build & apply smoothing conv kernel
|
||||
k = []
|
||||
for i in range(smoothing_radius):
|
||||
k.append([1/(smoothing_radius**2) for i in range(smoothing_radius)])
|
||||
kernel = np.array(k)
|
||||
|
||||
img = cv.filter2D(src=img, ddepth=-1, kernel=kernel)
|
||||
|
||||
# write colormapped image
|
||||
img_jet = cv.applyColorMap(img, cv.COLORMAP_JET)
|
||||
cv.imwrite(f'{file_name}-cropped-transformed-ratio.{file_ext}', img_jet)
|
||||
|
||||
# --- Generate temperature key ---
|
||||
|
||||
# adjust max & min temps to be the same as the image
|
||||
# tmin_adj = tmin / (smoothing_radius ** 2)
|
||||
# tmax_adj = tmax / (smoothing_radius ** 2)
|
||||
# Generate 6-step key
|
||||
step = (tmax - tmin) / (key_entries-1)
|
||||
temps = []
|
||||
key_img_arr = [[]]
|
||||
for i in range(key_entries):
|
||||
res_temp = tmin + (i * step)
|
||||
res_color = (tmax - (i * step)) / MAX_TEMP * 255
|
||||
temps.append(res_temp)
|
||||
key_img_arr[0].append([res_color, res_color, res_color])
|
||||
|
||||
key_img = np.array(key_img_arr).astype(np.uint8)
|
||||
key_img_jet = cv.applyColorMap(key_img, cv.COLORMAP_JET)
|
||||
# cv.imwrite(f'{file_name}-key.{file_ext}', key_img_jet)
|
||||
|
||||
tempkey = {}
|
||||
for i in range(len(temps)):
|
||||
c = key_img_jet[0][i]
|
||||
tempkey[temps[i]] = f"rgb({c[0]}, {c[1]}, {c[2]})"
|
||||
|
||||
print(json.dumps(tempkey, indent=4))
|
||||
BIN
examples/pyrometry/streaktest-edge-detection.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
examples/pyrometry/streaktest.png
Normal file
|
After Width: | Height: | Size: 58 KiB |