|
1 | 1 | #!/usr/bin/env dls-python |
2 | 2 | from adPythonPlugin import AdPythonPlugin |
3 | 3 |
|
| 4 | +from inspect import getargspec |
4 | 5 | from itertools import chain |
5 | 6 | import numpy as np |
6 | 7 | import cv2 |
7 | 8 |
|
8 | 9 |
|
9 | | -# Use thin wrapper functions around cv2 operations because we want a unified |
10 | | -# interface (fn(arr, params)) to more easily expose the functions to the user. |
| 10 | +# Unify the interface to morphological operations using a decorator such that |
| 11 | +# all operations are called as `fn(arr, (param1, param2, ...))`. This makes it |
| 12 | +# easier to expose functions with different numbers of arguments to the end |
| 13 | +# user in a generic way. |
11 | 14 |
|
12 | | -def erode(arr, params): |
13 | | - ksize, iterations = params[:2] |
| 15 | +def unified_interface(function): |
| 16 | + def wrapper(arr, params): |
| 17 | + n_params = len(getargspec(function).args) - 1 # (arr is not a param.) |
| 18 | + required_params = params[:n_params] # Throw away unwanted params. |
| 19 | + return function(arr, *required_params) |
| 20 | + return wrapper |
| 21 | + |
| 22 | + |
| 23 | +@unified_interface |
| 24 | +def erode(arr, ksize, iterations): |
14 | 25 | element = cv2.getStructuringElement(cv2.MORPH_RECT, (ksize, ksize)) |
15 | 26 | return cv2.erode(arr, element, iterations=iterations) |
16 | 27 |
|
17 | 28 |
|
18 | | -def dilate(arr, params): |
19 | | - ksize, iterations = params[:2] |
| 29 | +@unified_interface |
| 30 | +def dilate(arr, ksize, iterations): |
20 | 31 | element = cv2.getStructuringElement(cv2.MORPH_RECT, (ksize, ksize)) |
21 | 32 | return cv2.dilate(arr, element, iterations=iterations) |
22 | 33 |
|
23 | 34 |
|
24 | 35 | # `_morph` suffix to avoid name collision. |
25 | | -def open_morph(arr, params): |
26 | | - ksize, iterations = params[:2] |
| 36 | +@unified_interface |
| 37 | +def open_morph(arr, ksize, iterations): |
27 | 38 | element = cv2.getStructuringElement(cv2.MORPH_RECT, (ksize, ksize)) |
28 | 39 | return cv2.morphologyEx( |
29 | 40 | arr, cv2.MORPH_OPEN, element, iterations=iterations) |
30 | 41 |
|
31 | 42 |
|
32 | | -def close(arr, params): |
33 | | - ksize, iterations = params[:2] |
| 43 | +@unified_interface |
| 44 | +def close(arr, ksize, iterations): |
34 | 45 | element = cv2.getStructuringElement(cv2.MORPH_RECT, (ksize, ksize)) |
35 | 46 | return cv2.morphologyEx( |
36 | 47 | arr, cv2.MORPH_CLOSE, element, iterations=iterations) |
37 | 48 |
|
38 | 49 |
|
39 | | -def gradient(arr, params): |
40 | | - ksize, iterations = params[:2] |
| 50 | +@unified_interface |
| 51 | +def gradient(arr, ksize, iterations): |
41 | 52 | element = cv2.getStructuringElement(cv2.MORPH_RECT, (ksize, ksize)) |
42 | 53 | return cv2.morphologyEx( |
43 | 54 | arr, cv2.MORPH_GRADIENT, element, iterations=iterations) |
44 | 55 |
|
45 | 56 |
|
46 | | -def top_hat(arr, params): |
47 | | - ksize, iterations = params[:2] |
| 57 | +@unified_interface |
| 58 | +def top_hat(arr, ksize, iterations): |
48 | 59 | element = cv2.getStructuringElement(cv2.MORPH_RECT, (ksize, ksize)) |
49 | 60 | return cv2.morphologyEx( |
50 | 61 | arr, cv2.MORPH_TOPHAT, element, iterations=iterations) |
51 | 62 |
|
52 | 63 |
|
53 | | -def black_hat(arr, params): |
54 | | - ksize, iterations = params[:2] |
| 64 | +@unified_interface |
| 65 | +def black_hat(arr, ksize, iterations): |
55 | 66 | element = cv2.getStructuringElement(cv2.MORPH_RECT, (ksize, ksize)) |
56 | 67 | return cv2.morphologyEx( |
57 | 68 | arr, cv2.MORPH_BLACKHAT, element, iterations=iterations) |
58 | 69 |
|
59 | 70 |
|
60 | | -def blur(arr, params): |
61 | | - # The comma is necessary. (It unpacks the tuple.) |
62 | | - ksize, = params[:1] |
| 71 | +@unified_interface |
| 72 | +def blur(arr, ksize): |
63 | 73 | return cv2.blur(arr, (ksize, ksize)) |
64 | 74 |
|
65 | 75 |
|
66 | | -def gaussian_blur(arr, params): |
67 | | - ksize, = params[:1] |
| 76 | +@unified_interface |
| 77 | +def gaussian_blur(arr, ksize): |
68 | 78 | # Kernel size should be odd. |
69 | | - if not ksize % 2: |
70 | | - ksize += 1 |
| 79 | + if not ksize % 2: ksize += 1 |
71 | 80 | return cv2.GaussianBlur(arr, (ksize, ksize), 0) |
72 | 81 |
|
73 | 82 |
|
74 | | -def median_blur(arr, params): |
75 | | - ksize, = params[:1] |
76 | | - if not ksize % 2: |
77 | | - ksize += 1 |
| 83 | +@unified_interface |
| 84 | +def median_blur(arr, ksize): |
| 85 | + if not ksize % 2: ksize += 1 |
78 | 86 | return cv2.medianBlur(arr, ksize) |
79 | 87 |
|
80 | 88 |
|
81 | | -def canny_edge_detect(arr, params): |
82 | | - upper_threshold, lower_threshold = params[:2] |
83 | | - |
84 | | - # Upper and lower threshold arguments commute. |
| 89 | +@unified_interface |
| 90 | +def canny_edge_detect(arr, upper_threshold, lower_threshold): |
| 91 | + # (Upper and lower threshold arguments commute.) |
85 | 92 | return cv2.Canny(arr, upper_threshold, lower_threshold) |
86 | 93 |
|
87 | 94 |
|
|
0 commit comments