Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from config import FIELD_FEATURE_COUNT, MONSTER_DATA
from simular_history_match_ui import HistoryMatchUI
from input_panel_ui import InputPanelUI
from prediction_share_image import create_prediction_share_pixmap

logging.getLogger().setLevel(logging.DEBUG)
logging.getLogger("PIL").setLevel(logging.INFO)
Expand Down Expand Up @@ -134,6 +135,8 @@ def __init__(self):
if not self.cannot_model.is_model_loaded:
self.recognize_button.setEnabled(False)
self.recognize_button.setToolTip("模型未加载,无法使用此功能")
self.copy_image_button.setEnabled(False)
self.copy_image_button.setToolTip("模型未加载,无法使用此功能")
self.input_panel.predict_button.setEnabled(False)
self.input_panel.predict_button.setToolTip("模型未加载,无法使用此功能")

Expand Down Expand Up @@ -262,6 +265,12 @@ def init_ui(self):
self.recognize_only_button.setFixedWidth(80) # 小按钮
result_identify_layout.addWidget(self.recognize_only_button)

self.copy_image_button = QPushButton("复制图片")
self.copy_image_button.clicked.connect(self.copy_prediction_image)
self.copy_image_button.setStyleSheet(self.qt_button_style)
self.copy_image_button.setFixedWidth(90)
result_identify_layout.addWidget(self.copy_image_button)

result_layout.addWidget(result_identify_group)

center_layout.addWidget(result_group)
Expand Down Expand Up @@ -838,6 +847,36 @@ def predict(self):
left_monsters_dict, right_monsters_dict = self.input_panel.get_monster_counts()
self.history_match_ui.render_similar_matches(left_monsters_dict, right_monsters_dict)

def get_active_monsters(self, monsters_dict):
monsters = []
for monster_id_text, entry in monsters_dict.items():
count_text = entry.text()
if not count_text.isdigit() or int(count_text) <= 0:
continue
monster_id = int(monster_id_text)
monster_name = MONSTER_DATA["原始名称"][monster_id]
monsters.append((monster_id, monster_name, int(count_text)))
return monsters

def copy_prediction_image(self):
left_monsters_dict, right_monsters_dict = self.input_panel.get_monster_counts()
left_monsters = self.get_active_monsters(left_monsters_dict)
right_monsters = self.get_active_monsters(right_monsters_dict)

if not left_monsters and not right_monsters:
QMessageBox.information(self, "提示", "请先填写或识别双方怪物。")
return

prediction = self.get_prediction()
self.update_prediction(prediction)
self.update_input_display()

model_name = Path(self.cannot_model.model_path).name if self.cannot_model.model_path else "未加载"
pixmap = create_prediction_share_pixmap(left_monsters, right_monsters, prediction, model_name)
QApplication.clipboard().setPixmap(pixmap)
self.copy_image_button.setText("已复制")
QtCore.QTimer.singleShot(1200, lambda: self.copy_image_button.setText("复制图片"))

def get_recognize(self):
"""
根据当前模式获取截图并识别
Expand Down
151 changes: 151 additions & 0 deletions prediction_share_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
from PyQt6.QtCore import Qt, QRectF
from PyQt6.QtGui import QColor, QFont, QPainter, QPixmap


def get_prediction_result_text(left_win_prob):
winner = "左方" if left_win_prob > 0.5 else "右方"
if 0.6 > left_win_prob > 0.4:
winner = "难说"

if winner == "左方":
return "预测胜方: 左方", "#d84a3a"
if winner == "右方":
return "预测胜方: 右方", "#2389c9"
return "这一把难说", "#242424"


def create_prediction_share_pixmap(left_monsters, right_monsters, prediction, model_name):
right_win_prob = prediction
left_win_prob = 1 - right_win_prob
winner_text, winner_color = get_prediction_result_text(left_win_prob)

tile_w, tile_h = 84, 80
columns_per_side = 3
panel_w = tile_w * columns_per_side + 24
gap = 36
result_h = 116
footer_h = 24
margin_x = 42
margin_y = 22
left_rows = max(1, (len(left_monsters) + columns_per_side - 1) // columns_per_side)
right_rows = max(1, (len(right_monsters) + columns_per_side - 1) // columns_per_side)
rows = max(left_rows, right_rows)
width = panel_w * 2 + gap + margin_x * 2
panel_h = 44 + rows * tile_h + 16
height = margin_y * 2 + panel_h + result_h + footer_h

pixmap = QPixmap(width, height)
pixmap.fill(QColor("#f4f1e8"))

painter = QPainter(pixmap)
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
painter.setPen(Qt.PenStyle.NoPen)
painter.fillRect(QRectF(0, 0, width, height), QColor("#f4f1e8"))

subtitle_font = QFont("Microsoft YaHei", 13, QFont.Weight.Bold)
normal_font = QFont("Microsoft YaHei", 12, QFont.Weight.Bold)
count_font = QFont("Microsoft YaHei", 15, QFont.Weight.Bold)
winner_font = QFont("Microsoft YaHei", 24, QFont.Weight.Bold)
rate_font = QFont("Microsoft YaHei", 18, QFont.Weight.Bold)
model_font = QFont("Microsoft YaHei", 9)

left_rect = QRectF(margin_x, margin_y, panel_w, panel_h)
right_rect = QRectF(margin_x + panel_w + gap, margin_y, panel_w, panel_h)
draw_prediction_panel(
painter, left_rect, "左方", left_monsters, "#d84a3a", columns_per_side, tile_w, tile_h,
subtitle_font, normal_font, count_font
)
draw_prediction_panel(
painter, right_rect, "右方", right_monsters, "#2389c9", columns_per_side, tile_w, tile_h,
subtitle_font, normal_font, count_font
)

result_top = margin_y + panel_h + 36
painter.setPen(QColor(winner_color))
painter.setFont(winner_font)
painter.drawText(
QRectF(margin_x, result_top, width - margin_x * 2, 42),
Qt.AlignmentFlag.AlignCenter,
winner_text,
)
painter.setFont(rate_font)
painter.drawText(
QRectF(margin_x, result_top + 48, width - margin_x * 2, 34),
Qt.AlignmentFlag.AlignCenter,
f"左 {left_win_prob:.2%} | 右 {right_win_prob:.2%}",
)

painter.setPen(QColor("#9a9a9a"))
painter.setFont(model_font)
painter.drawText(
QRectF(margin_x, height - margin_y - 2, width - margin_x * 2, 18),
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter,
f"model: {model_name}",
)
painter.end()
return pixmap


def draw_prediction_panel(
painter, rect, side_name, monsters, accent_color, columns, tile_w, tile_h,
subtitle_font, normal_font, count_font
):
painter.setPen(Qt.PenStyle.NoPen)
painter.setBrush(QColor("#ffffff"))
painter.drawRoundedRect(rect, 14, 14)

painter.setBrush(QColor(accent_color))
header_height = 38
painter.drawRoundedRect(QRectF(rect.x(), rect.y(), rect.width(), header_height), 14, 14)
painter.drawRect(QRectF(rect.x(), rect.y() + 19, rect.width(), 19))

painter.setPen(QColor("#ffffff"))
painter.setFont(subtitle_font)
painter.drawText(
QRectF(rect.x() + 18, rect.y() + 5, rect.width() - 36, 30),
Qt.AlignmentFlag.AlignCenter,
side_name,
)

if not monsters:
painter.setPen(QColor("#777777"))
painter.setFont(normal_font)
painter.drawText(
QRectF(rect.x(), rect.y() + 66, rect.width(), 40),
Qt.AlignmentFlag.AlignCenter,
"无怪物",
)
return

start_x = rect.x() + 12
start_y = rect.y() + 52
for idx, (_, monster_name, count) in enumerate(monsters):
row = idx // columns
col = idx % columns
tile_rect = QRectF(start_x + col * tile_w, start_y + row * tile_h, tile_w - 10, tile_h - 4)

painter.setPen(Qt.PenStyle.NoPen)
painter.setBrush(QColor("#ededed"))
painter.drawRoundedRect(tile_rect, 10, 10)

monster_pixmap = QPixmap(f"images/{monster_name}.png")
if monster_pixmap.isNull():
monster_pixmap = QPixmap("images/empty.png")
if not monster_pixmap.isNull():
icon_rect = QRectF(tile_rect.x() + 16, tile_rect.y() + 6, 44, 42)
scaled = monster_pixmap.scaled(
int(icon_rect.width()), int(icon_rect.height()),
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation,
)
draw_x = icon_rect.x() + (icon_rect.width() - scaled.width()) / 2
draw_y = icon_rect.y() + (icon_rect.height() - scaled.height()) / 2
painter.drawPixmap(int(draw_x), int(draw_y), scaled)

painter.setFont(count_font)
painter.setPen(QColor("#222222"))
painter.drawText(
QRectF(tile_rect.x(), tile_rect.y() + 52, tile_rect.width(), 22),
Qt.AlignmentFlag.AlignCenter,
f"x{count}",
)