diff --git a/alignment.py b/alignment.py new file mode 100644 index 0000000000000000000000000000000000000000..3c429bcd303895ccc673aeb39121683bac2e98e1 --- /dev/null +++ b/alignment.py @@ -0,0 +1,381 @@ +import cv2 +import time +from UPICCO_new import * +import os +import numpy as np + +global prev_similarity, count_m1 , count_m2 , similarity_difference, step_motor_2 + +prev_similarity = 0 +step_motor = 0 +step_motor_2 = 0 +count_m2 = 0 +count_m1 = 0 +motor2 = 0 + +def del_files(): + """ + This function deletes files from a specified folder if there are more than 10 files in the folder. + """ + if os.path.exists(proc_folder): + file_list = os.listdir(proc_folder) + file_count = len(file_list) + if file_count > 10: + + for file_name in file_list: + file_path = os.path.join(proc_folder, file_name) + os.remove(file_path) + +def func_UPICCO_l2_plus(left_2): + """ + This function, func_UPICCO_l2_plus moves the second motor of a UPICCO device a given number of steps to the left. + + Functionality: + + Initializes a picco object from the UPICCO class. + Updates the global variable step_motor_2 by subtracting left_2. + Moves the second motor to the updated position using the move_absolute() method of the picco object. + Sets the velocity of the second motor to 1000 using the set_velocity() method of the picco object. + Prints the current positions of the motors using the positions attribute of the picco object. + Closes the picco object. + + Inputs: + + left_2: integer representing the number of steps to move the motor to the left. + """ + global step_motor_2 + print(prev_similarity, similarity) + picco = UPICCO() + step_motor_2 = step_motor_2 - left_2 + + picco.move_absolute(2, step_motor_2) + print(picco.set_velocity(2, 1000)) + print(picco.positions) + + picco.close() + +def func_UPICCO_l1_plus(left_1): + """ + This function, func_UPICCO_l1_plus moves the first motor of a UPICCO device a given number of steps to the left. + + Functionality: + + Initializes a picco object from the UPICCO class. + Updates the global variable step_motor_1 by subtracting left_1. + Moves the second motor to the updated position using the move_absolute() method of the picco object. + Sets the velocity of the second motor to 1000 using the set_velocity() method of the picco object. + Prints the current positions of the motors using the positions attribute of the picco object. + Closes the picco object. + + Inputs: + + left_1: integer representing the number of steps to move the motor to the left. + """ + global step_motor + print(prev_similarity, similarity) + picco = UPICCO() + step_motor = step_motor - left_1 + + picco.move_absolute(1, step_motor) + print(picco.set_velocity(1, 1000)) + print(picco.positions) + + picco.close() + +def func_UPICCO_l1(left_m1): + """ + This function, func_UPICCO_l1 moves the first motor of a UPICCO device a given number of steps to the left. + + Functionality: + + Initializes a picco object from the UPICCO class. + Updates the global variable step_motor_1 by subtracting left_m1. + Moves the second motor to the updated position using the move_absolute() method of the picco object. + Sets the velocity of the second motor to 1000 using the set_velocity() method of the picco object. + Prints the current positions of the motors using the positions attribute of the picco object. + Closes the picco object. + + Inputs: + + left_m1: integer representing the number of steps to move the motor to the left. + """ + global step_motor + print(prev_similarity, similarity) + picco = UPICCO() + step_motor = step_motor - num_steps + step_motor = step_motor - left_m1 + + picco.move_absolute(1, step_motor) + print(picco.set_velocity(1, 1000)) + print(picco.positions) + + picco.close() + +def func_UPICCO_l2(left_m2): + """ + This function func_UPICCO_l2, moves the first motor of a UPICCO device a given number of steps to the left. + + Functionality: + + Initializes a picco object from the UPICCO class. + Updates the global variable step_motor_2 by subtracting left_m2. + Moves the second motor to the updated position using the move_absolute() method of the picco object. + Sets the velocity of the second motor to 1000 using the set_velocity() method of the picco object. + Prints the current positions of the motors using the positions attribute of the picco object. + Closes the picco object. + + Inputs: + + left_m2: integer representing the number of steps to move the motor to the left. + """ + global step_motor_2 + print(prev_similarity, similarity) + + picco = UPICCO() + step_motor_2 = step_motor_2 - num_steps_2 + step_motor_2 = step_motor_2 - left_m2 + + picco.move_absolute(2, step_motor_2) + print(picco.set_velocity(2, 1000)) + print(picco.positions) + + picco.close() + +def func_UPICCO_r1(num_steps): + """ + This function func_UPICCO_r1, moves the first motor of a UPICCO device a given number of steps to the right. + + Functionality: + + Initializes a picco object from the UPICCO class. + Updates the global variable step_motor_1 by subtracting num_steps. + Moves the second motor to the updated position using the move_absolute() method of the picco object. + Sets the velocity of the second motor to 1000 using the set_velocity() method of the picco object. + Prints the current positions of the motors using the positions attribute of the picco object. + Closes the picco object. + + Inputs: + + num_steps: integer representing the number of steps to move the motor to the right. + """ + global step_motor + picco = UPICCO() + print(prev_similarity, similarity) + + step_motor = step_motor + num_steps + + picco.move_absolute(1, step_motor) + print(picco.set_velocity(1, 1000)) + print(picco.positions) + + picco.close() + +def func_UPICCO_r2(num_steps_2): + global step_motor_2,step_motor + picco = UPICCO() + print(prev_similarity, similarity) + + step_motor = step_motor + left_1 + step_motor_2 = step_motor_2 + num_steps_2 + + picco.move_absolute(2, step_motor_2) + picco.move_absolute(1, step_motor) + print(picco.set_velocity(2, 1000)) + print(picco.positions) + + picco.close() + +def compare(): + """ + The compare() function compares the latest image from a folder to a set of template images using cross-correlation, and then moves two motors based on the similarity value between the images. + + ssim_values: a list that holds the similarity values between the latest image and all the template images + similarity: the maximum similarity value found in the ssim_values list + prev_similarity: the similarity value from the previous iteration of the function + similarity_difference: the difference between the current similarity value and the threshold of 0.99 + left_m1: the number of steps that the first motor should move (when moving to the left) + left_1: the number of steps that the first motor should move (when moving to the left after the second motor has moved) + left_m2: the number of steps that the second motor should move (when moving to the left) + num_steps: the number of steps that the first motor should move (when moving to the right) + num_steps_2: the number of steps that the second motor should move (when moving to the right) + """ + global ssim_values, similarity, prev_similarity,count_m2 ,count_m1, motor2, num_steps, similarity_difference, left_m1, left_1,num_steps_2, left_m2, left_2 + + img2 = cv2.imread(output_filenames[-1]) + ssim_values = [] + + for i in range(len(output_filenames_al)): + img1 = cv2.imread(output_filenames_al[i]) + + if img1 is not None and img2 is not None: + img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) + img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) + corr = cv2.matchTemplate(img1_gray, img2_gray, cv2.TM_CCORR_NORMED) + ssim_values.append(corr[0][0]) + + similarity = max(ssim_values) + similarity_difference = abs(0.99 - similarity) + print(similarity) + + if similarity < 0.95 and similarity > prev_similarity and (count_m1 == 0 or count_m1 % 2 == 0): # motor 1 + num_steps = similarity_difference * 100 + if similarity > 0.94: + num_steps = similarity_difference * 500 + print(num_steps) + func_UPICCO_r1(num_steps) + prev_similarity = similarity + count_m1 = count_m1 + 2 # increase the counter to check what motions the motor has done + + elif similarity < 0.95 and similarity < prev_similarity and (count_m1 == 2 or count_m1 % 2 == 0): # alli katefthinsi gia motor 1 + left_m1 = similarity_difference * 100 + if similarity > 0.94: # set minimun step around 5 if the similarity is < 0.95 + left_m1 = similarity_difference * 500 + print(left_m1) + func_UPICCO_l1(left_m1) + prev_similarity = similarity + count_m1 = count_m1 + 3 + motor2 = count_m1 # counter to start moving the motor 2 bc motor 1 didnt increase the similarity + + elif similarity < 0.95 and similarity > prev_similarity and (count_m1 == 5 or count_m1 % 2 == 1): + left_1 = similarity_difference * 100 + if similarity > 0.94: + left_1 = similarity_difference * 500 + print(left_1) + func_UPICCO_l1_plus(left_1) + prev_similarity = similarity + count_m1 = count_m1 + 2 + + elif similarity < 0.95 and similarity < prev_similarity and motor2 > 0: # motor 2 + num_steps_2 = similarity_difference * 100 + if similarity > 0.94: + num_steps_2 = similarity_difference * 500 + print(num_steps_2) + func_UPICCO_r2(num_steps_2) + prev_similarity = similarity + count_m2 = count_m2 + 2 + + elif similarity < 0.95 and similarity > prev_similarity and (count_m2 == 2 or count_m2 %2 == 0) : + num_steps_2 = similarity_difference * 100 + if similarity > 0.94: + num_steps_2 = similarity_difference * 500 + print(num_steps_2) + func_UPICCO_r2(num_steps_2) + prev_similarity = similarity + count_m2 = count_m2 + 2 + + elif similarity < 0.95 and similarity < prev_similarity and (count_m2 == 2 or count_m2 %2 == 0) : # alli katefthisi motor 2 + left_m2 = similarity_difference * 100 + if similarity > 0.94: + left_m2 = similarity_difference * 500 + print(left_m2) + func_UPICCO_l2(left_m2) + prev_similarity = similarity + count_m2 = count_m2 + 3 + + elif similarity < 0.95 and similarity > prev_similarity and (count_m2 == 5 or count_m2 % 2 == 1): + left_2 = similarity_difference * 100 + if similarity > 0.94: + left_2 = similarity_difference * 500 + print(left_2) + func_UPICCO_l2_plus(left_2) + prev_similarity = similarity + count_m2 = count_m2 + 3 + +def first_image(): + """ + this function takes care of preprocessing and saving the most recent image from the specified folder, so that it can be used for further image processing + """ + + global output_filename, folder_path, latest_file,final_image, output_filenames, proc_folder + + folder_path = fr"C:\Users\{os.getlogin()}\Desktop\image_input" + files = os.listdir(folder_path) + files.sort(key=lambda x: os.path.getmtime(os.path.join(folder_path, x))) + latest_file = files[-1] + + image_path = os.path.join(folder_path, latest_file) + image = cv2.imread(image_path,cv2.IMREAD_GRAYSCALE) + + image = cv2.normalize(image, None, min_val, max_val, cv2.NORM_MINMAX) # normalize the first image according to the template images + # image = 255 - image + + proc_folder = "proc_folder" + if not os.path.exists(proc_folder): + os.mkdir(proc_folder) + + final_image = cv2.resize(image, target_size) + output_filename = os.path.join(proc_folder,os.path.splitext(latest_file)[0] + "_processed.jpg") + cv2.imwrite(output_filename, final_image) + + output_filenames = [] + output_filenames.append(output_filename) + +def aligned(): + """ + this function takes a list of template image files, normalizes them, resizes them, and saves them as .png files. It then stores the output filenames in a global variable output_filenames_al + + Normalization is done by finding the minimum and maximum pixel values for each image, and then using cv2.normalize() to scale the pixel values to a new range (min_val to max_val) specified by the global variables. + Resizing is done based on the dimensions of each template image. + """ + + global min_val, max_val, target_size, output_filenames_al + + image_files = ["snapshot_58.jpg","snapshot_9.jpg","snapshot_10.jpg","snapshot_11.jpg","empty0.jpg","empty1.jpg","empty2.jpg", "empty3.jpg", "snapshot_3.jpg", "snapshot_5.jpg", "snapshot_7.jpg"] + min_vals = [] + max_vals = [] + + for filename in image_files: + image = cv2.imread(filename, cv2.IMREAD_GRAYSCALE) + min_val = np.min(image) + max_val = np.max(image) + min_vals.append(min_val) + max_vals.append(max_val) # find min, max value for normalization + + min_val = max(min_vals) + max_val = min(max_vals) + + output_filenames_al = [] + for filename in image_files: + image = cv2.imread(filename, 0) + + image = cv2.normalize(image, None, min_val, max_val, cv2.NORM_MINMAX) + # image = 255 - image + target_size = (image.shape[1], image.shape[0]) + + output_filename_al = os.path.splitext(filename)[0] + "_aligned.png" + cv2.imwrite(output_filename_al, image) + output_filenames_al.append(output_filename_al) + +aligned() +first_image() +compare() + +while True: + """ + The while loop checks for new images in the specified folder continuously. + If a new image is detected, the image is normalized and resized according to the template images. The final processed image is then saved as a .jpg file and the file name is appended to the output_filenames list. + The compare function is then called to compare the newly processed image with the template images. The loop continues to run, checking for new images every second. + """ + + files = os.listdir(folder_path) + files.sort(key=lambda x: os.path.getmtime(os.path.join(folder_path, x))) + + if files[-1] != latest_file: + latest_file = files[-1] + + image_path = os.path.join(folder_path, latest_file) + image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) + + image = cv2.normalize(image, None, min_val, max_val, cv2.NORM_MINMAX) # normalize the new image according to the template images + # image = 255 - image + + final_image = cv2.resize(image, target_size) + + output_filename = os.path.join(proc_folder,os.path.splitext(latest_file)[0] + "_processed.jpg") + cv2.imwrite(output_filename, final_image) + output_filenames.append(output_filename) + + compare() + del_files() + + time.sleep(1)