1"""
2img_to_path_2.py
3Andrew Lorimer, January 2025
4Monash University
5
6Converts a path in a monochrome image to a series of points
7in a defined format for laser writing with the confocal
8setup. Configuration is done in img_to_path.ini. This version
9for use with write_path.py (Python).
10"""
11
12import configparser as cp
13import cv2
14import numpy as np
15import sys
16import matplotlib.pyplot as plt
17import write_path
18from pipython import datarectools, pitools
19import nidaqmx
20import pipython
21import time
22
23DEFAULTS = {'dimensions': '100, 100',
24 'z': '0',
25 'n_levels': '10',
26 'pitch': 1,
27 'black_exposure': '1'}
28DEFAULT_CONFIG_PATH = "img_to_path_2.ini"
29
30if __name__ == "__main__":
31
32 # Get config file path from arguments or use default path
33 if len(sys.argv) > 1 and sys.argv[1]:
34 config_path = sys.argv[1]
35 else:
36 config_path = DEFAULT_CONFIG_PATH
37
38 # Set up config parser
39 config = cp.ConfigParser()
40 config['DEFAULT'] = DEFAULTS
41 config.read_file(open(config_path))
42
43 # Set config values
44 real_dim = np.fromstring(config.get('Main', 'dimensions'), dtype=float, sep=",")
45 z = config.getfloat('Main', 'z')
46 n_levels = int(config.getfloat('Main', 'n_levels'))
47 pitch = config.getfloat('Main', 'pitch')
48 black_exposure = config.getfloat('Main', 'black_exposure')
49 input_path = config.get('Main', 'input')
50
51 # Read image
52 im = cv2.imread(input_path, cv2.IMREAD_GRAYSCALE)
53 im_dim = im.shape
54
55 # Check if aspect ratios match
56 if (im_dim[0] / im_dim[1] != real_dim[0]/real_dim[1]):
57 print("Warning: input and output aspect ratios do not match - result will be distorted")
58
59 # Convert image to defined number of levels
60 im = im // (255/n_levels)
61
62 # Upsample/downsample image for the writing resolution
63 n_points = real_dim / pitch
64 n_points = n_points.astype(int)
65 im = cv2.resize(im, (int(n_points[0]), int(n_points[1])), interpolation=cv2.INTER_CUBIC)
66
67 # Expand dynamic range
68 im = (im - im.min()) * 255/(im.max()-im.min())
69 # Display image
70 fig, ax = plt.subplots()
71 ax.imshow(im, cmap='gray')
72 plt.show()
73
74 print("Min: {}, Max: {}".format(im.min(), im.max()))
75
76 min_exposure = 0.1
77 #exposure_times = (100**((n_levels - im)/n_levels) - (1 - min_exposure)) * black_exposure / (100 - (1 - min_exposure))
78 p = 1
79 #exposure_times = (black_exposure / min_exposure)**(((n_levels - im)/n_levels)**p) * min_exposure
80 exposure_times = -(black_exposure - min_exposure)/n_levels * im + black_exposure
81 fig, ax = plt.subplots()
82 ax.imshow(exposure_times, cmap='gray')
83 plt.show()
84
85 print("Min: {}, Max: {}".format(exposure_times.min(), exposure_times.max()))
86
87 cont = input("Write image? (y/n): ")
88
89 if cont.lower() != 'y':
90 sys.exit()
91
92 print("Writing image")
93
94 task, pidevice = write_path.setup()
95
96 start_x = 0
97 start_y = 3
98 pidevice.MOV({1: start_x, 2: start_y, 3: z})
99
100
101 try:
102 for i in range(34, n_points[0]):
103 for j in range(n_points[1]):
104 pidevice.MOV({1: i*pitch+start_x, 2: j*pitch+start_y})
105 pitools.waitontarget(pidevice, [1, 2])
106 time.sleep(0.1)
107 exposure_time = exposure_times[i, j]
108 print(exposure_time)
109 if exposure_time >= min_exposure:
110 task.write(True)
111 time.sleep(exposure_time)
112 task.write(False)
113 time.sleep(0.1)
114 finally:
115 print("Exiting")
116 pidevice.MOV({1: start_x, 2: start_y, 3: z})
117 pitools.waitontarget(pidevice, [1, 2])
118 pitools.stopall(pidevice)
119 task.write(False)
120 task.close()
121
122