-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
177 lines (144 loc) · 6.81 KB
/
app.py
File metadata and controls
177 lines (144 loc) · 6.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import numpy as np
import cv2
import matplotlib.pyplot as plt
from skimage.segmentation import watershed
from scipy import ndimage as ndi
def adaptive_region_growing(image, min_size=50):
"""Улучшенный Region Growing с адаптивным выбором семян"""
# Автоматическое определение семян через локальные минимумы
h, w = image.shape
seeds = np.zeros_like(image, dtype=bool)
# Находим локальные минимумы
for y in range(1, h-1):
for x in range(1, w-1):
if image[y, x] < image[y-1:y+2, x-1:x+2].min():
seeds[y, x] = True
# Удаляем слишком близкие семена
seeds = ndi.binary_erosion(seeds, structure=np.ones((3,3)))
# Маркируем семена
markers, _ = ndi.label(seeds)
# Применяем водораздельную сегментацию
labels = watershed(image, markers)
return labels
def improved_split_and_merge(image, min_size=20, var_threshold=10, merge_threshold=15):
"""Улучшенный Split and Merge с дополнительным слиянием"""
def _split(img, x, y, w, h):
if w <= min_size or h <= min_size:
return [(x, y, w, h)]
region = img[y:y+h, x:x+w]
if np.var(region) < var_threshold:
return [(x, y, w, h)]
w2, h2 = w//2, h//2
regions = []
regions.extend(_split(img, x, y, w2, h2))
regions.extend(_split(img, x + w2, y, w - w2, h2))
regions.extend(_split(img, x, y + h2, w2, h - h2))
regions.extend(_split(img, x + w2, y + h2, w - w2, h - h2))
return regions
# Разделение
regions = _split(image, 0, 0, image.shape[1], image.shape[0])
# Создаем маску регионов
mask = np.zeros(image.shape[:2], dtype=np.int32)
for i, (x, y, w, h) in enumerate(regions):
mask[y:y+h, x:x+w] = i + 1
# Дополнительное слияние соседних регионов
return merge_adjacent_regions(image, mask, merge_threshold)
def merge_adjacent_regions(image, mask, threshold=15):
"""Слияние смежных регионов со схожей интенсивностью"""
h, w = image.shape
new_mask = mask.copy()
next_label = np.max(mask) + 1
# Проверяем соседние регионы
for y in range(1, h-1):
for x in range(1, w-1):
current = new_mask[y, x]
neighbors = set()
# Собираем соседние метки
for dy in (-1, 0, 1):
for dx in (-1, 0, 1):
if dy == 0 and dx == 0:
continue
ny, nx = y + dy, x + dx
neighbors.add(new_mask[ny, nx])
# Удаляем фон и текущий регион
neighbors.discard(0)
neighbors.discard(current)
# Проверяем схожесть регионов
for n in neighbors:
if n == 0 or n == current:
continue
# Сравниваем среднюю интенсивность
mean_current = np.mean(image[new_mask == current])
mean_neighbor = np.mean(image[new_mask == n])
if abs(mean_current - mean_neighbor) < threshold:
# Объединяем регионы
new_mask[new_mask == n] = current
# Перенумеровываем регионы
return ndi.label(new_mask)[0]
def visualize_segmentation(image, mask):
"""Улучшенная визуализация: границы + цветные регионы"""
# Находим границы
boundaries = np.zeros_like(image)
h, w = image.shape
for y in range(1, h-1):
for x in range(1, w-1):
if (mask[y, x] != mask[y, x+1] or
mask[y, x] != mask[y+1, x]):
boundaries[y, x] = 255
# Создаем цветное представление регионов
colored = np.zeros((h, w, 3), dtype=np.uint8)
unique_labels = np.unique(mask)
for label in unique_labels:
if label == 0: # Пропускаем фон
continue
color = np.random.randint(0, 255, size=3)
colored[mask == label] = color
# Наложение границ
colored[boundaries == 255] = [0, 0, 255]
return colored
# Загрузка и предобработка изображения
image_path = 'original.jpg'
original = cv2.imread(image_path)
if original is None:
raise FileNotFoundError(f"Image not found at {image_path}")
# Конвертация и улучшение контраста
gray = cv2.cvtColor(original, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# Улучшенная предобработка
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
enhanced = clahe.apply(blurred)
# 1. Улучшенный Region Growing
rg_mask = adaptive_region_growing(enhanced)
# 2. Улучшенный Split and Merge
sm_mask = improved_split_and_merge(enhanced, min_size=15, var_threshold=5, merge_threshold=10)
# 3. Watershed как альтернатива
_, thresh = cv2.threshold(enhanced, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
kernel = np.ones((3,3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
sure_bg = cv2.dilate(opening, kernel, iterations=3)
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist_transform, 0.5*dist_transform.max(), 255, 0)
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
_, markers = cv2.connectedComponents(sure_fg)
markers += 1
markers[unknown == 255] = 0
ws_mask = cv2.watershed(cv2.cvtColor(enhanced, cv2.COLOR_GRAY2BGR), markers)
ws_mask = np.where(ws_mask == -1, 0, ws_mask)
# Визуализация
rg_result = visualize_segmentation(enhanced, rg_mask)
sm_result = visualize_segmentation(enhanced, sm_mask)
ws_result = visualize_segmentation(enhanced, ws_mask)
# Сохранение результатов
cv2.imwrite('improved_region_growing.jpg', rg_result)
cv2.imwrite('improved_split_merge.jpg', sm_result)
cv2.imwrite('watershed.jpg', ws_result)
# Отображение
plt.figure(figsize=(18, 12))
plt.subplot(221), plt.imshow(original), plt.title('Original')
plt.subplot(222), plt.imshow(rg_result), plt.title('Improved Region Growing')
plt.subplot(223), plt.imshow(sm_result), plt.title('Improved Split & Merge')
plt.subplot(224), plt.imshow(ws_result), plt.title('Watershed')
plt.tight_layout()
plt.savefig('improved_segmentation_results.jpg')
plt.show()