import cv2 import sys, time, os import numpy as np from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtGui import QColor,QPen,QPainter,QPixmap,QImage,QPainterPath,QPolygonF from test1 import Ui_MainWindow from PyQt5.QtCore import QDate,QTime,Qt, QRect, QPoint, pyqtSignal from PyQt5.QtWidgets import QApplication, QFileDialog, QLabel,QMainWindow, QWidget, QPushButton def original(img): # 原圖 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # QT顏色顯示轉換 Ny , Nx , _ =img.shape img = QtGui.QImage(img.data, Nx, Ny, Nx*3 , QtGui.QImage.Format_RGB888) # 須改格式 return img class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, parent=None): #按鍵設定 super(MainWindow, self).__init__(parent) self.setupUi(self) self.PhotoOpen_Btn_1.clicked.connect(self.openfile1) # 按鍵open1 self.ROI_Btn.clicked.connect(self.showNewWindow) # 按鍵open1 self.roi_rect = QRect(100, 100, 50, 50) # ROI 的固定座標與大小 (x,y,Rx,Ry) xy為原始圖片的座標位置,RxRy為以座標位置延伸的長寬 # 開啟資料夾 並選擇圖片 def openfile1(self): filename, _ = QFileDialog.getOpenFileName(self, 'Open Image') self.img = cv2.imread(str(filename),cv2.IMREAD_GRAYSCALE) self.img_original = original(self.img) #original 為轉UI顯示格式 self.img_view1=self.img_original self.photoshow1.setPixmap(QtGui.QPixmap.fromImage(self.img_view1)) #選取ROI 開啟新視窗 def showNewWindow(self): self.nw = newWindow(self.img_view1) # 連接新視窗 self.nw.positionsChanged.connect(self.handlePositionsChanged) # 連接信號 self.nw.imageSaved.connect(self.receiveImage)# 連接信號 self.nw.show() # 顯示新視窗 x = self.nw.pos().x() # 取得新視窗目前 x 座標 y = self.nw.pos().y() # 取得新視窗目前 y 座標 self.nw.move(x+20, y) # 移動新視窗位置 def handlePositionsChanged(self, positions): # 這個方法會在 newWindow 實例發出 positionsChanged 信號時被調用 # positions 參數包含了 newWindow 實例發出信號時傳遞的數據 self.clicked_positions = positions print(self.clicked_positions) def receiveImage(self, image): self.photoshow2.setPixmap(QtGui.QPixmap.fromImage(image)) print(image) pass class newWindow(QtWidgets.QMainWindow): positionsChanged = pyqtSignal(list) imageSaved = QtCore.pyqtSignal(QtGui.QImage) def __init__(self,img_view1): super(newWindow, self).__init__() self.img_view1 = img_view1 #將主畫面讀到的圖檔拉來子畫面 self.ui() #子畫面初始化元件 self.newWindowsize_x =self.img_view1.width() self.newWindowsize_y =self.img_view1.height() self.setWindowTitle('newWindow') self.setFixedSize(800, 800) self.setMouseTracking(True) self.shownewWindowlabel1() self.clicked_positions = [] def ui(self): self.newWindowlabel1 = QtWidgets.QLabel(self) self.newWindowlabel1.setText('newWindowlabel1') self.newWindowlabel1.setGeometry(0, 0, 800, 800) self.newWindowlabel1.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) # 設置文本對齊在左上角 # self.newWindowlabel1.setScaledContents(True) self.newWindowlabel2 = QtWidgets.QLabel(self) self.newWindowlabel2.setText('newWindowlabel2') self.newWindowlabel2.setGeometry(0, 0, 200, 100) self.newWindowlabel2.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) # 設置文本對齊在左上角 def shownewWindowlabel1(self): self.img_pixmap = QtGui.QPixmap.fromImage(self.img_view1) def paintEvent(self,event): super().paintEvent(event) qpainter = QPainter(self) qpainter.drawPixmap(self.rect(), self.img_pixmap) # 在窗口上繪製圖片,保持原始尺寸 qpainter.setPen(QPen(QColor('#ff0000'), 5)) for pos in self.clicked_positions: x, y = pos qpainter.drawPoint(x, y) if len(self.clicked_positions) == 4: # 將最後一個點和第一個點連線 for i in range(len(self.clicked_positions)): x1, y1 = self.clicked_positions[i] x2, y2 = self.clicked_positions[(i + 1) % len(self.clicked_positions)] qpainter.drawLine(x1, y1, x2, y2) qpainter.end() self.cropImage() self.close() def cropImage(self): per_x = self.img_pixmap.size().width() / self.width() per_y = self.img_pixmap.size().height() / self.height() x_values = [pos[0] for pos in self.clicked_positions] y_values = [pos[1] for pos in self.clicked_positions] self.min_x = int(min(x_values)*per_x) self.max_x = int(max(x_values)*per_x) self.min_y = int(min(y_values)*per_y) self.max_y = int(max(y_values)*per_y) qimage = self.img_pixmap.toImage() cropped_qimage = qimage.copy(self.min_x, self.min_y, self.max_x - self.min_x, self.max_y - self.min_y) self.cropped_pixmap = QPixmap.fromImage(cropped_qimage) self.cropped_pixmap.save(r"D:\python_code\photo\cropped_image.jpg") # 儲存裁剪後的圖像 def mousePressEvent(self, event): if event.button() == 1: x = event.x() y = event.y() self.clicked_positions.append((x, y)) print(self.clicked_positions) self.newWindowlabel2.setText(f'{x}, {y}') # 透過 QLabel 顯示滑鼠座標 self.update() def savePaintedPixmap(self): # 创建新的 QPixmap 对象,并在其上绘制原始图片和红点 center_x = self.img_pixmap.width() // 2 center_y = self.img_pixmap.height()// 2 painted_pixmap = QtGui.QPixmap(self.img_pixmap.size()) painter = QtGui.QPainter(painted_pixmap) painted_pixmap.fill(QtCore.Qt.black) # painter.drawPixmap(self.cropped_pixmap.width(),self.cropped_pixmap.height(), self.cropped_pixmap) painter.drawPixmap(center_x,center_y, self.cropped_pixmap) painter.end() # 将 QPixmap 转换为 QImage 并发送 painted_image = painted_pixmap.toImage() self.imageSaved.emit(painted_image) def closeEvent(self, event): self.savePaintedPixmap() self.positionsChanged.emit(self.clicked_positions) if __name__=='__main__': app = QtWidgets.QApplication(sys.argv) win = MainWindow() win.show() sys.exit(app.exec_())