Python/pyqt5/CODE/ROIpractice/main.py
2024-06-25 22:02:02 +08:00

146 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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_())