fix: ahsf feat. summer
Some checks failed
App Builder / build (ubuntu-latest) (push) Has been cancelled
App Builder / build (windows-latest) (push) Has been cancelled
App Builder / Deploy (push) Has been cancelled
App Builder / Cleanup actions (push) Has been cancelled

This commit is contained in:
Prohurtz 2025-06-30 12:57:24 -05:00
parent 910e6fdfe1
commit 58eaed9ad4
4 changed files with 266 additions and 242 deletions

View File

@ -28,76 +28,94 @@ LICENSE: Summer Software Distribution License 1.0
------------------------------------------------------------------------------------------------------
"""
from __future__ import annotations
from typing import Tuple, Optional
import cv2
import numpy as np
from typing import Tuple, Optional
import numba
# ------------------------- utility helpers ------------------------- #
def _rect_scale(rect: Tuple[int, int, int, int],
ratio: float,
keep_center: bool = True,
square_outer: bool = False) -> Tuple[int, int, int, int]:
"""Scale rectangle by *ratio* (optionally keep centre fixed)."""
x, y, w, h = rect
if square_outer:
w = h = int(max(w, h) * ratio)
@numba.njit(cache=True, fastmath=True)
def _get_integral_sum(ii: np.ndarray, x: int, y: int, w: int, h: int) -> float:
return ii[y + h, x + w] - ii[y, x + w] - ii[y + h, x] + ii[y, x]
@numba.njit(cache=True, fastmath=True)
def _evaluate_single_position(ii: np.ndarray, x: int, y: int, width: int, height: int,
ratio_outer: float, kf: float, use_square: bool,
bx: int, by: int, bw: int, bh: int) -> Tuple[float, int, int, int, int, float, float]:
if use_square:
ow = oh = int(max(width, height) * ratio_outer)
else:
w = int(w * ratio)
h = int(h * ratio)
if keep_center:
cx, cy = x + rect[2] // 2, y + rect[3] // 2
x = int(cx - w / 2)
y = int(cy - h / 2)
return (x, y, w, h)
ow = int(width * ratio_outer)
oh = int(height * ratio_outer)
def _clip_rect(rect: Tuple[int, int, int, int],
boundary: Tuple[int, int, int, int]) -> Tuple[int, int, int, int]:
"""Clip *rect* to *boundary* = (x, y, w, h)."""
bx, by, bw, bh = boundary
x, y, w, h = rect
x = max(bx, x)
y = max(by, y)
w = min(x + w, bx + bw) - x
h = min(y + h, by + bh) - y
return (x, y, max(0, w), max(0, h))
cx = x + width // 2
cy = y + height // 2
ox = int(cx - ow / 2)
oy = int(cy - oh / 2)
def _get_block_integral(ii: np.ndarray,
rect: Tuple[int, int, int, int]) -> int:
"""Integralimage sum over *rect*."""
x, y, w, h = rect
return (ii[y+h, x+w] - ii[y, x+w] - ii[y+h, x] + ii[y, x])
ox = max(bx, ox)
oy = max(by, oy)
ow = min(ox + ow, bx + bw) - ox
oh = min(oy + oh, by + bh) - oy
if ow <= 0 or oh <= 0:
return -255.0, ox, oy, max(0, ow), max(0, oh), 0.0, 0.0
inner_area = width * height
outer_area = ow * oh - inner_area
if outer_area <= 0:
return -255.0, ox, oy, max(0, ow), max(0, oh), 0.0, 0.0
inner_sum = _get_integral_sum(ii, x, y, width, height)
outer_sum = _get_integral_sum(ii, ox, oy, ow, oh)
mu_in = inner_sum / inner_area
mu_out = (outer_sum - inner_sum) / outer_area
f_val = mu_out - kf * mu_in
return f_val, ox, oy, max(0, ow), max(0, oh), mu_in, mu_out
@numba.njit(cache=True)
def _coarse_search(ii: np.ndarray,
roi_x: int, roi_y: int, roi_w: int, roi_h: int,
width_min: int, width_max: int, wh_step: int, xy_step: int,
ratio_outer: float, kf: float, use_square: bool,
bx: int, by: int, bw: int, bh: int):
best_f = -255
best_pupil = (0, 0, 0, 0)
best_outer = (0, 0, 0, 0)
best_mu_in = best_mu_out = 0.0
for width in range(width_min, width_max + 1, wh_step):
height = width
xmax = roi_x + roi_w - width
ymax = roi_y + roi_h - height
if xmax < roi_x or ymax < roi_y:
continue
for x in range(roi_x, xmax + 1, xy_step):
for y in range(roi_y, ymax + 1, xy_step):
f_val, ox, oy, ow, oh, mu_in, mu_out = _evaluate_single_position(
ii, x, y, width, height, ratio_outer, kf, use_square, bx, by, bw, bh)
if f_val > best_f:
best_f = f_val
best_pupil = (x, y, width, height)
best_outer = (ox, oy, ow, oh)
best_mu_in = mu_in
best_mu_out = mu_out
return best_f, best_pupil, best_outer, best_mu_in, best_mu_out
def _canny_pure(img: np.ndarray,
low: int = 64,
high_ratio: float = 2.0) -> np.ndarray:
"""Lightweight Canny wrapper (imitates canny_pure())."""
img_blur = cv2.GaussianBlur(img, (3, 3), 0)
return cv2.Canny(img_blur, low, int(low*high_ratio))
# --------------------------- main class ---------------------------- #
class PupilDetectorHaar:
"""
Haarbased coarsetofine pupil detector.
Parameters
----------
ratio_outer : float
Scaling factor for Haar outer rectangle.
kf : float
Weighting term in response function f = µ_outer kf*µ_inner.
use_square_haar : bool
If True, outer Haar window is square; else horizontal rectangle.
use_init_rect : bool
If True, provide an approximate pupil box in *init_rect*.
init_rect : Tuple[int,int,int,int] | None
Initial pupil location on the fullresolution frame.
target_resolution : Tuple[int,int]
Image is downsampled so the longer side ~320 px by default.
width_min / width_max / wh_step / xy_step
Searchgrid parameters for Haar scanning.
"""
# -------- initialisation -------- #
def __init__(self,
ratio_outer: float = 1.4,
kf: float = 1.5,
@ -109,6 +127,7 @@ class PupilDetectorHaar:
width_max: int = 120,
wh_step: int = 2,
xy_step: int = 2):
self.ratio_outer = ratio_outer
self.kf = kf
self.use_square_haar = use_square_haar
@ -116,20 +135,17 @@ class PupilDetectorHaar:
self.init_rect = (0, 0, 0, 0) if init_rect is None else init_rect
self.target_resolution = target_resolution
# searchgrid params (may be autotuned after first frame)
self.width_min = width_min
self.width_max = width_max
self.wh_step = wh_step
self.xy_step = xy_step
# dynamic state
self.frame_num = 0
self.mu_inner = 50
self.mu_outer = 200
self.mu_inner0 = 50 # first frame stats
self.mu_inner0 = 50
self.mu_outer0 = 200
# outputs (public)
self.pupil_rect_coarse = (0, 0, 0, 0)
self.outer_rect_coarse = (0, 0, 0, 0)
self.max_response_coarse = -255
@ -138,67 +154,38 @@ class PupilDetectorHaar:
self.pupil_rect_fine = (0, 0, 0, 0)
self.center_fine = (0.0, 0.0)
# private temp
self._ratio_down = 1.0
self._img_boundary = (0, 0, 0, 0)
self._init_rect_down = (0, 0, 0, 0)
# ---------------------------------------------------------------- #
# PUBLIC API #
# ---------------------------------------------------------------- #
def detect(self, img_gray: np.ndarray) -> Tuple[Tuple[int,int,int,int], Tuple[float,float]]:
"""
Run detector on a single *uint8* gray image.
Returns
-------
pupil_rect_fine : (x,y,w,h)
center_fine : (cx,cy) -- both on fullresolution image.
"""
def detect(self, img_gray: np.ndarray) -> Tuple[Tuple[int, int, int, int], Tuple[float, float]]:
if img_gray.dtype != np.uint8:
raise TypeError("img_gray must be uint8 [0,255]")
self.frame_num += 1
img_down = self._preprocess(img_gray)
self._coarse_detection(img_down)
self._fine_detection(img_down)
self._fine_detection_fast(img_down)
self._postprocess()
return self.pupil_rect_fine, self.center_fine
# --------------- optional helper for visual debugging ------------ #
def draw_debug(self, bgr: np.ndarray) -> None:
"""Draw rectangular outputs on *bgr* inplace."""
cv2.rectangle(bgr, self.pupil_rect_fine, (0, 255, 0), 1)
cv2.rectangle(bgr, self.outer_rect_coarse, (255, 0, 0), 1)
cx, cy = map(int, self.center_fine)
cv2.drawMarker(bgr, (cx, cy), (0, 0, 255),
markerType=cv2.MARKER_CROSS, markerSize=10, thickness=1)
# ---------------------------------------------------------------- #
# INTERNAL STAGES #
# ---------------------------------------------------------------- #
def _preprocess(self, img_gray: np.ndarray) -> np.ndarray:
# downsample to target size (longer side ≈ target_resolution[0])
h, w = img_gray.shape
self._ratio_down = max(w / self.target_resolution[0],
h / self.target_resolution[1], 1.0)
new_w = int(round(w / self._ratio_down))
new_h = int(round(h / self._ratio_down))
img_down = cv2.resize(img_gray, (new_w, new_h),
interpolation=cv2.INTER_AREA)
img_down = cv2.resize(img_gray, (new_w, new_h), interpolation=cv2.INTER_AREA)
self._img_boundary = (0, 0, new_w, new_h)
# optional highintensity suppression on first frame
if self.use_init_rect and self.frame_num == 1:
# Estimate µ_inner0 / µ_outer0 inside init box
x, y, rw, rh = self.init_rect
region = img_gray[y:y+rh, x:x+rw]
region = img_gray[y:y + rh, x:x + rw]
self.mu_inner0 = np.percentile(region, 25)
self.mu_outer0 = np.percentile(region, 75)
# adjust kf like original code
if self.mu_outer0 - self.mu_inner0 > 30:
tau = self.mu_outer0
else:
@ -207,122 +194,94 @@ class PupilDetectorHaar:
return img_down
# ------------------------------------------------------------ #
# COARSE DETECTION #
# ------------------------------------------------------------ #
def _initial_search_range(self, img_down: np.ndarray) -> Tuple[int,int,int,int]:
"""Compute ROI and width range for current frame (downsampled)."""
def _initial_search_range(self, img_down: np.ndarray) -> Tuple[int, int, int, int]:
h, w = img_down.shape
margin = h // 10 // 2
full = (margin, margin, w - 2*margin, h - 2*margin)
full = (margin, margin, w - 2 * margin, h - 2 * margin)
if not self.use_init_rect:
self.roi = full
return
# scale init_rect to down resolution
self._init_rect_down = tuple(int(x / self._ratio_down) for x in self.init_rect)
ix, iy, iw, ih = self._init_rect_down
# grow ROI adaptively near borders (imitates C++ code)
rx, ry, rw, rh = full
enlarge = 35
if ix < enlarge: rx, rw = 0, w
if iy < enlarge: ry, rh = 0, h
if ix+iw > w - enlarge: rx, rw = 0, w
if iy+ih > h - enlarge: ry, rh = 0, h
if ix + iw > w - enlarge: rx, rw = 0, w
if iy + ih > h - enlarge: ry, rh = 0, h
self.roi = (rx, ry, rw, rh)
# width search band tuned by first frame
self.width_min = max(int(iw*1.0), 24)
self.width_max = min(int(iw*1.5), 120)
self.width_min = max(int(iw * 1.0), 24)
self.width_max = min(int(iw * 1.5), 120)
def _coarse_detection(self, img_down: np.ndarray) -> None:
self._initial_search_range(img_down)
roi_x, roi_y, roi_w, roi_h = self.roi
# build integral image (cv2 adds +1 row/col)
# Build integral image
ii = cv2.integral(img_down, sdepth=cv2.CV_32S)
best_f = -255
best_pupil = (0, 0, 0, 0)
best_outer = (0, 0, 0, 0)
best_mu_in, best_mu_out = 0, 0
for width in range(self.width_min, self.width_max+1, self.wh_step):
# height tied to width; rectangular pupils handled fine
for height in range(width, width+1, self.wh_step):
xmax = roi_x + roi_w - width
ymax = roi_y + roi_h - height
for x in range(roi_x, xmax+1, self.xy_step):
for y in range(roi_y, ymax+1, self.xy_step):
pupil = (x, y, width, height)
outer = _rect_scale(pupil, self.ratio_outer,
keep_center=True,
square_outer=self.use_square_haar)
outer = _clip_rect(outer, self._img_boundary)
mu_in, mu_out = 0.0, 0.0
mu_out = (_get_block_integral(ii, outer) -
_get_block_integral(ii, pupil)) / \
(outer[2]*outer[3] - width*height)
mu_in = _get_block_integral(ii, pupil) / (width*height)
f_val = mu_out - self.kf * mu_in
if f_val > best_f:
best_f = f_val
best_pupil = pupil
best_outer = outer
best_mu_in, best_mu_out = mu_in, mu_out
# Optimized search
bx, by, bw, bh = self._img_boundary
best_f, best_pupil, best_outer, best_mu_in, best_mu_out = _coarse_search(
ii, roi_x, roi_y, roi_w, roi_h,
self.width_min, self.width_max, self.wh_step, self.xy_step,
self.ratio_outer, self.kf, self.use_square_haar,
bx, by, bw, bh
)
self.pupil_rect_coarse = best_pupil
self.outer_rect_coarse = best_outer
self.max_response_coarse = best_f
self.mu_inner, self.mu_outer = best_mu_in, best_mu_out
self.mu_inner = best_mu_in
self.mu_outer = best_mu_out
px, py, pw, ph = best_pupil
self.center_coarse = (px + pw / 2, py + ph / 2)
# ------------------------------------------------------------ #
# FINE DETECTION #
# ------------------------------------------------------------ #
def _fine_detection(self, img_down: np.ndarray) -> None:
def _fine_detection_fast(self, img_down: np.ndarray) -> None:
px, py, pw, ph = self.pupil_rect_coarse
expand = 1.42
exp_rect = _clip_rect(_rect_scale(self.pupil_rect_coarse, expand, True),
self._img_boundary)
ex, ey, ew, eh = exp_rect
patch = img_down[ey:ey+eh, ex:ex+ew]
# threshold at µ_inner (same heuristic)
_, bw = cv2.threshold(patch, int(self.mu_inner), 255,
cv2.THRESH_BINARY_INV)
cx, cy = px + pw // 2, py + ph // 2
ew, eh = int(pw * expand), int(ph * expand)
ex, ey = cx - ew // 2, cy - eh // 2
# dilate to merge gaps
bw = cv2.dilate(bw, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5)))
# Clip to boundary
bx, by, bw, bh = self._img_boundary
ex = max(bx, ex)
ey = max(by, ey)
ew = min(ex + ew, bx + bw) - ex
eh = min(ey + eh, by + bh) - ey
# connected components
n, labels, stats, centroids = cv2.connectedComponentsWithStats(bw)
if n <= 1:
# fallback: keep coarse rect
self.pupil_rect_fine = tuple(int(v) for v in
np.array(self.pupil_rect_coarse) *
self._ratio_down)
self.center_fine = tuple(v * self._ratio_down
for v in self.center_coarse)
if ew <= 0 or eh <= 0:
self.pupil_rect_fine = self.pupil_rect_coarse
self.center_fine = self.center_coarse
return
patch = img_down[ey:ey + eh, ex:ex + ew]
_, bw = cv2.threshold(patch, int(self.mu_inner), 255, cv2.THRESH_BINARY_INV)
bw = cv2.dilate(bw, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)))
n, labels, stats, centroids = cv2.connectedComponentsWithStats(bw)
if n <= 1:
self.pupil_rect_fine = self.pupil_rect_coarse
self.center_fine = self.center_coarse
return
# discard tiny blobs (<4% of patch)
areas = stats[1:, cv2.CC_STAT_AREA]
mask = areas > 0.04 * bw.size
if not np.any(mask):
mask = areas.argmax()[None] # keep largest if all tiny
mask = areas.argmax()[None]
# choose component through image centre, else darkest centroid
cx_local = patch.shape[1] // 2
cy_local = patch.shape[0] // 2
comp_idx = labels[cy_local, cx_local]
if comp_idx == 0 or not mask[comp_idx-1]:
# pick darkest of two largest blobs (C++ heuristic)
if comp_idx == 0 or not mask[comp_idx - 1]:
dark = 255
for idx in np.flatnonzero(mask) + 1:
cx_i, cy_i = centroids[idx]
@ -331,24 +290,21 @@ class PupilDetectorHaar:
dark = val
comp_idx = idx
# final bounding box in downscaled coords
x, y, w, h = stats[comp_idx, cv2.CC_STAT_LEFT : cv2.CC_STAT_HEIGHT+1]
x, y, w, h = stats[comp_idx, cv2.CC_STAT_LEFT: cv2.CC_STAT_HEIGHT + 1]
x += ex
y += ey
self.pupil_rect_fine = (x, y, w, h)
self.center_fine = (x + w / 2, y + h / 2)
# ------------------------------------------------------------ #
# UPSAMPLE BACK #
# ------------------------------------------------------------ #
def _postprocess(self) -> None:
# scale coarse and fine rects + centres back to full resolution
scale = self._ratio_down
def _up(rect):
return tuple(int(round(v*scale)) for v in rect)
return tuple(int(round(v * scale)) for v in rect)
self.pupil_rect_coarse = _up(self.pupil_rect_coarse)
self.outer_rect_coarse = _up(self.outer_rect_coarse)
self.pupil_rect_fine = _up(self.pupil_rect_fine)
self.center_coarse = tuple(v*scale for v in self.center_coarse)
self.center_fine = tuple(v*scale for v in self.center_fine)
self.center_coarse = tuple(v * scale for v in self.center_coarse)
self.center_fine = tuple(v * scale for v in self.center_fine)

View File

@ -62,7 +62,7 @@ WINDOW_NAME = "EyeTrackApp"
page_url = "https://github.com/EyeTrackVR/EyeTrackVR/releases/latest"
appversion = "EyeTrackApp 0.2.3"
appversion = "EyeTrackApp 0.2.4"
class KeyManager:

193
poetry.lock generated
View File

@ -422,6 +422,37 @@ dev = ["changelist (==0.5)"]
lint = ["pre-commit (==3.7.0)"]
test = ["pytest (>=7.4)", "pytest-cov (>=4.1)"]
[[package]]
name = "llvmlite"
version = "0.44.0"
description = "lightweight wrapper around basic LLVM functionality"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "llvmlite-0.44.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:9fbadbfba8422123bab5535b293da1cf72f9f478a65645ecd73e781f962ca614"},
{file = "llvmlite-0.44.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cccf8eb28f24840f2689fb1a45f9c0f7e582dd24e088dcf96e424834af11f791"},
{file = "llvmlite-0.44.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7202b678cdf904823c764ee0fe2dfe38a76981f4c1e51715b4cb5abb6cf1d9e8"},
{file = "llvmlite-0.44.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40526fb5e313d7b96bda4cbb2c85cd5374e04d80732dd36a282d72a560bb6408"},
{file = "llvmlite-0.44.0-cp310-cp310-win_amd64.whl", hash = "sha256:41e3839150db4330e1b2716c0be3b5c4672525b4c9005e17c7597f835f351ce2"},
{file = "llvmlite-0.44.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:eed7d5f29136bda63b6d7804c279e2b72e08c952b7c5df61f45db408e0ee52f3"},
{file = "llvmlite-0.44.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ace564d9fa44bb91eb6e6d8e7754977783c68e90a471ea7ce913bff30bd62427"},
{file = "llvmlite-0.44.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5d22c3bfc842668168a786af4205ec8e3ad29fb1bc03fd11fd48460d0df64c1"},
{file = "llvmlite-0.44.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f01a394e9c9b7b1d4e63c327b096d10f6f0ed149ef53d38a09b3749dcf8c9610"},
{file = "llvmlite-0.44.0-cp311-cp311-win_amd64.whl", hash = "sha256:d8489634d43c20cd0ad71330dde1d5bc7b9966937a263ff1ec1cebb90dc50955"},
{file = "llvmlite-0.44.0-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:1d671a56acf725bf1b531d5ef76b86660a5ab8ef19bb6a46064a705c6ca80aad"},
{file = "llvmlite-0.44.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f79a728e0435493611c9f405168682bb75ffd1fbe6fc360733b850c80a026db"},
{file = "llvmlite-0.44.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0143a5ef336da14deaa8ec26c5449ad5b6a2b564df82fcef4be040b9cacfea9"},
{file = "llvmlite-0.44.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d752f89e31b66db6f8da06df8b39f9b91e78c5feea1bf9e8c1fba1d1c24c065d"},
{file = "llvmlite-0.44.0-cp312-cp312-win_amd64.whl", hash = "sha256:eae7e2d4ca8f88f89d315b48c6b741dcb925d6a1042da694aa16ab3dd4cbd3a1"},
{file = "llvmlite-0.44.0-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:319bddd44e5f71ae2689859b7203080716448a3cd1128fb144fe5c055219d516"},
{file = "llvmlite-0.44.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c58867118bad04a0bb22a2e0068c693719658105e40009ffe95c7000fcde88e"},
{file = "llvmlite-0.44.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46224058b13c96af1365290bdfebe9a6264ae62fb79b2b55693deed11657a8bf"},
{file = "llvmlite-0.44.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0097052c32bf721a4efc03bd109d335dfa57d9bffb3d4c24cc680711b8b4fc"},
{file = "llvmlite-0.44.0-cp313-cp313-win_amd64.whl", hash = "sha256:2fb7c4f2fb86cbae6dca3db9ab203eeea0e22d73b99bc2341cdf9de93612e930"},
{file = "llvmlite-0.44.0.tar.gz", hash = "sha256:07667d66a5d150abed9157ab6c0b9393c9356f229784a4385c02f99e94fc94d4"},
]
[[package]]
name = "macholib"
version = "1.16.3"
@ -583,42 +614,77 @@ extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.1
test = ["pytest (>=7.2)", "pytest-cov (>=4.0)", "pytest-xdist (>=3.0)"]
test-extras = ["pytest-mpl", "pytest-randomly"]
[[package]]
name = "numba"
version = "0.61.2"
description = "compiling Python code using LLVM"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "numba-0.61.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:cf9f9fc00d6eca0c23fc840817ce9f439b9f03c8f03d6246c0e7f0cb15b7162a"},
{file = "numba-0.61.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ea0247617edcb5dd61f6106a56255baab031acc4257bddaeddb3a1003b4ca3fd"},
{file = "numba-0.61.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ae8c7a522c26215d5f62ebec436e3d341f7f590079245a2f1008dfd498cc1642"},
{file = "numba-0.61.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bd1e74609855aa43661edffca37346e4e8462f6903889917e9f41db40907daa2"},
{file = "numba-0.61.2-cp310-cp310-win_amd64.whl", hash = "sha256:ae45830b129c6137294093b269ef0a22998ccc27bf7cf096ab8dcf7bca8946f9"},
{file = "numba-0.61.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:efd3db391df53aaa5cfbee189b6c910a5b471488749fd6606c3f33fc984c2ae2"},
{file = "numba-0.61.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:49c980e4171948ffebf6b9a2520ea81feed113c1f4890747ba7f59e74be84b1b"},
{file = "numba-0.61.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3945615cd73c2c7eba2a85ccc9c1730c21cd3958bfcf5a44302abae0fb07bb60"},
{file = "numba-0.61.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbfdf4eca202cebade0b7d43896978e146f39398909a42941c9303f82f403a18"},
{file = "numba-0.61.2-cp311-cp311-win_amd64.whl", hash = "sha256:76bcec9f46259cedf888041b9886e257ae101c6268261b19fda8cfbc52bec9d1"},
{file = "numba-0.61.2-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:34fba9406078bac7ab052efbf0d13939426c753ad72946baaa5bf9ae0ebb8dd2"},
{file = "numba-0.61.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4ddce10009bc097b080fc96876d14c051cc0c7679e99de3e0af59014dab7dfe8"},
{file = "numba-0.61.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5b1bb509d01f23d70325d3a5a0e237cbc9544dd50e50588bc581ba860c213546"},
{file = "numba-0.61.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:48a53a3de8f8793526cbe330f2a39fe9a6638efcbf11bd63f3d2f9757ae345cd"},
{file = "numba-0.61.2-cp312-cp312-win_amd64.whl", hash = "sha256:97cf4f12c728cf77c9c1d7c23707e4d8fb4632b46275f8f3397de33e5877af18"},
{file = "numba-0.61.2-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:3a10a8fc9afac40b1eac55717cece1b8b1ac0b946f5065c89e00bde646b5b154"},
{file = "numba-0.61.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d3bcada3c9afba3bed413fba45845f2fb9cd0d2b27dd58a1be90257e293d140"},
{file = "numba-0.61.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bdbca73ad81fa196bd53dc12e3aaf1564ae036e0c125f237c7644fe64a4928ab"},
{file = "numba-0.61.2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:5f154aaea625fb32cfbe3b80c5456d514d416fcdf79733dd69c0df3a11348e9e"},
{file = "numba-0.61.2-cp313-cp313-win_amd64.whl", hash = "sha256:59321215e2e0ac5fa928a8020ab00b8e57cda8a97384963ac0dfa4d4e6aa54e7"},
{file = "numba-0.61.2.tar.gz", hash = "sha256:8750ee147940a6637b80ecf7f95062185ad8726c8c28a2295b8ec1160a196f7d"},
]
[package.dependencies]
llvmlite = "==0.44.*"
numpy = ">=1.24,<2.3"
[[package]]
name = "numpy"
version = "1.23.5"
description = "NumPy is the fundamental package for array computing with Python."
version = "1.24.4"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "numpy-1.23.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9c88793f78fca17da0145455f0d7826bcb9f37da4764af27ac945488116efe63"},
{file = "numpy-1.23.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e9f4c4e51567b616be64e05d517c79a8a22f3606499941d97bb76f2ca59f982d"},
{file = "numpy-1.23.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7903ba8ab592b82014713c491f6c5d3a1cde5b4a3bf116404e08f5b52f6daf43"},
{file = "numpy-1.23.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e05b1c973a9f858c74367553e236f287e749465f773328c8ef31abe18f691e1"},
{file = "numpy-1.23.5-cp310-cp310-win32.whl", hash = "sha256:522e26bbf6377e4d76403826ed689c295b0b238f46c28a7251ab94716da0b280"},
{file = "numpy-1.23.5-cp310-cp310-win_amd64.whl", hash = "sha256:dbee87b469018961d1ad79b1a5d50c0ae850000b639bcb1b694e9981083243b6"},
{file = "numpy-1.23.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ce571367b6dfe60af04e04a1834ca2dc5f46004ac1cc756fb95319f64c095a96"},
{file = "numpy-1.23.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56e454c7833e94ec9769fa0f86e6ff8e42ee38ce0ce1fa4cbb747ea7e06d56aa"},
{file = "numpy-1.23.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5039f55555e1eab31124a5768898c9e22c25a65c1e0037f4d7c495a45778c9f2"},
{file = "numpy-1.23.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58f545efd1108e647604a1b5aa809591ccd2540f468a880bedb97247e72db387"},
{file = "numpy-1.23.5-cp311-cp311-win32.whl", hash = "sha256:b2a9ab7c279c91974f756c84c365a669a887efa287365a8e2c418f8b3ba73fb0"},
{file = "numpy-1.23.5-cp311-cp311-win_amd64.whl", hash = "sha256:0cbe9848fad08baf71de1a39e12d1b6310f1d5b2d0ea4de051058e6e1076852d"},
{file = "numpy-1.23.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f063b69b090c9d918f9df0a12116029e274daf0181df392839661c4c7ec9018a"},
{file = "numpy-1.23.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0aaee12d8883552fadfc41e96b4c82ee7d794949e2a7c3b3a7201e968c7ecab9"},
{file = "numpy-1.23.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92c8c1e89a1f5028a4c6d9e3ccbe311b6ba53694811269b992c0b224269e2398"},
{file = "numpy-1.23.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d208a0f8729f3fb790ed18a003f3a57895b989b40ea4dce4717e9cf4af62c6bb"},
{file = "numpy-1.23.5-cp38-cp38-win32.whl", hash = "sha256:06005a2ef6014e9956c09ba07654f9837d9e26696a0470e42beedadb78c11b07"},
{file = "numpy-1.23.5-cp38-cp38-win_amd64.whl", hash = "sha256:ca51fcfcc5f9354c45f400059e88bc09215fb71a48d3768fb80e357f3b457e1e"},
{file = "numpy-1.23.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8969bfd28e85c81f3f94eb4a66bc2cf1dbdc5c18efc320af34bffc54d6b1e38f"},
{file = "numpy-1.23.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7ac231a08bb37f852849bbb387a20a57574a97cfc7b6cabb488a4fc8be176de"},
{file = "numpy-1.23.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf837dc63ba5c06dc8797c398db1e223a466c7ece27a1f7b5232ba3466aafe3d"},
{file = "numpy-1.23.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33161613d2269025873025b33e879825ec7b1d831317e68f4f2f0f84ed14c719"},
{file = "numpy-1.23.5-cp39-cp39-win32.whl", hash = "sha256:af1da88f6bc3d2338ebbf0e22fe487821ea4d8e89053e25fa59d1d79786e7481"},
{file = "numpy-1.23.5-cp39-cp39-win_amd64.whl", hash = "sha256:09b7847f7e83ca37c6e627682f145856de331049013853f344f37b0c9690e3df"},
{file = "numpy-1.23.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:abdde9f795cf292fb9651ed48185503a2ff29be87770c3b8e2a14b0cd7aa16f8"},
{file = "numpy-1.23.5-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9a909a8bae284d46bbfdefbdd4a262ba19d3bc9921b1e76126b1d21c3c34135"},
{file = "numpy-1.23.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:01dd17cbb340bf0fc23981e52e1d18a9d4050792e8fb8363cecbf066a84b827d"},
{file = "numpy-1.23.5.tar.gz", hash = "sha256:1b1766d6f397c18153d40015ddfc79ddb715cabadc04d2d228d4e5a8bc4ded1a"},
{file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"},
{file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"},
{file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"},
{file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"},
{file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"},
{file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"},
{file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"},
{file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"},
{file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"},
{file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"},
{file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"},
{file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"},
{file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"},
{file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"},
{file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"},
{file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"},
{file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"},
{file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"},
{file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"},
{file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"},
{file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"},
{file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"},
{file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"},
{file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"},
{file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"},
{file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"},
{file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"},
{file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"},
]
[[package]]
@ -1293,52 +1359,53 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "scikit-image"
version = "0.24.0"
version = "0.25.2"
description = "Image processing in Python"
optional = false
python-versions = ">=3.9"
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "scikit_image-0.24.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cb3bc0264b6ab30b43c4179ee6156bc18b4861e78bb329dd8d16537b7bbf827a"},
{file = "scikit_image-0.24.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:9c7a52e20cdd760738da38564ba1fed7942b623c0317489af1a598a8dedf088b"},
{file = "scikit_image-0.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93f46e6ce42e5409f4d09ce1b0c7f80dd7e4373bcec635b6348b63e3c886eac8"},
{file = "scikit_image-0.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39ee0af13435c57351a3397eb379e72164ff85161923eec0c38849fecf1b4764"},
{file = "scikit_image-0.24.0-cp310-cp310-win_amd64.whl", hash = "sha256:7ac7913b028b8aa780ffae85922894a69e33d1c0bf270ea1774f382fe8bf95e7"},
{file = "scikit_image-0.24.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:272909e02a59cea3ed4aa03739bb88df2625daa809f633f40b5053cf09241831"},
{file = "scikit_image-0.24.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:190ebde80b4470fe8838764b9b15f232a964f1a20391663e31008d76f0c696f7"},
{file = "scikit_image-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59c98cc695005faf2b79904e4663796c977af22586ddf1b12d6af2fa22842dc2"},
{file = "scikit_image-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa27b3a0dbad807b966b8db2d78da734cb812ca4787f7fbb143764800ce2fa9c"},
{file = "scikit_image-0.24.0-cp311-cp311-win_amd64.whl", hash = "sha256:dacf591ac0c272a111181afad4b788a27fe70d213cfddd631d151cbc34f8ca2c"},
{file = "scikit_image-0.24.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6fccceb54c9574590abcddc8caf6cefa57c13b5b8b4260ab3ff88ad8f3c252b3"},
{file = "scikit_image-0.24.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ccc01e4760d655aab7601c1ba7aa4ddd8b46f494ac46ec9c268df6f33ccddf4c"},
{file = "scikit_image-0.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18836a18d3a7b6aca5376a2d805f0045826bc6c9fc85331659c33b4813e0b563"},
{file = "scikit_image-0.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8579bda9c3f78cb3b3ed8b9425213c53a25fa7e994b7ac01f2440b395babf660"},
{file = "scikit_image-0.24.0-cp312-cp312-win_amd64.whl", hash = "sha256:82ab903afa60b2da1da2e6f0c8c65e7c8868c60a869464c41971da929b3e82bc"},
{file = "scikit_image-0.24.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef04360eda372ee5cd60aebe9be91258639c86ae2ea24093fb9182118008d009"},
{file = "scikit_image-0.24.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:e9aadb442360a7e76f0c5c9d105f79a83d6df0e01e431bd1d5757e2c5871a1f3"},
{file = "scikit_image-0.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e37de6f4c1abcf794e13c258dc9b7d385d5be868441de11c180363824192ff7"},
{file = "scikit_image-0.24.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4688c18bd7ec33c08d7bf0fd19549be246d90d5f2c1d795a89986629af0a1e83"},
{file = "scikit_image-0.24.0-cp39-cp39-win_amd64.whl", hash = "sha256:56dab751d20b25d5d3985e95c9b4e975f55573554bd76b0aedf5875217c93e69"},
{file = "scikit_image-0.24.0.tar.gz", hash = "sha256:5d16efe95da8edbeb363e0c4157b99becbd650a60b77f6e3af5768b66cf007ab"},
{file = "scikit_image-0.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d3278f586793176599df6a4cf48cb6beadae35c31e58dc01a98023af3dc31c78"},
{file = "scikit_image-0.25.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5c311069899ce757d7dbf1d03e32acb38bb06153236ae77fcd820fd62044c063"},
{file = "scikit_image-0.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be455aa7039a6afa54e84f9e38293733a2622b8c2fb3362b822d459cc5605e99"},
{file = "scikit_image-0.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4c464b90e978d137330be433df4e76d92ad3c5f46a22f159520ce0fdbea8a09"},
{file = "scikit_image-0.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:60516257c5a2d2f74387c502aa2f15a0ef3498fbeaa749f730ab18f0a40fd054"},
{file = "scikit_image-0.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f4bac9196fb80d37567316581c6060763b0f4893d3aca34a9ede3825bc035b17"},
{file = "scikit_image-0.25.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d989d64ff92e0c6c0f2018c7495a5b20e2451839299a018e0e5108b2680f71e0"},
{file = "scikit_image-0.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2cfc96b27afe9a05bc92f8c6235321d3a66499995675b27415e0d0c76625173"},
{file = "scikit_image-0.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24cc986e1f4187a12aa319f777b36008764e856e5013666a4a83f8df083c2641"},
{file = "scikit_image-0.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:b4f6b61fc2db6340696afe3db6b26e0356911529f5f6aee8c322aa5157490c9b"},
{file = "scikit_image-0.25.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8db8dd03663112783221bf01ccfc9512d1cc50ac9b5b0fe8f4023967564719fb"},
{file = "scikit_image-0.25.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:483bd8cc10c3d8a7a37fae36dfa5b21e239bd4ee121d91cad1f81bba10cfb0ed"},
{file = "scikit_image-0.25.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d1e80107bcf2bf1291acfc0bf0425dceb8890abe9f38d8e94e23497cbf7ee0d"},
{file = "scikit_image-0.25.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a17e17eb8562660cc0d31bb55643a4da996a81944b82c54805c91b3fe66f4824"},
{file = "scikit_image-0.25.2-cp312-cp312-win_amd64.whl", hash = "sha256:bdd2b8c1de0849964dbc54037f36b4e9420157e67e45a8709a80d727f52c7da2"},
{file = "scikit_image-0.25.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7efa888130f6c548ec0439b1a7ed7295bc10105458a421e9bf739b457730b6da"},
{file = "scikit_image-0.25.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:dd8011efe69c3641920614d550f5505f83658fe33581e49bed86feab43a180fc"},
{file = "scikit_image-0.25.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28182a9d3e2ce3c2e251383bdda68f8d88d9fff1a3ebe1eb61206595c9773341"},
{file = "scikit_image-0.25.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8abd3c805ce6944b941cfed0406d88faeb19bab3ed3d4b50187af55cf24d147"},
{file = "scikit_image-0.25.2-cp313-cp313-win_amd64.whl", hash = "sha256:64785a8acefee460ec49a354706db0b09d1f325674107d7fa3eadb663fb56d6f"},
{file = "scikit_image-0.25.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:330d061bd107d12f8d68f1d611ae27b3b813b8cdb0300a71d07b1379178dd4cd"},
{file = "scikit_image-0.25.2.tar.gz", hash = "sha256:e5a37e6cd4d0c018a7a55b9d601357e3382826d3888c10d0213fc63bff977dde"},
]
[package.dependencies]
imageio = ">=2.33"
imageio = ">=2.33,<2.35.0 || >2.35.0"
lazy-loader = ">=0.4"
networkx = ">=2.8"
numpy = ">=1.23"
networkx = ">=3.0"
numpy = ">=1.24"
packaging = ">=21"
pillow = ">=9.1"
scipy = ">=1.9"
pillow = ">=10.1"
scipy = ">=1.11.4"
tifffile = ">=2022.8.12"
[package.extras]
build = ["Cython (>=3.0.4)", "build", "meson-python (>=0.15)", "ninja", "numpy (>=2.0.0rc1)", "packaging (>=21)", "pythran", "setuptools (>=67)", "spin (==0.8)", "wheel"]
build = ["Cython (>=3.0.8)", "build (>=1.2.1)", "meson-python (>=0.16)", "ninja (>=1.11.1.1)", "numpy (>=2.0)", "pythran (>=0.16)", "spin (==0.13)"]
data = ["pooch (>=1.6.0)"]
developer = ["ipython", "pre-commit", "tomli ; python_version < \"3.11\""]
docs = ["PyWavelets (>=1.1.1)", "dask[array] (>=2022.9.2)", "ipykernel", "ipywidgets", "kaleido", "matplotlib (>=3.6)", "myst-parser", "numpydoc (>=1.7)", "pandas (>=1.5)", "plotly (>=5.10)", "pooch (>=1.6)", "pydata-sphinx-theme (>=0.15.2)", "pytest-doctestplus", "pytest-runner", "scikit-learn (>=1.1)", "seaborn (>=0.11)", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-gallery (>=0.14)", "sphinx_design (>=0.5)", "tifffile (>=2022.8.12)"]
optional = ["PyWavelets (>=1.1.1)", "SimpleITK", "astropy (>=5.0)", "cloudpickle (>=0.2.1)", "dask[array] (>=2021.1.0)", "matplotlib (>=3.6)", "pooch (>=1.6.0)", "pyamg", "scikit-learn (>=1.1)"]
test = ["asv", "numpydoc (>=1.7)", "pooch (>=1.6.0)", "pytest (>=7.0)", "pytest-cov (>=2.11.0)", "pytest-doctestplus", "pytest-faulthandler", "pytest-localserver"]
docs = ["PyWavelets (>=1.6)", "dask[array] (>=2023.2.0)", "intersphinx-registry (>=0.2411.14)", "ipykernel", "ipywidgets", "kaleido (==0.2.1)", "matplotlib (>=3.7)", "myst-parser", "numpydoc (>=1.7)", "pandas (>=2.0)", "plotly (>=5.20)", "pooch (>=1.6)", "pydata-sphinx-theme (>=0.16)", "pytest-doctestplus", "scikit-learn (>=1.2)", "seaborn (>=0.11)", "sphinx (>=8.0)", "sphinx-copybutton", "sphinx-gallery[parallel] (>=0.18)", "sphinx_design (>=0.5)", "tifffile (>=2022.8.12)"]
optional = ["PyWavelets (>=1.6)", "SimpleITK", "astropy (>=5.0)", "cloudpickle (>=1.1.1)", "dask[array] (>=2023.2.0)", "matplotlib (>=3.7)", "pooch (>=1.6.0)", "pyamg (>=5.2)", "scikit-learn (>=1.2)"]
test = ["asv", "numpydoc (>=1.7)", "pooch (>=1.6.0)", "pytest (>=8)", "pytest-cov (>=2.11.0)", "pytest-doctestplus", "pytest-faulthandler", "pytest-localserver"]
[[package]]
name = "scipy"
@ -1599,4 +1666,4 @@ files = [
[metadata]
lock-version = "2.1"
python-versions = "~3.11.0"
content-hash = "7ffb992ec99af574f2c8cba03a0ba54fda04d7d691b8920a8f30adf465050ff2"
content-hash = "2c1cc120973c6c14fee04467811aa33c9ec374cf4c5415e7ca41ac8faa07005f"

View File

@ -11,7 +11,7 @@ python = "~3.11.0"
python-osc = "^1.8.0"
requests = "^2.28.1"
opencv-python = "~4.6.0.66"
numpy = "~1.23.5"
numpy = "~1.24.0"
pye3d = "^0.3.2"
pysimplegui-4-foss = "^4.6.4.1"
pydantic = "^2.4.2"
@ -25,6 +25,7 @@ colorama = "^0.4.6"
taskipy = "^1.10.4"
pytest = "^8.0.0"
pytest-cov = "^4.1.0"
numba = "^0.61.2"
[tool.poetry.group.dev.dependencies]
black = "^22.10.0"