fix: restructure src layout to proper package directory
Move src/__init__.py, detect.py, diagnose.py, extract_temp.py, utils/ into src/infrared_data/ to fix wheel package structure. Previously the whl placed files at root instead of infrared_data/ directory, causing ModuleNotFoundError on install. Also update pyproject.toml packages.find config to use standard src-layout discovery.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
# Utils Package
|
||||
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
温度特征提取工具函数
|
||||
从红外图像ROI区域提取温度统计特征
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
from typing import Dict, List, Tuple, Optional
|
||||
|
||||
|
||||
def extract_temp_stats(roi: np.ndarray) -> Dict[str, float]:
|
||||
"""
|
||||
从ROI区域提取温度统计特征
|
||||
|
||||
Args:
|
||||
roi: ROI区域图像数组
|
||||
|
||||
Returns:
|
||||
温度统计特征字典
|
||||
"""
|
||||
if roi.size == 0:
|
||||
return {
|
||||
'temp_max': 0.0,
|
||||
'temp_min': 0.0,
|
||||
'temp_mean': 0.0,
|
||||
'temp_std': 0.0,
|
||||
'temp_median': 0.0,
|
||||
}
|
||||
|
||||
return {
|
||||
'temp_max': float(np.max(roi)),
|
||||
'temp_min': float(np.min(roi)),
|
||||
'temp_mean': float(np.mean(roi)),
|
||||
'temp_std': float(np.std(roi)),
|
||||
'temp_median': float(np.median(roi)),
|
||||
}
|
||||
|
||||
|
||||
def extract_temp_histogram(roi: np.ndarray, bins: int = 32) -> np.ndarray:
|
||||
"""
|
||||
提取温度分布直方图特征
|
||||
|
||||
Args:
|
||||
roi: ROI区域图像数组
|
||||
bins: 直方图bin数量
|
||||
|
||||
Returns:
|
||||
归一化直方图向量
|
||||
"""
|
||||
if roi.size == 0:
|
||||
return np.zeros(bins)
|
||||
|
||||
hist, _ = np.histogram(roi.flatten(), bins=bins, range=(0, 255))
|
||||
hist = hist.astype(np.float32) / (hist.sum() + 1e-7)
|
||||
return hist
|
||||
|
||||
|
||||
def calculate_temp_gradient(roi: np.ndarray) -> Dict[str, float]:
|
||||
"""
|
||||
计算温度梯度特征(反映温度变化剧烈程度)
|
||||
|
||||
Args:
|
||||
roi: ROI区域图像数组
|
||||
|
||||
Returns:
|
||||
温度梯度统计
|
||||
"""
|
||||
if roi.size == 0:
|
||||
return {'gradient_mean': 0.0, 'gradient_std': 0.0}
|
||||
|
||||
grad_x = cv2.Sobel(roi, cv2.CV_32F, 1, 0, ksize=3)
|
||||
grad_y = cv2.Sobel(roi, cv2.CV_32F, 0, 1, ksize=3)
|
||||
gradient_magnitude = np.sqrt(grad_x**2 + grad_y**2)
|
||||
|
||||
return {
|
||||
'gradient_mean': float(np.mean(gradient_magnitude)),
|
||||
'gradient_std': float(np.std(gradient_magnitude)),
|
||||
}
|
||||
|
||||
|
||||
def extract_temp_features(roi: np.ndarray, include_hist: bool = True,
|
||||
include_gradient: bool = True) -> Dict:
|
||||
"""
|
||||
从ROI区域提取完整温度特征
|
||||
|
||||
Args:
|
||||
roi: ROI区域图像数组
|
||||
include_hist: 是否包含直方图特征
|
||||
include_gradient: 是否包含梯度特征
|
||||
|
||||
Returns:
|
||||
完整温度特征字典
|
||||
"""
|
||||
features = extract_temp_stats(roi)
|
||||
|
||||
if include_hist:
|
||||
features['temp_histogram'] = extract_temp_histogram(roi)
|
||||
|
||||
if include_gradient:
|
||||
features.update(calculate_temp_gradient(roi))
|
||||
|
||||
return features
|
||||
|
||||
|
||||
def normalize_roi(roi: np.ndarray, method: str = 'minmax') -> np.ndarray:
|
||||
"""
|
||||
对ROI进行归一化处理
|
||||
|
||||
Args:
|
||||
roi: ROI区域图像数组
|
||||
method: 归一化方法 ('minmax' 或 'zscore')
|
||||
|
||||
Returns:
|
||||
归一化后的图像
|
||||
"""
|
||||
if method == 'minmax':
|
||||
min_val, max_val = roi.min(), roi.max()
|
||||
if max_val - min_val < 1e-7:
|
||||
return np.zeros_like(roi)
|
||||
return (roi - min_val) / (max_val - min_val)
|
||||
elif method == 'zscore':
|
||||
mean_val, std_val = np.mean(roi), np.std(roi)
|
||||
if std_val < 1e-7:
|
||||
return np.zeros_like(roi)
|
||||
return (roi - mean_val) / std_val
|
||||
else:
|
||||
raise ValueError(f"Unknown normalization method: {method}")
|
||||
Reference in New Issue
Block a user