assembly-opencv 1.0.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.
@@ -0,0 +1,190 @@
1
+ import cv2
2
+ import numpy as np
3
+
4
+ from assembly.description.Decoration import func_description, class_description
5
+ from assembly.GeneralUtil import show_image
6
+
7
+ '''
8
+ 图像分割
9
+
10
+ 输入:单通道图像 & 原始图
11
+ 输出:二值化图像
12
+ '''
13
+
14
+
15
+ @class_description(
16
+ title="图像分割",
17
+ description="图像分割主要是指将图像分成各具特性的区域并提取出感兴趣目标的技术。",
18
+ level=7
19
+ )
20
+ class ImageSegmentation(object):
21
+
22
+ @func_description(
23
+ title="RGB阈值分割",
24
+ description="通过指定的RGB阈值范围将图像分割为前景和背景"
25
+ )
26
+ @staticmethod
27
+ def rgb_threshold(img, lower_bound=(0, 0, 0), upper_bound=(255, 255, 255)):
28
+ """
29
+ :name RGB阈值分割
30
+ :param img: 原始图
31
+ :param lower_bound: bgr下限
32
+ :param upper_bound: bgr上限
33
+ :return: binary: 二值化图
34
+ """
35
+ mask = cv2.inRange(img, np.array(lower_bound), np.array(upper_bound))
36
+ return mask
37
+
38
+ @func_description(
39
+ title="HSV阈值分割",
40
+ description="通过指定的HSV阈值范围将图像分割为前景和背景"
41
+ )
42
+ @staticmethod
43
+ def hsv_threshold(img, lower_bound=(0, 0, 0), upper_bound=(179, 255, 255)):
44
+ """
45
+ :name HSV阈值分割
46
+ :param img: 原始图
47
+ :param lower_bound: hsv下限
48
+ :param upper_bound: hsv上限
49
+ :return: binary: 二值化图
50
+ """
51
+ hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
52
+ h, s, v = cv2.split(hsv)
53
+ mask = cv2.inRange(hsv, np.array(lower_bound), np.array(upper_bound))
54
+ return mask
55
+
56
+ @func_description(
57
+ title="固定阈值分割",
58
+ description="通过指定的阈值范围将图像分割为前景和背景"
59
+ )
60
+ @staticmethod
61
+ def normal_threshold(gray, thresh, maxval=255, is_inv=False):
62
+ """
63
+ :name 固定阈值分割
64
+ :param gray: 单通道图
65
+ :param thresh: 阈值
66
+ :param maxval: 满足阈值赋予的新值
67
+ :param is_inv: 阈值类型,默认 False cv2.THRESH_BINARY,True为 cv2.THRESH_BINARY_INV
68
+ :return: binary: 二值化图
69
+ """
70
+ if is_inv:
71
+ THRESH_TYPE = cv2.THRESH_BINARY_INV
72
+ else:
73
+ THRESH_TYPE = cv2.THRESH_BINARY
74
+ retval, binary = cv2.threshold(gray, thresh, maxval, THRESH_TYPE)
75
+ return binary
76
+
77
+ @func_description(
78
+ title="Otsu阈值分割",
79
+ description="通过分析图像的灰度直方图自动计算全局阈值,将图像分割为前景和背景"
80
+ )
81
+ @staticmethod
82
+ def otsu_threshold(gray, maxval=255, is_inv=False):
83
+ """
84
+ :name Otsu阈值分割
85
+ :param gray: 单通道图
86
+ :param maxval: 满足阈值赋予的新值
87
+ :param is_inv: 阈值类型,默认 False cv2.THRESH_BINARY,True为 cv2.THRESH_BINARY_INV
88
+ :return: binary: 二值化图
89
+ """
90
+ if is_inv:
91
+ THRESH_TYPE = cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU
92
+ else:
93
+ THRESH_TYPE = cv2.THRESH_BINARY + cv2.THRESH_OTSU
94
+ retval, binary = cv2.threshold(gray, 0, maxval, THRESH_TYPE)
95
+ return binary
96
+
97
+ @func_description(
98
+ title="自适应阈值分割",
99
+ description="根据图像局部区域的灰度变化自动计算阈值,将图像分割为前景和背景"
100
+ )
101
+ @staticmethod
102
+ def adaptive_threshold(gray, maxval=255, method=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
103
+ is_inv=False, block_size=11, C=2):
104
+ """
105
+ :name 自适应阈值分割
106
+ :param gray: 单通道图
107
+ :param maxval: 满足阈值赋予的新值
108
+ :param method: 计算阈值的方法,默认 cv2.ADAPTIVE_THRESH_GAUSSIAN_C,可选 cv2.ADAPTIVE_THRESH_MEAN_C
109
+ :param is_inv: 阈值类型,默认 False cv2.THRESH_BINARY,True为 cv2.THRESH_BINARY_INV
110
+ :param block_size: 计算阈值的邻域大小,必须为奇数
111
+ :param C: 从计算得到的阈值中减去的常数
112
+ :return: binary: 二值化图
113
+ """
114
+ if is_inv:
115
+ THRESH_TYPE = cv2.THRESH_BINARY_INV
116
+ else:
117
+ THRESH_TYPE = cv2.THRESH_BINARY
118
+ if block_size % 2 == 0:
119
+ raise ValueError("block_size must be an odd number")
120
+ binary = cv2.adaptiveThreshold(gray, maxval, method, THRESH_TYPE, block_size, C)
121
+ return binary
122
+
123
+ @func_description(
124
+ title="漫水填充分割",
125
+ description="通过从种子点开始扩展区域,将图像分割为不同的区域"
126
+ )
127
+ @staticmethod
128
+ def flood_fill(gray, seed_point, new_val, lo_diff=5, up_diff=5, flags=4):
129
+ """
130
+ :name 漫水填充分割
131
+ :param gray: 单通道图
132
+ :param seed_point: 种子点,格式为 (x, y)
133
+ :param new_val: 新值,格式为 (B, G, R)
134
+ :param lo_diff: 低差分,表示允许的颜色变化范围
135
+ :param up_diff: 高差分,表示允许的颜色变化范围
136
+ :param flags: 漫水填充的连接方式,默认 4,可选 8
137
+ :return: binary: 二值化图
138
+ """
139
+ img_copy = gray.copy()
140
+ h, w = img_copy.shape[:2]
141
+ mask = np.zeros((h + 2, w + 2), np.uint8)
142
+ num_filled_pixels, image, mask, rect = cv2.floodFill(img_copy, mask, seed_point, new_val, (lo_diff,),
143
+ (up_diff,), flags)
144
+ # 裁剪掩膜(去除边缘的多余像素)
145
+ binary_mask = mask[1:-1, 1:-1] # 得到(h, w)尺寸的掩膜
146
+ # 生成二值图:填充区=黑色(0),其余=白色(255)
147
+ binary_result = np.where(binary_mask > 0, 0, 255).astype(np.uint8)
148
+ return binary_result
149
+
150
+
151
+ # 暴露方法
152
+ def rgb_threshold(img, lower_bound=(0, 0, 0), upper_bound=(255, 255, 255)):
153
+ return ImageSegmentation.rgb_threshold(img, lower_bound, upper_bound)
154
+
155
+ def hsv_threshold(img, lower_bound=(0, 0, 0), upper_bound=(179, 255, 255)):
156
+ return ImageSegmentation.hsv_threshold(img, lower_bound, upper_bound)
157
+
158
+ def normal_threshold(gray, thresh, maxval=255, is_inv=False):
159
+ return ImageSegmentation.normal_threshold(gray, thresh, maxval, is_inv)
160
+
161
+ def otsu_threshold(gray, maxval=255, is_inv=False):
162
+ return ImageSegmentation.otsu_threshold(gray, maxval, is_inv)
163
+
164
+ def adaptive_threshold(gray, maxval=255, method=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
165
+ is_inv=False, block_size=11, C=2):
166
+ return ImageSegmentation.adaptive_threshold(gray, maxval, method, is_inv, block_size, C)
167
+
168
+ def flood_fill(gray, seed_point, new_val, lo_diff=5, up_diff=5, flags=4):
169
+ return ImageSegmentation.flood_fill(gray, seed_point, new_val, lo_diff, up_diff, flags)
170
+
171
+
172
+
173
+ if __name__ == '__main__':
174
+ image_segment = ImageSegmentation()
175
+ img = cv2.imdecode(np.fromfile(r"C:\Users\GT-LAPTOP-043\Downloads\test.jpg", dtype=np.uint8),
176
+ cv2.IMREAD_COLOR)
177
+ gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
178
+ show_image("gray_img", gray_img)
179
+ binary_img = image_segment.rgb_threshold(img, lower_bound=[0, 0, 0], upper_bound=[100, 100, 100])
180
+ show_image("rgb_threshold", binary_img)
181
+ binary_img = image_segment.hsv_threshold(img, lower_bound=[0, 0, 0], upper_bound=[179, 255, 100])
182
+ show_image("hsv_threshold", binary_img)
183
+ binary_img = image_segment.normal_threshold(gray_img, 127, is_inv=True)
184
+ show_image("normal_threshold", binary_img)
185
+ binary_img = image_segment.otsu_threshold(gray_img, is_inv=True)
186
+ show_image("otsu_threshold", binary_img)
187
+ binary_img = image_segment.adaptive_threshold(gray_img, is_inv=True)
188
+ show_image("adaptive_threshold", binary_img)
189
+ binary_img = image_segment.flood_fill(gray_img, (50, 50), 255)
190
+ show_image("flood_fill", binary_img)
@@ -0,0 +1,221 @@
1
+ import cv2
2
+ import numpy as np
3
+
4
+ from assembly.description.Decoration import func_description, class_description
5
+ from assembly.GeneralUtil import show_image
6
+
7
+ '''
8
+ 形态学变化
9
+
10
+ 输入:二值化图
11
+ 输出:二值化图
12
+ '''
13
+
14
+
15
+ @class_description(
16
+ title="形态学变化",
17
+ description="形态学变化是图像处理中常用的图像处理技术之一,它是对图像进行形态学操作的过程,包括腐蚀、膨胀、开运算、闭运算等。",
18
+ level=4
19
+ )
20
+ class MorphologicalChange(object):
21
+
22
+ @func_description(
23
+ title="腐蚀操作",
24
+ description="腐蚀操作会使图像中的前景物体变小,去除小的噪点,断开细小的连接"
25
+ )
26
+ @staticmethod
27
+ def mlc_erode(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
28
+ """
29
+ :name 腐蚀操作
30
+ :param binary: 二值化图
31
+ :param kernel_size: 卷积核大小,必须为奇数
32
+ :param kernel_type: 卷积核类型,默认矩形 cv2.MORPH_RECT, 可选 cv2.MORPH_ELLIPSE, cv2.MORPH_CROSS
33
+ :param iterations: 腐蚀次数
34
+ :return binary: 二值化图
35
+ """
36
+ if kernel_size % 2 == 0:
37
+ raise ValueError("kernel_size must be an odd number")
38
+ kernel = cv2.getStructuringElement(kernel_type, (kernel_size, kernel_size))
39
+ eroded = cv2.erode(binary, kernel, iterations=iterations)
40
+ return eroded
41
+
42
+ @func_description(
43
+ title="膨胀操作",
44
+ description="膨胀操作会使图像中的前景物体变大,填充小的空白,连接物体上的小洞"
45
+ )
46
+ @staticmethod
47
+ def mlc_dilate(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
48
+ """
49
+ :name 膨胀操作
50
+ :param binary: 二值化图
51
+ :param kernel_size: 卷积核大小,必须为奇数
52
+ :param kernel_type: 卷积核类型,默认矩形 cv2.MORPH_RECT, 可选 cv2.MORPH_ELLIPSE, cv2.MORPH_CROSS
53
+ :param iterations: 膨胀次数
54
+ :return binary: 二值化图
55
+ """
56
+ if kernel_size % 2 == 0:
57
+ raise ValueError("kernel_size must be an odd number")
58
+ kernel = cv2.getStructuringElement(kernel_type, (kernel_size, kernel_size))
59
+ dilated = cv2.dilate(binary, kernel, iterations=iterations)
60
+ return dilated
61
+
62
+ @func_description(
63
+ title="开运算",
64
+ description="先腐蚀后膨胀,去除小的噪点,断开细小的连接"
65
+ )
66
+ @staticmethod
67
+ def mlc_open(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
68
+ """
69
+ :name 开运算
70
+ :param binary: 二值化图
71
+ :param kernel_size: 卷积核大小,必须为奇数
72
+ :param kernel_type: 卷积核类型,默认矩形 cv2.MORPH_RECT, 可选 cv2.MORPH_ELLIPSE, cv2.MORPH_CROSS
73
+ :param iterations: 开操作次数
74
+ :return binary: 二值化图
75
+ """
76
+ if kernel_size % 2 == 0:
77
+ raise ValueError("kernel_size must be an odd number")
78
+ kernel = cv2.getStructuringElement(kernel_type, (kernel_size, kernel_size))
79
+ opened = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=iterations)
80
+ return opened
81
+
82
+ @func_description(
83
+ title="闭运算",
84
+ description="先膨胀后腐蚀,填充小的空白,连接物体上的小洞"
85
+ )
86
+ @staticmethod
87
+ def mlc_close(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
88
+ """
89
+ :name 闭运算
90
+ :param binary: 二值化图
91
+ :param kernel_size: 卷积核大小,必须为奇数
92
+ :param kernel_type: 卷积核类型,默认矩形 cv2.MORPH_RECT, 可选 cv2.MORPH_ELLIPSE, cv2.MORPH_CROSS
93
+ :param iterations: 闭操作次数
94
+ :return binary: 二值化图
95
+ """
96
+ if kernel_size % 2 == 0:
97
+ raise ValueError("kernel_size must be an odd number")
98
+ kernel = cv2.getStructuringElement(kernel_type, (kernel_size, kernel_size))
99
+ closed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=iterations)
100
+ return closed
101
+
102
+ @func_description(
103
+ title="形态学梯度",
104
+ description="形态学梯度是图像的梯度,表示图像中前景物体与背景之间的差异"
105
+ )
106
+ @staticmethod
107
+ def mlc_gradient(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
108
+ """
109
+ :name 形态学梯度
110
+ :param binary: 二值化图
111
+ :param kernel_size: 卷积核大小,必须为奇数
112
+ :param kernel_type: 卷积核类型,默认矩形 cv2.MORPH_RECT, 可选 cv2.MORPH_ELLIPSE, cv2.MORPH_CROSS
113
+ :param iterations: 形态学梯度次数
114
+ :return binary: 二值化图
115
+ """
116
+ if kernel_size % 2 == 0:
117
+ raise ValueError("kernel_size must be an odd number")
118
+ kernel = cv2.getStructuringElement(kernel_type, (kernel_size, kernel_size))
119
+ gradient = cv2.morphologyEx(binary, cv2.MORPH_GRADIENT, kernel, iterations=iterations)
120
+ return gradient
121
+
122
+ @func_description(
123
+ title="顶帽操作",
124
+ description="顶帽操作是原始图像与开操作结果之间的差异,突出图像中的小亮区域"
125
+ )
126
+ @staticmethod
127
+ def mlc_top_hat(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
128
+ """
129
+ :name 顶帽操作
130
+ :param binary: 二值化图
131
+ :param kernel_size: 卷积核大小,必须为奇数
132
+ :param kernel_type: 卷积核类型,默认矩形 cv2.MORPH_RECT, 可选 cv2.MORPH_ELLIPSE, cv2.MORPH_CROSS
133
+ :param iterations: 顶帽操作次数
134
+ :return img:顶帽操作后的图像
135
+ """
136
+ if kernel_size % 2 == 0:
137
+ raise ValueError("kernel_size must be an odd number")
138
+ kernel = cv2.getStructuringElement(kernel_type, (kernel_size, kernel_size))
139
+ tophat = cv2.morphologyEx(binary, cv2.MORPH_TOPHAT, kernel, iterations=iterations)
140
+ return tophat
141
+
142
+ @func_description(
143
+ title="黑帽操作",
144
+ description="黑帽操作是闭操作结果与原始图像之间的差异,突出图像中的小暗区域"
145
+ )
146
+ @staticmethod
147
+ def mlc_black_hat(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
148
+ """
149
+ :name 黑帽操作
150
+ :param binary: 二值化图
151
+ :param kernel_size: 卷积核大小,必须为奇数
152
+ :param kernel_type: 卷积核类型,默认矩形 cv2.MORPH_RECT, 可选 cv2.MORPH_ELLIPSE, cv2.MORPH_CROSS
153
+ :param iterations: 黑帽操作次数
154
+ :return binary: 二值化图
155
+ """
156
+ if kernel_size % 2 == 0:
157
+ raise ValueError("kernel_size must be an odd number")
158
+ kernel = cv2.getStructuringElement(kernel_type, (kernel_size, kernel_size))
159
+ blackhat = cv2.morphologyEx(binary, cv2.MORPH_BLACKHAT, kernel, iterations=iterations)
160
+ return blackhat
161
+
162
+ @func_description(
163
+ title="骨架化",
164
+ description="骨架化是将图像中连通区域的边界线去除,使图像变成一个单一的轮廓线"
165
+ )
166
+ @staticmethod
167
+ def mlc_skeletonize(binary):
168
+ """
169
+ :name 骨架化
170
+ :param binary: 二值化图
171
+ :return binary: 二值化图
172
+ """
173
+ skeleton = cv2.ximgproc.thinning(binary)
174
+ return skeleton
175
+
176
+
177
+ # 暴露方法
178
+
179
+ def mlc_erode(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
180
+ return MorphologicalChange.mlc_erode(binary, kernel_size, kernel_type, iterations)
181
+
182
+ def mlc_dilate(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
183
+ return MorphologicalChange.mlc_dilate(binary, kernel_size, kernel_type, iterations)
184
+
185
+ def mlc_open(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
186
+ return MorphologicalChange.mlc_open(binary, kernel_size, kernel_type, iterations)
187
+
188
+ def mlc_close(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
189
+ return MorphologicalChange.mlc_close(binary, kernel_size, kernel_type, iterations)
190
+
191
+ def mlc_gradient(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
192
+ return MorphologicalChange.mlc_gradient(binary, kernel_size, kernel_type, iterations)
193
+
194
+ def mlc_top_hat(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
195
+ return MorphologicalChange.mlc_top_hat(binary, kernel_size, kernel_type, iterations)
196
+
197
+ def mlc_black_hat(binary, kernel_size=3, kernel_type=cv2.MORPH_RECT, iterations=1):
198
+ return MorphologicalChange.mlc_black_hat(binary, kernel_size, kernel_type, iterations)
199
+
200
+ def mlc_skeletonize(binary):
201
+ return MorphologicalChange.mlc_skeletonize(binary)
202
+
203
+
204
+ if __name__ == '__main__':
205
+ morphological_change = MorphologicalChange()
206
+ img = cv2.imdecode(np.fromfile(r"C:\Users\GT-LAPTOP-043\Downloads\黑白格.jpg", dtype=np.uint8),
207
+ cv2.IMREAD_COLOR)
208
+ gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
209
+ ret, gray_img = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV, gray_img)
210
+
211
+ show_image("gray_img", gray_img, 500, 500)
212
+ show_image("mlc_erode", morphological_change.mlc_erode(gray_img), 500, 500)
213
+ show_image("mlc_dilate", morphological_change.mlc_dilate(gray_img), 500, 500)
214
+ show_image("mlc_open", morphological_change.mlc_open(gray_img), 500, 500)
215
+ show_image("mlc_close", morphological_change.mlc_close(gray_img), 500, 500)
216
+ show_image("mlc_gradient", morphological_change.mlc_gradient(gray_img), 500, 500)
217
+ show_image("mlc_top_hat", morphological_change.mlc_top_hat(gray_img), 500, 500)
218
+ show_image("mlc_black_hat", morphological_change.mlc_black_hat(gray_img), 500, 500)
219
+ show_image("mlc_skeletonize", morphological_change.mlc_skeletonize(gray_img), 500, 500)
220
+
221
+ cv2.destroyAllWindows()