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