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)