-
Notifications
You must be signed in to change notification settings - Fork 0
SResor/Image_Processing
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
# post_processing.py # # Description: # This program does either temporal analysis or spatial analysis on a set of images. Temporal analysis determines # the percent variation from pulse to pulse, normalized for exposure time. Spatial analysis determines the # spatial distribution of the illumination and how reliable that distribution is. In both cases the images are # reduced from their original resolution by removing 25% of the image on all four sides. Once analysis is finished # the resultant data is exported to an Excel file and displayed as an image. # The two types of analysis seek to answer the following questions: # # Temporal: # - How much percent variation do you see from pulse to pulse (as represented by Coefficient of Variation (CoV))? # - Is it random noise or does it drift in one direction over time? why? (Is the change in CoV the same # every time for the different exposures?) # - Are the detected pulses linear with time? (will twice the exposure get you twice as much light?) If # not, why? (flattened light dose might mean saturated image) # - How much do you lose in percent compared to the 1 ms case? # # Spatial: # - What does the spatial distribution of the illumination look like? # - How repeateable/reliable is that illumination shape? (for a given exposure time, can you show me # a picture representing the (pixel-wise) variation you see from image to image, compared to an average image?) # - How do these factors change as you change the pulse length? (Does the illumination shape change at # higher exposures?) # BONUS: Why is it brighter in the center? Can you make it flatter? # # Python Packages: # - numpy # - opencv-python # - glob2 # - xlsxwriter # - matplotlib import cv2 import numpy as np import glob from enum import Enum import xlsxwriter as xw import matplotlib.pyplot as plt TEST_CASE = False # Determine whether the program runs the temporal or spatial processing code # True is for Temporal, False is for Spatial # Temporal test case partial filepath. Must be modified for use on other PCs. Should point to location of test images # Filepath is partial because images must be loaded in a particular order TEMPORAL_FILEPATH = r"C:\Users\seanr\PycharmProjects\Image_Processing\Temporal Test Images" # Spatial test case filepath. Must be modified for use on other PCs. Should point to location of test images SPATIAL_FILEPATH = r"C:\Users\seanr\PycharmProjects\Image_Processing\Spatial Test Images" RESOLUTION_HEIGHT = 480 # Pixel height of the image files being processed RESOLUTION_WIDTH = 640 # Pixel width of the image files being processed # Enum class for the four different LED conditions for the temporal test case # May need to be modified later if test case includes white light from LED # If modified then the Intel RealSense camera code should also be modified class LED_color(Enum): RED = 0 GREEN = 1 BLUE = 2 NO = 3 # Dictionary to hold exposure times (in ms) with the respective LED colors for the temporal test case # Must be modified if other exposure times are used for testing # Length of this dictionary should always be one less than the length of the LED_color enumerator class exposure_time = { LED_color.RED: 1.0, LED_color.GREEN: 2.0, LED_color.BLUE: 3.0 } # Function to import image files in a particular order for the temporal test case # Because the pixel values must be divided by a different exposure time for each image the images must be in a # particular order def ordered_import_images(filepath): reference_images = [] for color in LED_color: end_of_file = "\\*" + str(color.name) + ".png" single_image = [cv2.imread(file, cv2.IMREAD_GRAYSCALE) for file in glob.glob(filepath + end_of_file)] if color.value == 3: ambient_light_image = single_image else: reference_images.append(single_image) print("Images imported...") return ambient_light_image, reference_images # Function to import image files in no particular order for the spatial test case def import_images(filepath): end_of_file = "\\*.png" reference_images = [cv2.imread(file, cv2.IMREAD_GRAYSCALE) for file in glob.glob(filepath + end_of_file)] print("Images imported...") return reference_images # Function that subtracts the ambient light pixel values from each image and then normalizes the image pixel values # for the differing exposure times by dividing out the exposure time def normalize_for_exposure(ambient_light_image, reference_images): normalized_test_images = [] single_image = np.empty([int(RESOLUTION_HEIGHT * 0.5), int(RESOLUTION_WIDTH * 0.5)]) for color in LED_color: if color.value == len(LED_color) - 1: continue else: x = int(RESOLUTION_HEIGHT * 0.25) j = 0 while x < RESOLUTION_HEIGHT * 0.75: y = int(RESOLUTION_WIDTH * 0.25) k = 0 while y < RESOLUTION_WIDTH * 0.75: ref_pixel = reference_images[color.value][0][x][y] amb_pixel = ambient_light_image[0][x][y] single_pixel = ref_pixel - amb_pixel exposure = list(exposure_time.values())[color.value] single_image[j][k] = single_pixel / exposure # = (ref_pixel / exposure) - amb_pixel # should be used if the camera's exposure time is # not consistent across image acquisitons y += 1 k += 1 x += 1 j += 1 normalized_test_images.append(single_image.copy()) return normalized_test_images # Function was working with the spatial image files. The ref_array parameter must be in a list # in order for the function to work properly, even if it's a list of length one. This is so # that the function could be passed a list of multiple images to write to Excel, in case a user # needs to investigate individual image values. def write_to_excel(ref_array, filepath): workbook = xw.Workbook(filepath + '\\test.xlsx') for x in range(len(ref_array)): out_array = ref_array[x].copy() rotated_array = np.rot90(np.fliplr(out_array)) if len(ref_array) > 1: worksheet = workbook.add_worksheet(str(list(exposure_time.values())[x]) + "ms " + str(list(exposure_time.keys())[x])) else: worksheet = workbook.add_worksheet("% CoV") row = 0 for col, data in enumerate(rotated_array): worksheet.write_column(row, col, data) workbook.close() # Function that will display the passed image in grayscale. The ref_array parameter must be in # a list in order for the function to work properly, even if it's a list of length one. This is so # that the function could be passed a list of multiple images to display if necessary. # NOTE: darker areas correspond to locations of lowest variance, not highest def show_image(ref_array): for x in range(len(ref_array)): out_array = ref_array[x].copy() plt.imshow(out_array, cmap='gray', vmin=0, vmax=255) plt.show() # This function calculates the coefficient of variation (CoV) for each pixel # in the set of images passed. def coefficient_of_variation(reference_images, number_of_images): sum_image = np.empty([int(RESOLUTION_HEIGHT * 0.5), int(RESOLUTION_WIDTH * 0.5)]) i = 0 for x in reference_images: sum_image = sum_image + x mean_reference = sum_image / float(number_of_images) std_dev = np.empty([int(RESOLUTION_HEIGHT * 0.5), int(RESOLUTION_WIDTH * 0.5)]) cov = np.empty([int(RESOLUTION_HEIGHT * 0.5), int(RESOLUTION_WIDTH * 0.5)]) x = 0 while x < RESOLUTION_HEIGHT * 0.5: y = 0 while y < RESOLUTION_WIDTH * 0.5: my_vars = [] z = 0 while z < len(reference_images): var_name = reference_images[z][x][y] my_vars.append(var_name) z += 1 std_dev[x][y] = np.std(my_vars) y += 1 x += 1 cov = std_dev / mean_reference * 100.0 return cov # This function trims the image from its original resolution to a smaller resolution. # It cuts 25% of the image off on either side and the top and bottom. def trim_image(reference_images): zoomed_images = [] single_image = np.empty([int(RESOLUTION_HEIGHT * 0.5), int(RESOLUTION_WIDTH * 0.5)]) x = 0 while x < len(reference_images): y = int(RESOLUTION_HEIGHT * 0.25) j = 0 while y < RESOLUTION_HEIGHT * 0.75: z = int(RESOLUTION_WIDTH * 0.25) k = 0 while z < RESOLUTION_WIDTH * 0.75: single_image[j][k] = reference_images[x][y][z] z += 1 k += 1 y += 1 j += 1 x += 1 zoomed_images.append(single_image.copy()) return zoomed_images def main(): if TEST_CASE: ambient_light_image, reference_images = ordered_import_images(TEMPORAL_FILEPATH) normalized_reference = normalize_for_exposure(ambient_light_image, reference_images) # The two commented lines below can be uncommented if the user wishes to examine the normalized values # of the images returned by normalize_for_exposure() # write_to_excel(normalized_reference, TEMPORAL_FILEPATH) # show_image(normalized_reference) cov = coefficient_of_variation(normalized_reference, len(normalized_reference)) listr = [cov] # Array must be held inside a list for the write_to_excel() and show_image() functions write_to_excel(listr, TEMPORAL_FILEPATH) show_image(listr) elif not TEST_CASE: reference_images = import_images(SPATIAL_FILEPATH) zoomed_images = trim_image(reference_images) cov = coefficient_of_variation(zoomed_images, len(zoomed_images)) listr = [cov] # Array must be held inside a list for the write_to_excel() and show_image() functions write_to_excel(listr, SPATIAL_FILEPATH) show_image(listr) main()
About
No description, website, or topics provided.
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published