|
|

楼主 |
发表于 2026-9-29 23:10:14
|
显示全部楼层
- FACE_PARAMS = [
- # ===== 骨骼结构(大范围调整) =====
- ("face_width", "脸型宽窄", "narrow face", "wide face"),
- ("face_height", "脸的长短", "long face", "short face"),
- ("cheekbone_width", "颧骨宽度", "narrow cheekbones", "wide cheekbones"),
- ("jaw_width", "下颌宽度", "narrow jaw", "wide jaw"),
- ("chin_shape", "下巴形状", "pointed chin", "round chin"),
- ("face_roundness", "脸的圆润度", "angular face", "round face"),
- # ===== 五官细节(小范围调整) =====
- ("eye_size", "眼睛大小", "small eyes", "big eyes"),
- ("eye_distance", "眼距宽窄", "close-set eyes", "wide-set eyes"),
- ("nose_size", "鼻子大小", "small nose", "big nose"),
- ("mouth_size", "嘴巴大小", "small mouth", "big mouth"),
- ("lip_thickness", "嘴唇厚度", "thin lips", "thick lips"),
- ("eyebrow_thickness", "眉毛粗细", "thin eyebrows", "thick eyebrows"),
- ]
- PRESET_STYLES = {
- "精致": {
- "eye_size": 15, "eye_distance": 0, "nose_size": -10,
- "mouth_size": -8, "lip_thickness": -5, "eyebrow_thickness": -5,
- },
- "可爱": {
- "eye_size": 20, "eye_distance": -8, "nose_size": -12,
- "mouth_size": -5, "lip_thickness": 5, "eyebrow_thickness": 0,
- },
- "成熟": {
- "eye_size": -5, "eye_distance": 5, "nose_size": 0,
- "mouth_size": 8, "lip_thickness": 10, "eyebrow_thickness": 5,
- },
- "英气": {
- "eye_size": -5, "eye_distance": -5, "nose_size": 8,
- "mouth_size": 0, "lip_thickness": -8, "eyebrow_thickness": 10,
- },
- }
- class FaceParamSliders(QGroupBox):
- """五官参数滑块组,发射 params_changed(dict) 信号。"""
- params_changed = pyqtSignal(dict)
- def __init__(self, parent=None):
- super().__init__("五官参数(实时改变已生成图片,0=中性)", parent)
- self._sliders = {}
- self.recommend_callback = None # 外部传入的推荐计算回调
- self._build_ui()
- def _build_ui(self):
- lay = QVBoxLayout(self)
- lay.setSpacing(12)
-
- # 推荐配置按钮 + 预设风格
- btn_row = QHBoxLayout()
- btn_row.addStretch()
- preset_combo = QComboBox()
- preset_combo.addItem("五官风格 ▾")
- for name in PRESET_STYLES:
- preset_combo.addItem(name)
- preset_combo.setFixedWidth(100)
- preset_combo.currentIndexChanged.connect(self._on_preset_selected)
- btn_row.addWidget(preset_combo)
- recommend_btn = QPushButton("✨ 推荐配置(黄金比例)")
- recommend_btn.setStyleSheet("""
- QPushButton {
- background-color: #D45500;
- color: white;
- padding: 6px 16px;
- border-radius: 4px;
- font-weight: bold;
- }
- QPushButton:hover {
- background-color: #E06010;
- }
- """)
- recommend_btn.clicked.connect(self._apply_recommend)
- btn_row.addWidget(recommend_btn)
- lay.addLayout(btn_row)
-
- for key, label, neg_term, pos_term in FACE_PARAMS:
- row = QHBoxLayout()
- row.setSpacing(12)
- lbl = QLabel(label)
- lbl.setFixedWidth(90)
- row.addWidget(lbl)
- slider = QSlider(Qt.Orientation.Horizontal)
- slider.setRange(-100, 100)
- slider.setValue(0)
- slider.setFixedWidth(160)
- slider.valueChanged.connect(lambda v, k=key: self._on_changed(k, v))
- row.addWidget(slider)
- self._sliders[key] = slider
- val_lbl = QLabel("0")
- val_lbl.setFixedWidth(32)
- val_lbl.setStyleSheet("color: #666; font-size: 11px;")
- slider.valueChanged.connect(lambda v, l=val_lbl: l.setText(str(v)))
- row.addWidget(val_lbl)
- term_lbl = QLabel("—")
- term_lbl.setFixedWidth(140)
- term_lbl.setStyleSheet("color: #0078D4; font-size: 10px; font-family: Consolas, monospace;")
- slider.valueChanged.connect(
- lambda v, l=term_lbl, n=neg_term, p=pos_term:
- l.setText(p if v > 30 else (n if v < -30 else "—")))
- row.addWidget(term_lbl)
- lay.addLayout(row)
- def _on_changed(self, key, value):
- self.params_changed.emit(self.get_params())
- def get_params(self) -> dict:
- return {key: s.value() / 100.0 for key, s in self._sliders.items()}
- def _apply_recommend(self):
- """应用黄金比例推荐配置。"""
- # 如果有外部回调,就用回调计算推荐值
- if self.recommend_callback is not None:
- recommend_values = self.recommend_callback()
- else:
- # 默认推荐值(相对于中性状态的偏移)
- recommend_values = {
- # 骨骼结构(偏上镜审美,小脸)
- "face_width": -20,
- "face_height": 10,
- "cheekbone_width": -25,
- "jaw_width": -30,
- "chin_shape": -25,
- "face_roundness": -20,
- # 五官细节(精致+大眼)
- "eye_size": 35,
- "eye_distance": -5,
- "nose_size": -30,
- "mouth_size": -25,
- "lip_thickness": 10,
- "eyebrow_thickness": 5,
- }
-
- for key, value in recommend_values.items():
- if key in self._sliders:
- self._sliders[key].setValue(int(value))
- def _on_preset_selected(self, index):
- if index <= 0:
- return
- names = list(PRESET_STYLES.keys())
- if index - 1 >= len(names):
- return
- preset = PRESET_STYLES[names[index - 1]]
- for key, value in preset.items():
- if key in self._sliders:
- self._sliders[key].setValue(int(value))
- combo = self.sender()
- if combo:
- combo.setCurrentIndex(0)
-
- def reset(self):
- for s in self._sliders.values():
- s.setValue(0)
复制代码
|
|