optiklear 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
optiklear/__init__.py ADDED
File without changes
optiklear/conv.py ADDED
@@ -0,0 +1,103 @@
1
+ import math
2
+
3
+ def rotate_kernel(h):
4
+
5
+ for i in h:
6
+ i.reverse()
7
+
8
+ h.reverse()
9
+ return h
10
+
11
+ def get_kernel_mid(h):
12
+
13
+ h_length = len(h)
14
+
15
+ h_mid_arr = math.floor(h_length / 2)
16
+ mid_idx = math.floor(len(h[h_mid_arr]) / 2)
17
+
18
+ return h_mid_arr, mid_idx
19
+
20
+ def pad_matrix(h, B):
21
+
22
+ h = rotate_kernel(h)
23
+
24
+ row_count = len(h)
25
+ col_count = len(h[0])
26
+
27
+ side_pad = (col_count - 1) // 2
28
+ across_pad = (row_count - 1) // 2
29
+
30
+ # Side Padding
31
+ for i in range(len(B)):
32
+ for j in range(side_pad):
33
+ B[i].append([0, 0, 0])
34
+ B[i].insert(0, [0, 0, 0])
35
+
36
+ # Create top/bottom padding row
37
+ my_pad = [[0, 0, 0] for i in range(len(B[0]))]
38
+
39
+ # Top and bottom padding
40
+ for i in range(across_pad):
41
+ B.insert(0, my_pad.copy())
42
+ B.append(my_pad.copy())
43
+
44
+ return h, B
45
+
46
+ def convolution(h, B):
47
+
48
+ # Rotate kernel and pad B
49
+ h, B = pad_matrix(h, B)
50
+
51
+ # Get kernel midpoint indexes
52
+ h_mid_arr, mid_idx = get_kernel_mid(h)
53
+
54
+ output = []
55
+
56
+ # Move the kernel across B
57
+ for i in range(h_mid_arr, len(B) - h_mid_arr):
58
+
59
+ row = []
60
+
61
+ for j in range(mid_idx, len(B[i]) - mid_idx):
62
+
63
+ total_B = 0
64
+ total_G = 0
65
+ total_R = 0
66
+
67
+
68
+ # Multiply kernel elements with B elements
69
+ for k in range(len(h)):
70
+
71
+ for l in range(len(h[k])):
72
+
73
+ pixel = B[i - h_mid_arr + k][j - mid_idx + l]
74
+
75
+ total_B += pixel[0] * h[k][l]
76
+ total_G += pixel[1] * h[k][l]
77
+ total_R += pixel[2] * h[k][l]
78
+
79
+
80
+ row.append([total_B, total_G, total_R])
81
+
82
+ output.append(row)
83
+
84
+ return output
85
+
86
+ # Client Code
87
+ '''
88
+ result = convolution(
89
+ [
90
+ [1/9, 1/9, 1/9],
91
+ [1/9, 1/9, 1/9],
92
+ [1/9, 1/9, 1/9]
93
+ ],
94
+ [
95
+ [1, 0, 1, 2, 2],
96
+ [1, 1, 2, 2, 3],
97
+ [1, 2, 2, 6, 3],
98
+ [1, 1, 2, 2, 3]
99
+ ]
100
+ )
101
+
102
+ print(result)
103
+ '''
optiklear/mat_trans.py ADDED
@@ -0,0 +1,418 @@
1
+ import numpy as np
2
+ from math import *
3
+
4
+
5
+
6
+
7
+ def matmax_multiply(A, B):
8
+
9
+ C = [
10
+ [
11
+ sum(A[i][j] * B[j][k] for j in range(len(B)))
12
+ for k in range(len(B[0]))
13
+ ]
14
+ for i in range(len(A))
15
+ ]
16
+
17
+ return C
18
+
19
+
20
+ # --------------------------------------------------
21
+ # HORIZONTAL SHEAR
22
+ # --------------------------------------------------
23
+
24
+ def horizontal_shear2D(image, k):
25
+
26
+ A = [
27
+ [1, k],
28
+ [0, 1]
29
+ ]
30
+
31
+ height = image.shape[0]
32
+ width = image.shape[1]
33
+
34
+ new_width = width + int(abs(k) * height)
35
+ new_height = height
36
+
37
+ transformed_image = np.zeros(
38
+ (new_height, new_width, image.shape[2]),
39
+ dtype=image.dtype
40
+ )
41
+
42
+ for row in range(height):
43
+
44
+ for col in range(width):
45
+
46
+ coordinate = [
47
+ [col],
48
+ [row]
49
+ ]
50
+
51
+ new_coordinate = matmax_multiply(A, coordinate)
52
+
53
+ new_col = int(new_coordinate[0][0])
54
+ new_row = int(new_coordinate[1][0])
55
+
56
+ if 0 <= new_col < new_width and 0 <= new_row < new_height:
57
+
58
+ transformed_image[new_row, new_col] = image[row, col]
59
+
60
+ return transformed_image
61
+
62
+
63
+ # --------------------------------------------------
64
+ # VERTICAL SHEAR
65
+ # --------------------------------------------------
66
+
67
+ def vertical_shear2D(image, k):
68
+
69
+ A = [
70
+ [1, 0],
71
+ [k, 1]
72
+ ]
73
+
74
+ height = image.shape[0]
75
+ width = image.shape[1]
76
+
77
+ new_width = width
78
+ new_height = height + int(abs(k) * width)
79
+
80
+ transformed_image = np.zeros(
81
+ (new_height, new_width, image.shape[2]),
82
+ dtype=image.dtype
83
+ )
84
+
85
+ for row in range(height):
86
+
87
+ for col in range(width):
88
+
89
+ coordinate = [
90
+ [col],
91
+ [row]
92
+ ]
93
+
94
+ new_coordinate = matmax_multiply(A, coordinate)
95
+
96
+ new_col = int(new_coordinate[0][0])
97
+ new_row = int(new_coordinate[1][0])
98
+
99
+ if 0 <= new_col < new_width and 0 <= new_row < new_height:
100
+
101
+ transformed_image[new_row, new_col] = image[row, col]
102
+
103
+ return transformed_image
104
+
105
+
106
+ # --------------------------------------------------
107
+ # SCALING
108
+ # --------------------------------------------------
109
+
110
+ def scale2D(image, Sx, Sy):
111
+
112
+ A = [
113
+ [Sx, 0],
114
+ [0, Sy]
115
+ ]
116
+
117
+ height = image.shape[0]
118
+ width = image.shape[1]
119
+
120
+ new_width = int(width * abs(Sx))
121
+ new_height = int(height * abs(Sy))
122
+
123
+ transformed_image = np.zeros(
124
+ (new_height, new_width, image.shape[2]),
125
+ dtype=image.dtype
126
+ )
127
+
128
+ for row in range(height):
129
+
130
+ for col in range(width):
131
+
132
+ coordinate = [
133
+ [col],
134
+ [row]
135
+ ]
136
+
137
+ new_coordinate = matmax_multiply(A, coordinate)
138
+
139
+ new_col = int(new_coordinate[0][0])
140
+ new_row = int(new_coordinate[1][0])
141
+
142
+ if 0 <= new_col < new_width and 0 <= new_row < new_height:
143
+
144
+ transformed_image[new_row, new_col] = image[row, col]
145
+
146
+ return transformed_image
147
+
148
+
149
+
150
+ def clockwise_rotate2D(image, ang_deg):
151
+
152
+ theta = radians(ang_deg)
153
+
154
+ c = cos(theta)
155
+ s = sin(theta)
156
+
157
+ A = [
158
+ [c, -s],
159
+ [s, c]
160
+ ]
161
+
162
+ height = image.shape[0]
163
+ width = image.shape[1]
164
+
165
+ # Center of the original image
166
+ center_col = (width - 1) / 2
167
+ center_row = (height - 1) / 2
168
+
169
+ # Size of the rotated image
170
+ new_width = int(
171
+ abs(width * c) + abs(height * s)
172
+ )
173
+
174
+ new_height = int(
175
+ abs(height * c) + abs(width * s)
176
+ )
177
+
178
+ transformed_image = np.zeros(
179
+ (new_height, new_width, image.shape[2]),
180
+ dtype=image.dtype
181
+ )
182
+
183
+ # Center of the new image
184
+ new_center_col = (new_width - 1) / 2
185
+ new_center_row = (new_height - 1) / 2
186
+
187
+ for row in range(height):
188
+
189
+ for col in range(width):
190
+
191
+ # Move the pixel coordinate so that
192
+ # the image center becomes the origin
193
+ coordinate = [
194
+ [col - center_col],
195
+ [row - center_row]
196
+ ]
197
+
198
+ new_coordinate = matmax_multiply(A, coordinate)
199
+
200
+ rotated_col = new_coordinate[0][0]
201
+ rotated_row = new_coordinate[1][0]
202
+
203
+ # Move the coordinate back to the image
204
+ # and place it relative to the new image center
205
+ new_col = int(round(rotated_col + new_center_col))
206
+ new_row = int(round(rotated_row + new_center_row))
207
+
208
+ if 0 <= new_col < new_width and 0 <= new_row < new_height:
209
+
210
+ transformed_image[new_row, new_col] = image[row, col]
211
+
212
+ return transformed_image
213
+
214
+
215
+ def antiClockwise_rotate2D(image, ang_deg):
216
+
217
+ theta = radians(ang_deg)
218
+
219
+ c = cos(theta)
220
+ s = sin(theta)
221
+
222
+ A = [
223
+ [c, s],
224
+ [-s, c]
225
+ ]
226
+
227
+ height = image.shape[0]
228
+ width = image.shape[1]
229
+
230
+ # Center of the original image
231
+ center_col = (width - 1) / 2
232
+ center_row = (height - 1) / 2
233
+
234
+ # Size of the rotated image
235
+ new_width = int(
236
+ abs(width * c) + abs(height * s)
237
+ )
238
+
239
+ new_height = int(
240
+ abs(height * c) + abs(width * s)
241
+ )
242
+
243
+ transformed_image = np.zeros(
244
+ (new_height, new_width, image.shape[2]),
245
+ dtype=image.dtype
246
+ )
247
+
248
+ # Center of the new image
249
+ new_center_col = (new_width - 1) / 2
250
+ new_center_row = (new_height - 1) / 2
251
+
252
+ for row in range(height):
253
+
254
+ for col in range(width):
255
+
256
+ # Move the pixel coordinate so that
257
+ # the image center becomes the origin
258
+ coordinate = [
259
+ [col - center_col],
260
+ [row - center_row]
261
+ ]
262
+
263
+ new_coordinate = matmax_multiply(A, coordinate)
264
+
265
+ rotated_col = new_coordinate[0][0]
266
+ rotated_row = new_coordinate[1][0]
267
+
268
+ # Move the coordinate back to the image
269
+ # and place it relative to the new image center
270
+ new_col = int(round(rotated_col + new_center_col))
271
+ new_row = int(round(rotated_row + new_center_row))
272
+
273
+ if 0 <= new_col < new_width and 0 <= new_row < new_height:
274
+
275
+ transformed_image[new_row, new_col] = image[row, col]
276
+
277
+ return transformed_image
278
+
279
+
280
+
281
+ # --------------------------------------------------
282
+ # FLIP LEFT ↔ RIGHT
283
+ # Reflection about the Y-axis
284
+ # --------------------------------------------------
285
+
286
+ def flipX2D(image):
287
+
288
+ A = [
289
+ [-1, 0],
290
+ [0, 1]
291
+ ]
292
+
293
+ height = image.shape[0]
294
+ width = image.shape[1]
295
+
296
+ transformed_image = np.zeros(
297
+ image.shape,
298
+ dtype=image.dtype
299
+ )
300
+
301
+ for row in range(height):
302
+
303
+ for col in range(width):
304
+
305
+ coordinate = [
306
+ [col],
307
+ [row]
308
+ ]
309
+
310
+ new_coordinate = matmax_multiply(A, coordinate)
311
+
312
+ new_col = int(
313
+ new_coordinate[0][0] + (width - 1)
314
+ )
315
+
316
+ new_row = int(
317
+ new_coordinate[1][0]
318
+ )
319
+
320
+ if 0 <= new_col < width and 0 <= new_row < height:
321
+
322
+ transformed_image[new_row, new_col] = image[row, col]
323
+
324
+ return transformed_image
325
+
326
+
327
+ # --------------------------------------------------
328
+ # FLIP TOP ↔ BOTTOM
329
+ # Reflection about the X-axis
330
+ # --------------------------------------------------
331
+
332
+ def flipY2D(image):
333
+
334
+ A = [
335
+ [1, 0],
336
+ [0, -1]
337
+ ]
338
+
339
+ height = image.shape[0]
340
+ width = image.shape[1]
341
+
342
+ transformed_image = np.zeros(
343
+ image.shape,
344
+ dtype=image.dtype
345
+ )
346
+
347
+ for row in range(height):
348
+
349
+ for col in range(width):
350
+
351
+ coordinate = [
352
+ [col],
353
+ [row]
354
+ ]
355
+
356
+ new_coordinate = matmax_multiply(A, coordinate)
357
+
358
+ new_col = int(
359
+ new_coordinate[0][0]
360
+ )
361
+
362
+ new_row = int(
363
+ new_coordinate[1][0] + (height - 1)
364
+ )
365
+
366
+ if 0 <= new_col < width and 0 <= new_row < height:
367
+
368
+ transformed_image[new_row, new_col] = image[row, col]
369
+
370
+ return transformed_image
371
+
372
+
373
+
374
+ def translate2D(image, translation):
375
+
376
+ tx = translation[0]
377
+ ty = translation[1]
378
+
379
+ A = [
380
+ [1, 0],
381
+ [0, 1]
382
+ ]
383
+
384
+ height = image.shape[0]
385
+ width = image.shape[1]
386
+
387
+ transformed_image = np.zeros(
388
+ image.shape,
389
+ dtype=image.dtype
390
+ )
391
+
392
+ for row in range(height):
393
+
394
+ for col in range(width):
395
+
396
+ coordinate = [
397
+ [col],
398
+ [row]
399
+ ]
400
+
401
+ new_coordinate = matmax_multiply(A, coordinate)
402
+
403
+ new_col = int(
404
+ new_coordinate[0][0] + tx
405
+ )
406
+
407
+ new_row = int(
408
+ new_coordinate[1][0] + ty
409
+ )
410
+
411
+ if 0 <= new_col < width and 0 <= new_row < height:
412
+
413
+ transformed_image[new_row, new_col] = image[row, col]
414
+
415
+ return transformed_image
416
+
417
+
418
+
optiklear/mat_vec.py ADDED
@@ -0,0 +1,73 @@
1
+ from math import cos, radians, sin
2
+
3
+ # A is a transformation matrix
4
+ def matvec_multiply(A, x):
5
+ b = [ sum (x[j] * A[i][j] for j in range(len(x)))for i in range(len(A))]
6
+ return b
7
+
8
+ # u is a vector
9
+ def horizontal_shear2D(u, k):
10
+ # k is shear factor, u is vector
11
+ A = [[1, k], [0, 1]] # A is horizontal shear matrix
12
+ b = matvec_multiply(A, u)
13
+ return b
14
+ #print(horizontal_shear2D([0, 2], -1))
15
+
16
+ def vertical_shear2D(u, k):
17
+ A = [[1, 0], [k, 1]] # A is vertical shear matrix
18
+ b = matvec_multiply(A, u)
19
+ return b
20
+ #print(vertical_shear2D([2, 2], 1))
21
+
22
+
23
+ def scale2D(u, Sx, Sy):
24
+ #Sx and Sy are scalar constants
25
+ A = [[Sx, 0], [0, Sy]] # A is scale matrix
26
+ b = matvec_multiply(A, u)
27
+ return b
28
+ #print(scale([2, 2], 5, 0.5))
29
+
30
+ def clockwise_rotate2D(u, ang_deg):
31
+ theta = radians(ang_deg)
32
+ c = cos(theta)
33
+ s = sin(theta)
34
+
35
+ A = [[c, s],[-s, c]]
36
+
37
+ #A = [[cos(radians(ang_deg)), sin(radians(ang_deg))], [-sin(radians(ang_deg)), cos(radians(ang_deg))]]
38
+ b = matvec_multiply(A, u)
39
+ return b
40
+ #print(clockwise_rotate2D([1, 2], 30))
41
+
42
+
43
+ def antiClockwise_rotate2D(u, ang_deg):
44
+ # A = [[cos(radians(ang_deg)), -sin(radians(ang_deg))], [sin(radians(ang_deg)), cos(radians(ang_deg))]]
45
+ theta = radians(ang_deg)
46
+ c = cos(theta)
47
+ s = sin(theta)
48
+ A = [[c, -s],[s, c]]
49
+ b = matvec_multiply(A, u)
50
+ return b
51
+ #print(clockwise_rotate2D([1, 2], 30))
52
+
53
+ def flipX2D(u):
54
+ #reflect along the y-axis
55
+ A = [[-1, 0], [0, 1]]
56
+ b = matvec_multiply(A, u)
57
+ return b
58
+ #print(flipX2D([1, 2]))
59
+
60
+ def flipY2D(u):
61
+ #reflect along the x-axis
62
+ A = [[1, 0], [0, -1]]
63
+ b = matvec_multiply(A, u)
64
+ return b
65
+ #print(flipY2D([1, 2]))
66
+
67
+ def translate2D(u, translation):
68
+ # translation is a 2d vector
69
+ A = [[1, 0], [0, 1]]
70
+ b = matvec_multiply(A, u)
71
+ translated = [b[0] + translation[0], b[1] + translation[1]]
72
+ return translated
73
+ #print(translate2D([1, 2], [1, -1]))
optiklear/noise_gen.py ADDED
@@ -0,0 +1,45 @@
1
+ import random
2
+ import numpy as np
3
+ import copy
4
+
5
+
6
+ def unif_noise(image, lower, upper):
7
+ for i in range(image.shape[0]):
8
+ for j in range(image.shape[1]):
9
+ noise = random.uniform(lower, upper)
10
+ noisy_pixel = image[i, j] + noise
11
+ noisy_pixel = np.clip(noisy_pixel, 0, 255)
12
+ image[i, j] = np.uint8(np.round(noisy_pixel))
13
+
14
+ return image
15
+
16
+
17
+
18
+ def gauss_noise(image, std):
19
+ for i in range(image.shape[0]):
20
+ for j in range(image.shape[1]):
21
+ noise = random.gauss(mu=0.0, sigma=std)
22
+ noisy_pixel = image[i, j] + noise
23
+ noisy_pixel = np.clip(noisy_pixel, 0, 255)
24
+ image[i, j] = np.uint8(np.round(noisy_pixel))
25
+ return image
26
+
27
+
28
+
29
+
30
+ def salt_pepper_noise(image, prob_pepper, prob_salt):
31
+
32
+ copied_image = copy.deepcopy(image)
33
+
34
+ for i in range(len(copied_image)):
35
+ for j in range(len(copied_image[i])):
36
+
37
+ rand_num = random.random()
38
+
39
+ if rand_num < prob_pepper:
40
+ copied_image[i][j] = 0
41
+
42
+ elif rand_num > 1 - prob_salt:
43
+ copied_image[i][j] = 255
44
+
45
+ return copied_image
@@ -0,0 +1,83 @@
1
+ import copy
2
+
3
+
4
+ def pad_matrix(B, row_count, col_count):
5
+
6
+ window_size = row_count * col_count
7
+
8
+ side_pad = (col_count - 1) // 2
9
+ across_pad = (row_count - 1) // 2
10
+
11
+ # Side Padding
12
+ for i in range(len(B)):
13
+ for j in range(side_pad):
14
+ B[i].append([0, 0, 0])
15
+ B[i].insert(0, [0, 0, 0])
16
+
17
+ # Create top/bottom padding row
18
+ my_pad = [[0, 0, 0] for i in range(len(B[0]))]
19
+
20
+ # Top and bottom padding
21
+ for i in range(across_pad):
22
+ B.insert(0, my_pad.copy())
23
+ B.append(my_pad.copy())
24
+
25
+ return B, window_size
26
+
27
+
28
+ def med_filter(input_image, row_count, col_count):
29
+
30
+ # Make a copy so the original image is not modified
31
+ image_copy = copy.deepcopy(input_image)
32
+
33
+ # Pad the image
34
+ B, window_size = pad_matrix(
35
+ image_copy,
36
+ row_count,
37
+ col_count
38
+ )
39
+
40
+ output_image = []
41
+
42
+ # Move the window across B
43
+ for i in range(len(B) - row_count + 1):
44
+
45
+ row = []
46
+
47
+ for j in range(len(B[0]) - col_count + 1):
48
+
49
+ # Lists for the three RGB channels
50
+ red_values = []
51
+ green_values = []
52
+ blue_values = []
53
+
54
+ # Extract the window
55
+ for k in range(row_count):
56
+ for l in range(col_count):
57
+
58
+ pixel = B[i + k][j + l]
59
+
60
+ red_values.append(pixel[0])
61
+ green_values.append(pixel[1])
62
+ blue_values.append(pixel[2])
63
+
64
+ # Sort each channel
65
+ red_values.sort()
66
+ green_values.sort()
67
+ blue_values.sort()
68
+
69
+ # Get median of each channel
70
+ median_red = red_values[window_size // 2]
71
+ median_green = green_values[window_size // 2]
72
+ median_blue = blue_values[window_size // 2]
73
+
74
+ # Construct the output pixel
75
+ row.append([
76
+ median_red,
77
+ median_green,
78
+ median_blue
79
+ ])
80
+
81
+ output_image.append(row)
82
+
83
+ return output_image
@@ -0,0 +1,87 @@
1
+ import math
2
+
3
+ # Add more than 2 vectors
4
+ def add2D_multi(*vectors):
5
+ return (sum([v[0] for v in vectors]), sum([v[1] for v in vectors]))
6
+
7
+
8
+
9
+ def vec_add2D(u, v):
10
+ w = [u[0] + v[0], u[1] + v[1]]
11
+ return w
12
+ #print(vec_add([2, 4], [5, 10]))
13
+
14
+
15
+ def vec_subtract2D(u, v):
16
+ w = [u[0]- v[0], u[1] - v[1]]
17
+ return w
18
+
19
+
20
+ def mag_v2D(v):
21
+ # return math.floor(math.sqrt(v[0]**2 + v[1]**2))
22
+ return math.sqrt(v[0]**2 + v[1]**2)
23
+ #print(mag_v([5, 10]))
24
+
25
+ def dis_vecs2D(u, v):
26
+ return math.sqrt((v[0]-u[0])**2 + (v[1]-u[1])**2)
27
+
28
+
29
+
30
+ def dot_product2D(u, v):
31
+ uv = u[0] * v[0] + u[1] * v[1]
32
+ return uv
33
+
34
+
35
+
36
+ def ang_vectors2D(u, v):
37
+ uv = dot_product2D(u, v)
38
+ cos_val = uv/(mag_v2D(u) * mag_v2D(v))
39
+ ang_between = math.degrees(math.acos(cos_val))
40
+ return ang_between
41
+
42
+
43
+
44
+ def scale(weight, v):
45
+ v = [weight * i for i in v]
46
+ return v
47
+
48
+
49
+
50
+ # use for single polar coordinates
51
+ def pole_to_cart(radius, angle):
52
+ x = radius * math.cos(math.radians(angle))
53
+ y = radius * math.sin(math.radians(angle))
54
+ return (x, y)
55
+
56
+
57
+ def polar_vector_to_cart(polar_vector):
58
+ length, angle = polar_vector
59
+ return (length*math.cos(angle), length*math.sin(angle))
60
+
61
+ # use for single vector
62
+ def cart_to_pole(x, y):
63
+ radius = math.sqrt(x**2 + y**2)
64
+ # tan_theta = y/x
65
+ theta = math.atan2(y, x)
66
+ return (radius, theta)
67
+
68
+ # use for multiple vectors
69
+ def cart_to_polar(vector):
70
+ x, y = vector[0], vector[1]
71
+ angle = math.atan2(y,x)
72
+ return (mag_v2D(vector), angle)
73
+
74
+
75
+ def rotate(angle, vectors):
76
+ polars = [cart_to_polar(v) for v in vectors]
77
+ return [polar_vector_to_cart((length, a+angle)) for length,a in polars]
78
+
79
+
80
+ def translate(translation, vectors):
81
+ return [add2D_multi(translation, v) for v in vectors]
82
+
83
+
84
+ def cross_prod(u, v):
85
+ u_cross_v = [u[1]* v[2] - u[2] * v[1] , u[2] * v[0] - u[0] * v[2] , u[0] * v[1] - u[1] * v[0] ]
86
+ return u_cross_v
87
+ #print(cross_prod([1, 2, -1], [2, -1, 2]))
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.5
2
+ Name: optiklear
3
+ Version: 0.1.0
4
+ Summary: A Python library for mathematical operations and image processing
5
+ Requires-Python: >=3.10
6
+ Requires-Dist: numpy
7
+ Description-Content-Type: text/markdown
8
+
9
+ # OptiKlear
10
+
11
+ **OptiKlear** is a Python library for mathematical operations and digital image processing.
12
+
13
+ It provides reusable functions for vector operations, matrix-vector transformations, image transformations, noise generation and spatial filtering.
14
+
15
+ ## Features
16
+
17
+ Current functionality includes:
18
+
19
+ - **Convolution:** Spatial convolution for image filtering.
20
+ - **Nonlinear filtering:** Median filtering.
21
+ - **Noise generation:** Uniform, Gaussian and salt-and-pepper noise.
22
+ - **Geometric transformations:** Scaling, rotation, shearing, flipping and translation.
23
+ - **Matrix-vector operations:** Matrix multiplication and 2D vector transformations.
24
+ - **Vector operations:** Vector addition, subtraction, magnitude, distance, dot product, cross product and rotation.
25
+
26
+ ## Installation
27
+
28
+ Install OptiKlear using pip:
29
+
30
+ ```bash
31
+ pip install optiklear
32
+ ```
33
+
34
+ **Note:** OptiKlear is currently under development. The package will be available on PyPI following its initial release.
35
+
36
+ ## Requirements
37
+
38
+ - Python 3.10 or later
39
+ - NumPy
40
+
41
+ ## Package Structure
42
+
43
+ | Module | Description |
44
+ |---|---|
45
+ | `conv` | Convolution operations |
46
+ | `non_linear` | Nonlinear image filtering |
47
+ | `noise_gen` | Image noise generation |
48
+ | `mat_trans` | 2D image transformations |
49
+ | `mat_vec` | Matrix-vector operations and transformations |
50
+ | `vec_operations` | Mathematical vector operations |
51
+
52
+ ## Usage
53
+
54
+ Import individual functions from their respective modules.
55
+
56
+ For example, to use vector operations:
57
+
58
+ ```python
59
+ from optiklear.vec_operations import vec_add2D, mag_v2D
60
+
61
+ u = [3, 4]
62
+ v = [2, 5]
63
+
64
+ result = vec_add2D(u, v)
65
+ magnitude = mag_v2D(u)
66
+
67
+ print(result)
68
+ print(magnitude)
69
+ ```
70
+
71
+ To use image noise generation:
72
+
73
+ ```python
74
+ from optiklear.noise_gen import gauss_noise
75
+
76
+ noisy_image = gauss_noise(image, 9)
77
+ ```
78
+
79
+ The image-processing functions currently use NumPy arrays and/or Python lists according to their individual implementations. Check each function's input requirements before use.
80
+
81
+ ## Development Roadmap
82
+
83
+ Planned additions for future versions include:
84
+
85
+ - Point operations
86
+ - Edge detection
87
+
@@ -0,0 +1,10 @@
1
+ optiklear/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ optiklear/conv.py,sha256=sfds5VAoO_cDkZTLRDsO0UzoDPGmpd7dbZnD_AzhWqc,1991
3
+ optiklear/mat_trans.py,sha256=YpQ_TsQ_TvcJDMahM54zXzF6Hny8pCXCQkozDNlowJw,8854
4
+ optiklear/mat_vec.py,sha256=2u_Krzng3yad_gQzJQloJTD12CpIbbUghrivDjjD6i0,1898
5
+ optiklear/noise_gen.py,sha256=SRtmN2m0tnUruHwA7Q3LHYlpSmNaRMZaeupqUaBqLwk,1147
6
+ optiklear/non_linear.py,sha256=wDjX_QzgGjBvdhUQvAGQsHlJutgjBbQUoh86DXBkra0,2016
7
+ optiklear/vec_operations.py,sha256=TSfe-CR-GhQXGnATMm3iHJSXxf28Eapma_e2b-b0840,1946
8
+ optiklear-0.1.0.dist-info/METADATA,sha256=d9aq_mnRtMJVVRxun1BzfSgv2go757PQi-MUVGf8yY4,2272
9
+ optiklear-0.1.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
10
+ optiklear-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any