def batch_extract_temp_for_class(dirLoc, mask, emiss=[0], exiftoolpath=''): """ This function creates a 3D numpy array thermal image that ONLY contains pixels for class of interest with all other pixels set to 0. This is for a directory of images. INPUTS: 1) dirLoc: a string containing the directory of FLIR images. 2) mask: a binary mask with class pixels set as 1. 3) emiss: a 2D numpy array with each pixel containing correct emissivity 4) exiftoolpath = OPTIONAL a string containing the location of exiftools. Only use if the exiftool path is different than the python path. OUTPUTS: 1) all_temp: a 3D numpy array of temperature values for a class of interest The first two dimensions will match the dimensions of a single temperature image. The third dimension size will match the number of files in directory. """ filelist = glob.glob(dirLoc + '*') print('Found ' + str(len(filelist)) + ' files.') all_temp = np.ma.empty((mask.shape[0], mask.shape[1], len(filelist))) for f in range(0,len(filelist)): # Get individual file if not exiftoolpath: flir = flirimageextractor.FlirImageExtractor() else: flir = flirimageextractor.FlirImageExtractor(exiftool_path=exiftoolpath) flir.process_image(filelist[f], RGB=True) if len(emiss) == 1: all_temp[:,:,f] = extract_temp_for_class(flir, mask, plot=0) else: all_temp[:,:,f] = extract_temp_for_class(flir, mask, emiss, plot=0) return all_temp
def thermal(image=src): global temps try: flir = flirimageextractor.FlirImageExtractor() flir.process_image(image) temps = flir.get_thermal_np() except: pass detector = dlib.get_frontal_face_detector() image = cv2.imread(image) image = imutils.resize(image, width=500) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) rects = detector(gray, 1) rect = rects[0] # first person (x, y, w, h) = face_utils.rect_to_bb(rect) cv2.rectangle(image, (x + x // 2, y), (x + w // 3, y + h // 6), (0, 0, 255), 2) if len(temps) != 0: f = (np.matrix(temps[y:y + h // 6, x:x + w // 3]).mean()) else: f = 0 cv2.putText(image, str(int(f)) + " F", (x + x // 2, y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 1) return image
def extract_and_register(path): """ Extracts the thermal matrix and rgb data from an image taken on a FLIROne camera. Also crops and scales the rgb data, to be registered with the thermal matrix. :param path: Path where image is located :type path: str :return: Rgb and thermal images in a tuple, in that order :rtype: (list[int,int,int],list[int,int]) """ flir = flirimageextractor.FlirImageExtractor() flir.process_image(path) thermal_im = flir.extract_thermal_image() # Read the images to be aligned rgb_im = cv2.cvtColor(flir.extract_embedded_image(), cv2.COLOR_RGB2BGR) rgb_im = rgb_im[185:-90, 120:-86] # thermal_im = optimal_quantization(thermal_im) scale_percent = 55 # percent of original size width = int(rgb_im.shape[1] * scale_percent / 100) height = int(rgb_im.shape[0] * scale_percent / 100) dim = (width, height) # resize image rgb_im = cv2.resize(rgb_im, dim, interpolation=cv2.INTER_AREA) return rgb_im, thermal_im
def hotspotFinder(img_path): ir_image = flirimageextractor.FlirImageExtractor() ir_image.process_image(img_path) temps = ir_image.get_thermal_np() max_temp = np.max(temps) #4 is the ratio between temperature array and image coord = np.where(temps==max_temp)*np.array(4) return coord, max_temp
def batch_extract_temp(dirLoc, classmask=[0], emiss=[0], exiftoolpath=''): """ This function creates a 3D numpy array thermal image for a directory of images. It can apply the emissivity correction to the batch of images which assumes the RGB image applies to all images (aka the camera didn't move). It can also only extract pixels for a class of interest. INPUTS: 1) dirLoc: a string containing the directory of FLIR images. 2) classmask: OPTIONAL - a binary mask with class pixels set as 1. Output will only have class pixel temperatures. 3) emiss: OPTIONAL - a 2D numpy array with each pixel containing correct emissivity. If provided output will correct temperature based on emissivity 4) exiftoolpath = OPTIONAL - a string containing the location of exiftools. Only use if the exiftool path is different than the python path. OUTPUTS: 1) all_temp: a 3D numpy array of temperature values for a class of interest The first two dimensions will match the dimensions of a single temperature image. The third dimension size will match the number of files in directory. """ filelist = glob.glob(dirLoc + '*') print('Found ' + str(len(filelist)) + ' files.') for f in range(0, len(filelist)): # Get individual file if not exiftoolpath: flir = flirimageextractor.FlirImageExtractor() else: flir = flirimageextractor.FlirImageExtractor( exiftool_path=exiftoolpath) flir.process_image(filelist[f], RGB=True) # Setting up 3D numpy array based on if class mask is provided. if f == 0: temp = flir.get_thermal_np() if len(classmask) == 1: classmask = np.ones((temp.shape[0], temp.shape[1])) all_temp = np.ma.empty( (classmask.shape[0], classmask.shape[1], len(filelist))) # Emissivity Correction if len(emiss) == 1: all_temp[:, :, f] = extract_temp(flir, classmask, plot=0) else: all_temp[:, :, f] = extract_temp(flir, classmask, emiss, plot=0) return all_temp
def reset(self): flir = flirimageextractor.FlirImageExtractor() flir.process_image(self.flir_path, RGB=True) thermogram = flyr.unpack(self.flir_path) thermal_values = np.array(thermogram.celsius) (y, x) = thermal_values.shape thermal = cv2.imread(self.flir_path) visual = flir.get_rgb_np() visual = cv2.resize(visual, (x, y)) thermal = cv2.resize(thermal, (x, y)) self.visual = visual self.thermal = thermal self.thermal_values = thermal_values
def multiple_images(FOLDER_PATH): flir = flirimageextractor.FlirImageExtractor(is_debug=True) # get a list of all of the files in the folder and filter for just thermal images thermal_images = [ join(FOLDER_PATH, f) for f in listdir(FOLDER_PATH) if isfile(join(FOLDER_PATH, f)) and f.lower().endswith(".jpg") and flir.check_for_thermal_image(join(FOLDER_PATH, f)) ] logger.debug(thermal_images) # create a folder to store everything in if not os.path.exists(join(FOLDER_PATH, "thermal-data")): mkdir(join(FOLDER_PATH, "thermal-data")) # create two arrays to keep track of the minTemp and maxTemp temperatures min_values = [] max_values = [] logger.level("SECTION", no=38, color="<yellow>", icon="🎯") logger.log("SECTION", "Getting thermal information for all images") # for each of the thermal images, get the thermal data (and save it to disk?) for image in thermal_images: flir.process_image(image) thermal_data = flir.get_thermal_np() # process the temperature data from the image max_values.append(np.amax(thermal_data)) min_values.append(np.amin(thermal_data)) filename = join( FOLDER_PATH, "thermal-data", "".join("".join(image.split("/")[-1]).split(".")[:-1]), ) logger.info(f"Saving thermal data to {filename}.np") np.save(filename, thermal_data) # using all the thermal data calculate the minimum and maximum temperatures for the dataset dataset_min = np.amin(min_values) dataset_max = np.amax(max_values) logger.log("SECTION", "Saving the images to disk") # using these minTemp maxTemp values, save all of the images to disk for image in thermal_images: flir.process_image(image) flir.save_images(minTemp=dataset_min, maxTemp=dataset_max)
def extract_temperature_ir(self, min_temp=25, max_temp=35, input_dir=None, output_dir=None): #get temperature plot from IR images if input_dir is None: input_dir = self.input_dir flir = flirimageextractor.FlirImageExtractor(palettes=[cm.hot]) ir_list = [fname for fname in os.listdir(input_dir) if re.match(r'DJI_[0-9]+_R.JPG', fname)] for ir_file in ir_list: img_path = os.path.join(input_dir, ir_file) flir.process_image(img_path) thermal_arr = flir.get_thermal_np() result = flir.save_images(min_temp, max_temp) #save the results arr_filename = os.path.splitext(ir_file)[0] + '_temp.npy' np.save(os.path.join(output_dir, arr_filename), thermal_arr)
def _main_(args): input_path = args.input files = [] # r=root, d=directories, f = files for r, d, f in os.walk(input_path): for file in f: if '.jpg' in file: files.append(os.path.join(r, file)) for f in files: flir = flirimageextractor.FlirImageExtractor() print(f) try: flir.process_image(f) I = flirimageextractor.FlirImageExtractor.get_thermal_np(flir) except: I = plt.imread(f) #flir.save_images() #flir.plot() #img = img.astype(np.int8) W = np.where(np.isnan(I)) if np.shape(W)[1] > 0: #xmax = np.max(np.amax(W,axis=0)) ymax = np.max(np.amin(W, axis=1)) img = I[:ymax, :] else: img = I list_string = f.split('/') list_string[-3] += '_jpg' f_aux = '/'.join(list_string) mkdir(f_aux) plt.imsave(f_aux, img, cmap='gray')
def _main_(args): input_path = args.input output_path = args.output thermal_path = args.input_thermal mkdir(output_path) mkdir(output_path + 'images/') mkdir(output_path + 'anns/') Excel = pandas.read_excel(input_path, sheet_name='Lista_Archivos_Fotos', header=1) for index_path in range(len(Excel.Archivo)): if not pandas.notna(Excel.Archivo[index_path]): continue path_Flir = Excel.loc[index_path]['Archivo'] cod_falla = int(Excel.loc[index_path]['Cód. Falla']) sev = Excel.loc[index_path]['Severidad'] #if cod_falla != 4: # continue ## Junta las mismas fotos con distintos label EJ : # DJI_0021B ---> DJI_0021 aux = path_Flir.split('/')[-2:] if len(aux[1].split('.')[0]) > 8: aux[1] = aux[1].split('.')[0][:8] + '.' + aux[1].split('.')[1] path_Flir_aux = thermal_path + '/'.join(path_Flir.split('/')[-2:]) if not os.path.isfile(path_Flir_aux): print('No existe la imagen', path_Flir_aux) continue flir = flirimageextractor.FlirImageExtractor() try: flir.process_image(path_Flir_aux) I = flirimageextractor.FlirImageExtractor.get_thermal_np(flir) w, h = I.shape except: print('No se puede leer la imagen Flir', path_Flir_aux) continue dic_data = flir.get_metadata(path_Flir_aux) meas = [s for s in dic_data.keys() if "Meas" in s] q_bbox = len(meas) // 3 # cada bbox tiene 3 parametros param_bbox = [] for num_bbox in range(1, q_bbox + 1): # Se guarda los parametros de los boundibox (xmin, ymin, width, height) width = xmax- xmin param_bbox.append( list( map(int, dic_data['Meas' + str(num_bbox) + 'Params'].split(' ')))) ##### Save Image and create XML annotations type of fault path_save_img = output_path + 'images/' + '_'.join(aux) path_save_anns = output_path + 'anns/' + '_'.join(aux) path_save_anns = path_save_anns[:-4] + '.xml' if not os.path.isfile(path_save_img): plt.imsave(path_save_img, I, cmap='gray') #si el archivo ya existe se agregan mas anotaciones if os.path.isfile(path_save_anns): et = ET.parse(path_save_anns) root = et.getroot() for box in param_bbox: obj = ET.SubElement(root, "object") ET.SubElement(obj, "name").text = str(cod_falla) ET.SubElement(obj, "pose").text = 'Unspecified' ET.SubElement(obj, "truncated").text = str(0) ET.SubElement(obj, "difficult").text = str(0) bx = ET.SubElement(obj, "bndbox") ET.SubElement(bx, "xmin").text = str(box[0]) ET.SubElement(bx, "ymin").text = str(box[1]) ET.SubElement(bx, "xmax").text = str(box[0] + box[2]) ET.SubElement(bx, "ymax").text = str(box[1] + box[3]) tree = ET.ElementTree(root) tree.write(path_save_anns) ## Si no existe se crea desde cero else: root = ET.Element("annotation") ET.SubElement(root, "folder").text = output_path[:-1] ET.SubElement(root, "filename").text = '_'.join( path_Flir.split('/')[-2:]) ET.SubElement(root, "path").text = path_save_img source = ET.SubElement(root, "source") ET.SubElement(source, "database").text = 'Unknown' size = ET.SubElement(root, "size") ET.SubElement(size, "width").text = str(w) ET.SubElement(size, "height").text = str(h) ET.SubElement(size, "depth").text = str(1) ET.SubElement(root, "segmented").text = '0' for box in param_bbox: obj = ET.SubElement(root, "object") ET.SubElement(obj, "name").text = str(cod_falla) ET.SubElement(obj, "pose").text = 'Unspecified' ET.SubElement(obj, "truncated").text = str(0) ET.SubElement(obj, "difficult").text = str(0) bx = ET.SubElement(obj, "bndbox") ET.SubElement(bx, "xmin").text = str(box[0]) ET.SubElement(bx, "ymin").text = str(box[1]) ET.SubElement(bx, "xmax").text = str(box[0] + box[2]) ET.SubElement(bx, "ymax").text = str(box[1] + box[3]) tree = ET.ElementTree(root) tree.write(path_save_anns) files = [] # r=root, d=directories, f = files for r, d, f in os.walk(input_path): for file in f: if '.jpg' in file: files.append(os.path.join(r, file)) for f in files: flir = flirimageextractor.FlirImageExtractor() print(f) try: flir.process_image(f) I = flirimageextractor.FlirImageExtractor.get_thermal_np(flir) except: I = plt.imread(f) #flir.save_images() #flir.plot() #img = img.astype(np.int8) W = np.where(np.isnan(I)) if np.shape(W)[1] > 0: #xmax = np.max(np.amax(W,axis=0)) ymax = np.max(np.amin(W, axis=1)) img = I[:ymax, :] else: img = I list_string = f.split('/') list_string[-3] += '_jpg' f_aux = '/'.join(list_string) mkdir(f_aux) plt.imsave(f_aux, img, cmap='gray')
import numpy as np import matplotlib.pyplot as plt import matplotlib matplotlib.use('TKAgg') # Needed to have figures display properly in spyder. import flirimageextractor import utilities as u ## ---GETTING STARTED---------------------------------------------------------- ## Setting up some parameters # You will have change the path of exiftool depending on where it was installed. dirLoc = 'C:\\Users\\susanmeerdink\\Documents\\Git\\FLIR_thermal_tools\\Test_Images\\' exiftoolpath = "C:\\Users\\susanmeerdink\\.utilities\\exiftool.exe" ## Load Image using flirimageextractor filename = dirLoc + 'IR_56020.jpg' flir = flirimageextractor.FlirImageExtractor(exiftool_path=exiftoolpath) flir.process_image(filename, RGB=True) ## Examine thermal and full resolution RGB images # Most FLIR cameras take a thermal image and a corresponding RGB image. # The RGB camera is higher resolution and has a larger field of view. therm = flir.get_thermal_np() rgb_fullres = flir.get_rgb_np() plt.figure(figsize=(10, 5)) plt.subplot(1, 2, 1) plt.imshow(therm) plt.title('Thermal Image') plt.subplot(1, 2, 2) plt.imshow(rgb_fullres) plt.title('RGB Full Resolution Image') plt.show(
import flirimageextractor from matplotlib import cm from matplotlib import pyplot as plt import cv2 # Read the image using OpenCV library image = cv2.imread('Transformer.jpg') plt.subplot(1, 1, 1) plt.imshow(image) plt.show() # Find the shape of the image rows, cols, color = image.shape print(image.shape) # Process the image using FlirImageExtractor library flir = flirimageextractor.FlirImageExtractor( palettes=[cm.jet, cm.bwr, cm.gist_ncar]) flir.process_image('Transformer.jpg') flir.save_images() flir.plot() thermal = flir.get_thermal_np() flir.check_for_thermal_image('Transformer.jpg') # Extract the temperature per pixel of the image Transformer.jpg for i in range(image.shape[0]): for j in range(0, image.shape[1]): pixel = image[i, j] temperature = thermal[i, j] print(pixel, temperature)
import flirimageextractor import numpy as np from PIL import Image # User defined variables threshold = 25 # Celsius threshold_color = (255, 0, 0) # RGB value img_path = "./sample_data/flir_vue_pro_r_images/Images/sample_image.jpg" # Relative or absolute path to the image # Get the images that will be sent to the end user org_img = Image.open(img_path) new_img = Image.open(img_path) new_img_pixels = new_img.load() # Extract the thermal data flir = flirimageextractor.FlirImageExtractor() flir.process_image(img_path, False) temperatures = np.array(flir.thermal_image_np.copy()) # Check if any pixel is above threshold # Every pixel above the thermal threshold will be asgined the threshold color above_threshold = False for row, col in np.ndindex(temperatures.shape): if temperatures[row, col] > threshold: new_img_pixels[col, row] = threshold_color above_threshold = True if above_threshold: # Do something here # Return the pil objects org_img.show()
description= "Extract thermal and visible data from FLIR One exported images.") parser.add_argument("in_path", help="Input directory containing exported images") parser.add_argument("out_path", help="Output directory for extracted dataset") parser.add_argument("-v", "--verbose", dest="verbose", help="Verbose output", action="store_true") args = vars(parser.parse_args()) # Setup output dir if os.path.isdir(args["out_path"]): shutil.rmtree(args["out_path"], ignore_errors=False, onerror=None) os.makedirs(os.path.join(args["out_path"], "thermal")) os.makedirs(os.path.join(args["out_path"], "visible")) flir = flirimageextractor.FlirImageExtractor(palettes=[]) images = filter(lambda f: f.endswith(".jpg"), os.listdir(args["in_path"])) for image in images: try: thermal, visible = extract_image( flir, os.path.join(args["in_path"], image), args["verbose"]) imsave(os.path.join(args["out_path"], "thermal", image), thermal) imsave(os.path.join(args["out_path"], "visible", image), visible) except: print("Could not process image!")
def temp_analysis(name): flir = flirimageextractor.FlirImageExtractor() flir.process_image(name) temp = flir.thermal_image_np.reshape((flir.thermal_image_np.size, 1)) mean = np.sum(temp) / flir.thermal_image_np.size return mean
December 2019 """ # Importing Functions import numpy as np import matplotlib.pyplot as plt import matplotlib matplotlib.use('TKAgg') # Needed to have figures display properly. import flirimageextractor import utilities as u ## Load Image using flirimageextractor # Note: I had to change the path of my exiftool which you may need to also change. filename = 'C:\\Users\\susanmeerdink\\Documents\\Git\\FLIR_thermal_tools\\Test_Images\\IR_56020.jpg' flir = flirimageextractor.FlirImageExtractor( exiftool_path="C:\\Users\\susanmeerdink\\.utilities\\exiftool.exe") flir.process_image(filename, RGB=True) ## Examine thermal and full resolution RGB images # Most FLIR cameras take a thermal image and a corresponding RGB image. # The RGB camera is higher resolution and has a larger field of view. therm = flir.get_thermal_np() rgb_fullres = flir.get_rgb_np() plt.figure(figsize=(10, 5)) plt.subplot(1, 2, 1) plt.imshow(therm) plt.title('Thermal Image') plt.subplot(1, 2, 2) plt.imshow(rgb_fullres) plt.title('RGB Full Resolution Image') plt.show(