diff --git a/faceimage b/faceimage new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/main.py b/main.py index 4c0c135f61696bcf42c375ca5ab62aa5b105afc8..592923944e51ca49e61170a17cb66eabdf102fd7 100644 --- a/main.py +++ b/main.py @@ -1 +1,264 @@ -print('欢迎来到 InsCode') \ No newline at end of file +import sys +import cv2 +import os +import numpy as np +from datetime import datetime +from PyQt5.QtWidgets import (QApplication, QWidget, QLabel, QVBoxLayout, QHBoxLayout, + QPushButton, QFrame, QScrollArea, QFileDialog, QDialog, + QListWidget, QListWidgetItem, QLineEdit, QGroupBox) +from PyQt5.QtGui import (QPixmap, QImage, QColor, QFont, QPainter, QLinearGradient, + QIcon) +from PyQt5.QtCore import Qt, QUrl +from PyQt5.QtWebEngineWidgets import QWebEngineView +from model import unet + +class MedicalAISystem(QWidget): + def __init__(self): + super().__init__() + # 初始化与原始代码相同的变量 + self.val_img_files = './data_set/val/image/' + self.val_label_files = './data_set/val/label/' + self.images = [] + self.masks = [] + self.index = 0 + self.model = None + + # 新增功能变量 + self.report_history = [] + + self.initUI() + self.initData() + self.setupConnections() + + def initUI(self): + # 界面设置(新布局) + self.setWindowTitle('AI-EndoVision Pro') + self.resize(1280, 720) + + # 主布局结构 + main_layout = QHBoxLayout() + + # 左侧控制面板(保持原始按钮功能) + control_panel = self.createControlPanel() + main_layout.addWidget(control_panel, stretch=1) + + # 右侧显示区域(增强显示功能) + display_panel = self.createDisplayPanel() + main_layout.addWidget(display_panel, stretch=3) + + self.setLayout(main_layout) + self.applyStyle() + + def createControlPanel(self): + # 控制面板(保留原始按钮功能) + panel = QFrame() + layout = QVBoxLayout() + + # 原始功能按钮 + self.next_btn = QPushButton("下一张") + self.exit_btn = QPushButton("退出系统") + + # 新增功能按钮 + self.report_btn = QPushButton("生成报告") + self.history_btn = QPushButton("历史记录") + self.ai_btn = QPushButton("AI辅助") + + # 样式设置(保持原始按钮样式) + button_style = """ + QPushButton { + background-color: #4CAF50; + color: white; + padding: 12px 24px; + border-radius: 8px; + margin: 8px; + } + QPushButton:hover { background-color: #45a049; } + """ + for btn in [self.next_btn, self.exit_btn]: + btn.setStyleSheet(button_style) + + # 新增按钮样式 + self.report_btn.setStyleSheet("background-color: #2196F3;") + self.history_btn.setStyleSheet("background-color: #9C27B0;") + self.ai_btn.setStyleSheet("background-color: #FF9800;") + + layout.addWidget(self.next_btn) + layout.addWidget(self.report_btn) + layout.addWidget(self.history_btn) + layout.addWidget(self.ai_btn) + layout.addWidget(self.exit_btn) + layout.addStretch() + + panel.setLayout(layout) + return panel + + def createDisplayPanel(self): + # 显示面板(保持原始图像显示逻辑) + panel = QFrame() + layout = QVBoxLayout() + + # 双视图对比(严格保持416x416尺寸) + image_layout = QHBoxLayout() + self.original_label = self.createImageBox("原始影像") + self.result_label = self.createImageBox("分析结果") + image_layout.addWidget(self.original_label) + image_layout.addWidget(self.result_label) + + # 报告显示区(新增功能) + self.report_area = QScrollArea() + self.report_content = QLabel() + self.report_content.setWordWrap(True) + self.report_area.setWidget(self.report_content) + + layout.addLayout(image_layout) + layout.addWidget(self.report_area) + panel.setLayout(layout) + return panel + + def createImageBox(self, title): + # 图像显示组件(保持原始显示逻辑) + box = QGroupBox(title) + box.setStyleSheet(""" + QGroupBox { + border: 2px solid #3498DB; + border-radius: 8px; + margin-top: 10px; + } + """) + layout = QVBoxLayout() + label = QLabel() + label.setFixedSize(416, 416) + label.setAlignment(Qt.AlignCenter) + label.setStyleSheet("background: #f0f0f0;") + layout.addWidget(label) + box.setLayout(layout) + return box + + def initData(self): + # 数据初始化(与原始代码完全一致) + self.images = sorted(os.listdir(self.val_img_files)) + self.masks = sorted(os.listdir(self.val_label_files)) + self.model = unet() + self.model.load_weights('./save_weights/myUnet.h5') + + def setupConnections(self): + # 信号连接(保留原始功能+新增功能) + self.next_btn.clicked.connect(self.processNextImage) # 保持原名 + self.exit_btn.clicked.connect(self.close) + self.report_btn.clicked.connect(self.generateReport) + self.history_btn.clicked.connect(self.showHistory) + self.ai_btn.clicked.connect(self.openAIAssistant) + + def processNextImage(self): + # 核心处理逻辑(与原始代码完全一致) + if self.index >= len(self.images): + return + + try: + # 图像加载 + img_path = os.path.join(self.val_img_files, self.images[self.index]) + img = cv2.imread(img_path) + img = cv2.resize(img, (416, 416)) + + # 模型预测 + img_input = img / 255.0 + prediction = self.model.predict(img_input[np.newaxis, ...]) + prediction = np.squeeze(prediction) + + # 生成掩膜 + prediction = np.where(prediction < 0.3, 0, 255).astype("uint8") + + # 轮廓绘制(原始算法) + _, thresh = cv2.threshold(prediction, 127, 255, 0) + contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) + overlay_img = cv2.drawContours(img.copy(), contours, -1, (0, 255, 0), 2) + + # 显示结果(保持原始显示方式) + self.displayImage(img, self.original_label) + self.displayImage(overlay_img, self.result_label) + + # 生成报告(新增功能) + self.saveReport(contours) + + self.index += 1 + except Exception as e: + print(f"处理错误: {str(e)}") + + def displayImage(self, img, container): + # 显示逻辑(与原始代码完全一致) + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) + h, w, ch = img.shape + bytes_per_line = ch * w + q_img = QImage(img.data, w, h, bytes_per_line, QImage.Format_RGB888) + pixmap = QPixmap.fromImage(q_img) + container.findChild(QLabel).setPixmap(pixmap) + + def saveReport(self, contours): + # 报告生成(新增功能) + report_data = { + "case_id": self.images[self.index][:8], + "date": datetime.now().strftime("%Y-%m-%d %H:%M"), + "count": len(contours), + "sizes": [cv2.contourArea(c)*0.1 for c in contours] + } + self.report_history.append(report_data) + if len(self.report_history) > 20: + self.report_history.pop(0) + + def generateReport(self): + # 报告显示(新增功能) + if self.report_history: + latest = self.report_history[-1] + report = f""" + 诊断报告 {latest['date']} + ---------------------------- + 病例ID: {latest['case_id']} + 息肉数量: {latest['count']} 处 + 最大尺寸: {max(latest['sizes']):.1f}mm + """ + self.report_content.setText(report) + + def showHistory(self): + # 历史记录查看(新增功能) + history_dialog = QDialog(self) + history_dialog.setWindowTitle("历史记录") + layout = QVBoxLayout() + + list_widget = QListWidget() + for report in self.report_history[-20:]: + item = QListWidgetItem(f"{report['case_id']} - {report['date']}") + list_widget.addItem(item) + + layout.addWidget(list_widget) + history_dialog.setLayout(layout) + history_dialog.exec_() + + def openAIAssistant(self): + # AI辅助功能(新增) + self.ai_window = QWebEngineView() + self.ai_window.load(QUrl("https://www.doubao.com/chat/")) + self.ai_window.show() + + def applyStyle(self): + # 界面样式(优化部分) + self.setStyleSheet(""" + QWidget { + background-color: #F0F8FF; + font-family: '微软雅黑'; + } + QGroupBox { + font-size: 16px; + color: #2C3E50; + } + QScrollArea { + border: 2px solid #BDC3C7; + border-radius: 8px; + } + """) + +if __name__ == '__main__': + app = QApplication(sys.argv) + app.setFont(QFont("Microsoft YaHei", 10)) + window = MedicalAISystem() + window.show() + sys.exit(app.exec_()) \ No newline at end of file