bambu-a1-mini / mo_optimizer.py
SissiFeng's picture
Initial commit: Bambu A1 Mini analysis system
477c54f
import numpy as np
import hdbscan
from skimage import feature, filters
import cv2
from typing import Dict, Any
class MOPrintOptimizer:
"""Multi-objective optimizer for print parameters"""
def __init__(self):
# Weights for different objectives
self.weights = {
'quality': 0.4,
'speed': 0.3,
'material': 0.3
}
# Quality thresholds
self.quality_thresholds = {
'missing_rate': 0.1, # 10% missing is bad
'excess_rate': 0.1, # 10% excess is bad
'stringing_rate': 0.05, # 5% stringing is bad
'uniformity': 0.8 # At least 80% uniformity is good
}
# Material efficiency parameters
self.material_params = {
'optimal_flow_rate': 100, # 100% flow rate
'flow_tolerance': 10, # ±10% tolerance
'optimal_layer_height': 0.2 # 0.2mm layer height
}
def evaluate_quality(self, metrics: Dict[str, float]) -> float:
"""Evaluate print quality score
Args:
metrics: Dictionary containing quality metrics
- missing_rate: Percentage of missing material
- excess_rate: Percentage of excess material
- stringing_rate: Percentage of stringing
- uniformity_score: Score for print uniformity
Returns:
float: Quality score (0-1)
"""
# Convert each metric to a score (0-1)
missing_score = 1.0 - min(1.0, metrics['missing_rate'] / self.quality_thresholds['missing_rate'])
excess_score = 1.0 - min(1.0, metrics['excess_rate'] / self.quality_thresholds['excess_rate'])
stringing_score = 1.0 - min(1.0, metrics['stringing_rate'] / self.quality_thresholds['stringing_rate'])
uniformity_score = metrics['uniformity_score']
# Combine scores with equal weights
quality_score = np.mean([
missing_score,
excess_score,
stringing_score,
uniformity_score
])
return float(quality_score)
def evaluate_material_efficiency(self, params: Dict[str, float]) -> float:
"""Evaluate material efficiency
Args:
params: Current print parameters
Returns:
float: Material efficiency score (0-1)
"""
# Flow rate deviation from optimal
flow_deviation = abs(params['flow_rate'] - self.material_params['optimal_flow_rate'])
flow_score = 1.0 - min(1.0, flow_deviation / self.material_params['flow_tolerance'])
# Layer height optimization (thicker layers use less material for same volume)
layer_score = params['layer_height'] / self.material_params['optimal_layer_height']
layer_score = min(1.0, layer_score) # Cap at 1.0
# Retraction optimization (less retraction is better for material efficiency)
retraction_score = 1.0 - (params['retraction_distance'] / 10.0) # Assuming max 10mm
# Combine scores
material_score = np.mean([
flow_score * 0.4, # Flow rate is most important
layer_score * 0.4, # Layer height equally important
retraction_score * 0.2 # Retraction less important
])
return float(material_score)
def evaluate_objectives(self, image: np.ndarray, params: Dict[str, float]) -> Dict[str, Any]:
"""Evaluate all objectives and combine them
Args:
image: Print image for quality analysis
params: Current print parameters
Returns:
dict: Evaluation results including individual scores and total
"""
# Get quality metrics from image analysis
quality_metrics = {
'missing_rate': 0.05, # These should come from DefectDetector
'excess_rate': 0.03, # in real implementation
'stringing_rate': 0.02,
'uniformity_score': 0.95
}
# Calculate individual objective scores
quality_score = self.evaluate_quality(quality_metrics)
speed_score = params['print_speed'] / 150.0 # Normalize to max speed
material_score = self.evaluate_material_efficiency(params)
# Combine objectives using weights
total_score = (
quality_score * self.weights['quality'] +
speed_score * self.weights['speed'] +
material_score * self.weights['material']
)
return {
'objectives': {
'quality': float(quality_score),
'speed': float(speed_score),
'material': float(material_score),
'total': float(total_score)
},
'metrics': quality_metrics
}
def evaluate_print_quality(self, image, expected_pattern=None):
"""Evaluate print quality using hybrid approach
Args:
image: Current print image
expected_pattern: Expected print pattern (optional)
Returns:
dict: Quality metrics
"""
# 1. Traditional Image Processing
edge_metrics = self._analyze_edges(image)
surface_metrics = self._analyze_surface(image)
# 2. HDBSCAN-based defect clustering
defect_metrics = self._cluster_defects(image)
# 3. Pattern matching if expected pattern provided
pattern_metrics = self._analyze_pattern(image, expected_pattern) if expected_pattern else {}
return {
'edge_quality': edge_metrics,
'surface_quality': surface_metrics,
'defect_analysis': defect_metrics,
'pattern_accuracy': pattern_metrics
}
def _analyze_edges(self, image):
"""Analyze edge quality using traditional methods"""
# Multi-scale edge detection
edges_fine = feature.canny(image, sigma=1)
edges_medium = feature.canny(image, sigma=2)
edges_coarse = feature.canny(image, sigma=3)
return {
'fine_edge_score': np.mean(edges_fine),
'medium_edge_score': np.mean(edges_medium),
'coarse_edge_score': np.mean(edges_coarse),
'edge_consistency': self._calculate_edge_consistency(
[edges_fine, edges_medium, edges_coarse]
)
}
def _analyze_surface(self, image):
"""Analyze surface quality using texture analysis"""
# Local Binary Patterns for texture
lbp = feature.local_binary_pattern(image, P=8, R=1, method='uniform')
# GLCM features
glcm = feature.graycomatrix(image, [1], [0, np.pi/4, np.pi/2, 3*np.pi/4])
contrast = feature.graycoprops(glcm, 'contrast')
homogeneity = feature.graycoprops(glcm, 'homogeneity')
return {
'texture_uniformity': np.std(lbp),
'surface_contrast': np.mean(contrast),
'surface_homogeneity': np.mean(homogeneity)
}
def _cluster_defects(self, image):
"""Use HDBSCAN to cluster potential defects"""
# Extract potential defect points
defect_points = self._extract_defect_points(image)
if len(defect_points) > 0:
# Apply HDBSCAN clustering
clusterer = hdbscan.HDBSCAN(
min_cluster_size=3,
min_samples=2,
metric='euclidean',
cluster_selection_epsilon=0.5
)
cluster_labels = clusterer.fit_predict(defect_points)
# Analyze clusters
return self._analyze_defect_clusters(defect_points, cluster_labels)
return {'defect_count': 0, 'cluster_sizes': [], 'defect_density': 0}
def _calculate_edge_consistency(self, edges):
"""Calculate edge consistency"""
return np.mean([np.mean(edge) for edge in edges])
def _analyze_pattern(self, image, expected_pattern):
"""Analyze pattern accuracy"""
# Placeholder for pattern matching
return 0.8 # Assuming 80% accuracy
def _extract_defect_points(self, image):
"""Extract potential defect points"""
# Placeholder for defect point extraction
return np.array([[0, 0], [1, 1], [2, 2]]) # Placeholder points
def _analyze_defect_clusters(self, defect_points, cluster_labels):
"""Analyze defect clusters"""
# Placeholder for cluster analysis
return {'defect_count': len(np.unique(cluster_labels)), 'cluster_sizes': [], 'defect_density': 0}
def _apply_parameter_adjustments(self, current_params, adjustments):
"""Apply parameter adjustments"""
# Placeholder for parameter adjustment logic
return current_params # Placeholder return