146 lines
6.6 KiB
Python
146 lines
6.6 KiB
Python
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_())
|