The problem is as follows: I have a thermal image from FLIR which I use to extract two images from its embedded data: raw thermal image and embedded image. What I want to do is to select a rectangle in the embedded image which corresponds exactly the thermal image region.
Example of these 3 images follows:
Thermal Image: https://drive.google.com/file/d/1-rKPUEYrSJCnjiMYM-1Wm_uHnhoK955R/view?usp=sharing
Embedded Image: https://drive.google.com/file/d/1vKnCUXsFhkjHN5suwOagvOxAOc4BB3DT/view?usp=sharing
Raw Image: https://drive.google.com/file/d/1evDRpGoztt2RqwqNXmPzv1ratkhafWgK/view?usp=sharing
I have written some python code to do that and here it is:
import cv2
def get_offset(path):
"""Utility function to get Offset information
Args:
path (str): Path to image
Returns:
Dict
"""
run = subprocess.Popen(
f'exiftool -q -q -m -j -OffsetX -OffsetY "{path}"',
shell=True,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE
)
j = json.loads(run.communicate()[0])[0]
return j
def get_raw(path):
"""Utility function to get raw image
Args:
path (str): Path to image
"""
run = subprocess.Popen(
f'exiftool "{path}" -q -q -m -b -RawThermalImage | convert - gray:- | convert -depth 16 -endian lsb -size 640x480 gray:- raw.png',
shell=True,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE
)
return_code = os.waitpid(run.pid, 0)
run = subprocess.Popen(
f'identify -verbose raw.png | grep -in5 "Gray:" | grep min | sort -k 3 | head -n 1 | cut -d" " -f8',
shell=True,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE
)
os.waitpid(run.pid, 0)
min_thermal_value_16bits = int(run.communicate()[0].strip())
run = subprocess.Popen(
f'identify -verbose raw.png | grep -in5 "Gray:" | grep max | sort -k 3 | head -n 1 | cut -d" " -f8',
shell=True,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE
)
os.waitpid(run.pid, 0)
max_thermal_value_16bits = int(run.communicate()[0].strip())
if min_thermal_value_16bits < 60 and 65000 < max_thermal_value_16bits:
run = subprocess.Popen(
f'exiftool "{path}" -q -q -m -b -RawThermalImage | convert - gray: | convert -depth 16 -endian msb -size 640x480 gray:- raw.png',
shell=True,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE
)
return_code = os.waitpid(run.pid, 0)
path = "path to thermal image"
get_raw(path)
emb_img = cv2.imread("path to embedded image", cv2.IMREAD_COLOR)
emb_height, emb_width, emb_channels = emb_img.shape
emb_center = {
'x': math.floor(emb_width / 2),
'y': math.floor(emb_height / 2)
}
raw_img = cv2.imread('raw.png', cv2.IMREAD_GRAYSCALE)
raw_width, raw_height = raw_img.shape
raw_center = {
'x': math.floor(raw_width / 2),
'y': math.floor(raw_height / 2)
}
j = get_offset(path)
x1 = emb_center.get('x') - raw_center.get('x') + j.get('OffsetX')
y1 = emb_center.get('y') - raw_center.get('y') + j.get('OffsetY')
cv2.rectangle(
emb_img, (x1, y1),
(x1 + 640, y1 + 480),
(0, 0, 255), 3
)
cv2.imwrite('overlap.png', emb_img)
The result is a quite far to be what I want and can be accessed here: https://drive.google.com/file/d/1nSNcoEayHLw5s-CoAjAOslr-TTlVvLiu/view?usp=sharing
I wonder if there is a way to match perfectly the thermal image region on the embedded image using only the metadata provided by the thermal image