/
LitvinovVN
/
ComputerVision
Обзор
Документация
Войти
/
LitvinovVN
/
ComputerVision
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
Klette_Computer_Vision_2019/part3/code/chapter3_image_analysis.py
236 строк
7 KB
Art_Lun
Ковалевский глава 3 Клетте
22 дек 2025, 00:45
22 дек 2025, 00:45
1cf5214
Код
Авторство
О чём код?
import numpy as np from collections import deque from math import sqrt, cos, sin, pi # ============================================================ # 3.1 ТОПОЛОГИЯ ИЗОБРАЖЕНИЙ # ============================================================ A4 = [(-1, 0), (1, 0), (0, -1), (0, 1)] A8 = A4 + [(-1, -1), (-1, 1), (1, -1), (1, 1)] def connected_components(binary, connectivity=4): h, w = binary.shape visited = np.zeros_like(binary, bool) components = [] neigh = A4 if connectivity == 4 else A8 for y in range(h): for x in range(w): if binary[y, x] and not visited[y, x]: q = deque([(y, x)]) visited[y, x] = True comp = [] while q: cy, cx = q.popleft() comp.append((cy, cx)) for dy, dx in neigh: ny, nx = cy + dy, cx + dx if 0 <= ny < h and 0 <= nx < w: if binary[ny, nx] and not visited[ny, nx]: visited[ny, nx] = True q.append((ny, nx)) components.append(comp) return components def trace_boundary(binary): h, w = binary.shape neigh = A8 start = None for y in range(h): for x in range(w): if binary[y, x]: start = (y, x) break if start: break boundary = [start] prev = None curr = start while True: found = False for dy, dx in neigh: ny, nx = curr[0] + dy, curr[1] + dx if 0 <= ny < h and 0 <= nx < w: if binary[ny, nx] and (ny, nx) != prev: nxt = (ny, nx) found = True break if not found or nxt == start: break boundary.append(nxt) prev, curr = curr, nxt return boundary # ============================================================ # 3.2 ГЕОМЕТРИЯ # ============================================================ def area(binary): return int(np.sum(binary)) def perimeter(boundary): L = 0.0 for i in range(1, len(boundary)): y1, x1 = boundary[i - 1] y2, x2 = boundary[i] dy, dx = abs(y2 - y1), abs(x2 - x1) if dy + dx == 1: L += 1 else: L += sqrt(2) return L def curvature(contour, k=3): curv = [] n = len(contour) for i in range(k, n - k): x0, y0 = contour[i] x1, y1 = contour[i - k] x2, y2 = contour[i + k] a = x1 - 2 * x0 + x2 b = y1 - 2 * y0 + y2 c = x2 - x1 d = y2 - y1 denom = (c * c + d * d) ** 1.5 curv.append(0 if denom == 0 else 2 * (a * d - b * c) / denom) return curv def distance_transform(binary): h, w = binary.shape D = np.full((h, w), np.inf) zeros = np.argwhere(~binary) ones = np.argwhere(binary) for y, x in ones: D[y, x] = min( (y - zy) ** 2 + (x - zx) ** 2 for zy, zx in zeros ) return np.sqrt(D) # ============================================================ # 3.3 АНАЛИЗ ЗНАЧЕНИЙ ИЗОБРАЖЕНИЯ # ============================================================ def histogram(image, levels=256): hist = np.zeros(levels, int) for v in image.flatten(): hist[int(v)] += 1 return hist def image_statistics(image): return { "min": float(np.min(image)), "max": float(np.max(image)), "mean": float(np.mean(image)), "variance": float(np.var(image)), "std": float(np.std(image)), } def local_mean(image, window=3): h, w = image.shape r = window // 2 out = np.zeros_like(image, float) for y in range(h): for x in range(w): ys = max(0, y - r) ye = min(h, y + r + 1) xs = max(0, x - r) xe = min(w, x + r + 1) out[y, x] = np.mean(image[ys:ye, xs:xe]) return out # ============================================================ # 3.4 ПОИСК ПРЯМЫХ И ОКРУЖНОСТЕЙ # ============================================================ def hough_lines(edge_image, theta_steps=180): h, w = edge_image.shape diag = int(sqrt(h * h + w * w)) rhos = np.linspace(-diag, diag, 2 * diag) thetas = np.linspace(0, pi, theta_steps) acc = np.zeros((len(rhos), len(thetas)), int) ys, xs = np.nonzero(edge_image) for x, y in zip(xs, ys): for t_i, theta in enumerate(thetas): rho = int(round(x * cos(theta) + y * sin(theta))) + diag if 0 <= rho < len(rhos): acc[rho, t_i] += 1 return acc, rhos, thetas def hough_circles(edge_image, radius_range): h, w = edge_image.shape acc = {} ys, xs = np.nonzero(edge_image) for r in radius_range: acc[r] = np.zeros((h, w), int) for x, y in zip(xs, ys): for theta in range(0, 360, 5): a = int(x - r * cos(theta * pi / 180)) b = int(y - r * sin(theta * pi / 180)) if 0 <= a < w and 0 <= b < h: acc[r][b, a] += 1 return acc # ============================================================ # ПРИМЕР ИСПОЛЬЗОВАНИЯ # ============================================================ if __name__ == "__main__": img = np.zeros((50, 50), dtype=np.uint8) img[10:40, 20:30] = 200 binary = img > 0 comps = connected_components(binary, 8) boundary = trace_boundary(binary) print("Компоненты:", len(comps)) print("Площадь:", area(binary)) print("Периметр:", perimeter(boundary)) curv = curvature(boundary) print("Кривизна (первые значения):", curv[:5]) D = distance_transform(binary) print("DT центр:", D[25, 25]) print("Статистика:", image_statistics(img)) print("Гистограмма (ненулевые):", np.count_nonzero(histogram(img))) edges = binary acc_lines, _, _ = hough_lines(edges) print("Макс. голосов (прямые):", np.max(acc_lines)) circles = hough_circles(edges, range(5, 15)) print("Окружности обработаны:", len(circles))