367 lines
14 KiB
Plaintext
367 lines
14 KiB
Plaintext
|
import time
|
|||
|
|
|||
|
from PyQt5.QtGui import QPixmap, QImage
|
|||
|
from PyQt5.QtWidgets import QWidget, QFileDialog,QMainWindow, QLabel, QSizePolicy, QApplication, QAction, QHBoxLayout
|
|||
|
from PyQt5.QtCore import *
|
|||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
|
import sys
|
|||
|
import traceback
|
|||
|
|
|||
|
import ctypes as C
|
|||
|
import numpy as np
|
|||
|
import cv2
|
|||
|
import os
|
|||
|
from test_0415_ui import Ui_MainWindow
|
|||
|
from pyueye import ueye
|
|||
|
import numpy as np
|
|||
|
import cv2
|
|||
|
# 串口通信
|
|||
|
import serial
|
|||
|
import time
|
|||
|
import threading
|
|||
|
import torch
|
|||
|
from Class.Camera import Camera_class
|
|||
|
from Class.Motor import Motor_class
|
|||
|
from Class.Pan import Pan_class
|
|||
|
from Class.Yolo import yolo_class
|
|||
|
|
|||
|
|
|||
|
|
|||
|
class img_yolo(QtCore.QThread):
|
|||
|
sinOut = pyqtSignal(str) # 聲明一個帶字串參數的信號
|
|||
|
|
|||
|
def __init__(self,yolo_model,parent=None):
|
|||
|
super().__init__(parent)
|
|||
|
self.yolo = yolo_model
|
|||
|
|
|||
|
def normalize_image(self, img):
|
|||
|
if img is not None:
|
|||
|
normalized_image = cv2.normalize(img, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX)
|
|||
|
return normalized_image
|
|||
|
return None
|
|||
|
|
|||
|
def run(self):
|
|||
|
print('run')
|
|||
|
self.img_list = []
|
|||
|
self.filename_list = []
|
|||
|
for filename in os.listdir(r"./image_folder"):
|
|||
|
if filename.endswith('.jpg') or filename.endswith('.bmp'):
|
|||
|
img = cv2.imread('image_folder' + "/" + filename)
|
|||
|
self.img_list.append(img)
|
|||
|
self.filename_list.append(filename)
|
|||
|
# self.img_test(img, filename)
|
|||
|
print(f'img讀取完成')
|
|||
|
for i in range(0,len(self.filename_list)):
|
|||
|
img = self.img_list[i]
|
|||
|
file_name = self.filename_list[i]
|
|||
|
t1 = time.time()
|
|||
|
results = self.yolo.YoloDetect(img)
|
|||
|
t2 = time.time()
|
|||
|
print(f'推論時間 = {t2 - t1}')
|
|||
|
# print(results)
|
|||
|
print(f'{file_name}')
|
|||
|
|
|||
|
# 檢查是否有預測結果
|
|||
|
if results.pred[0] is None or len(results.pred[0]) == 0:
|
|||
|
continue
|
|||
|
|
|||
|
# 獲取預測的信心值和類別
|
|||
|
conf = results.pred[0][0, 4] # 取最高信心度
|
|||
|
predicted_classes = results.names[int(results.pred[0][0, -1])]
|
|||
|
|
|||
|
# 獲取 bounding box 的座標
|
|||
|
box = results.pred[0][0, :4].cpu().numpy().astype(int)
|
|||
|
|
|||
|
# 提取ROI (Region of Interest)
|
|||
|
roi = img[box[1]:box[3], box[0]:box[2]]
|
|||
|
|
|||
|
# 正規化ROI圖像
|
|||
|
normalized_roi = self.normalize_image(roi)
|
|||
|
|
|||
|
# 將正規化的ROI轉換為灰度圖像
|
|||
|
gray_roi = cv2.cvtColor(normalized_roi, cv2.COLOR_BGR2GRAY)
|
|||
|
|
|||
|
# 創建CLAHE對象
|
|||
|
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(3, 3))
|
|||
|
# 對灰度圖像應用CLAHE
|
|||
|
clahe_image = clahe.apply(gray_roi)
|
|||
|
|
|||
|
# # 二值化處理
|
|||
|
# _, binary_image = cv2.threshold(sharpened_image, 30, 255, cv2.THRESH_BINARY)
|
|||
|
|
|||
|
# 形態學膨脹
|
|||
|
# kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 8)) #用這個
|
|||
|
# dilated_image = cv2.dilate(binary_image, kernel, iterations=2)
|
|||
|
# closed_image = cv2.morphologyEx(binary_image, cv2.MORPH_CLOSE, kernel) #用這個
|
|||
|
# opened_image = cv2.morphologyEx(binary_image, cv2.MORPH_OPEN, kernel)
|
|||
|
|
|||
|
# 將圖像轉換為灰度格式
|
|||
|
# gray_image = cv2.cvtColor(closed_image, cv2.COLOR_BGR2GRAY)
|
|||
|
|
|||
|
# 找到輪廓
|
|||
|
# contours, _ = cv2.findContours(closed_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
|||
|
|
|||
|
# 取得原圖檔名稱
|
|||
|
base_name, ext = os.path.splitext(file_name)
|
|||
|
|
|||
|
# 另存繪製後的ROI,檔名加上 '_2'
|
|||
|
new_file_name = f'{base_name}_2{ext}'
|
|||
|
print(f'Saving {new_file_name}')
|
|||
|
cv2.imwrite(f'img_2/{new_file_name}', clahe_image)
|
|||
|
|
|||
|
# # 獲取最外圍輪廓
|
|||
|
# if len(contours) > 0:
|
|||
|
# # 擬合最外圍輪廓為橢圓
|
|||
|
# ellipse = cv2.fitEllipse(contours[0])
|
|||
|
#
|
|||
|
# # 在原圖上繪製橢圓
|
|||
|
# contour_image = roi.copy()
|
|||
|
# cv2.ellipse(contour_image, ellipse, (0, 255, 0), 1) # 使用綠色線條繪製橢圓
|
|||
|
#
|
|||
|
# # 取得原圖檔名稱
|
|||
|
# base_name, ext = os.path.splitext(file_name)
|
|||
|
#
|
|||
|
# # 另存繪製後的ROI,檔名加上 '_2'
|
|||
|
# new_file_name = f'{base_name}_2{ext}'
|
|||
|
# print(f'Saving {new_file_name}')
|
|||
|
# cv2.imwrite(f'img_2/{new_file_name}', sharpened_image)
|
|||
|
#
|
|||
|
# # 如果信心值超過0.6,則保存圖片
|
|||
|
# if conf > 0.6:
|
|||
|
# resized_frame_high_conf = cv2.resize(results.render()[0], (1280, 1280))
|
|||
|
# print(f'Saving {file_name}')
|
|||
|
# cv2.imwrite(f'img_2/{file_name}', resized_frame_high_conf)
|
|||
|
# else:
|
|||
|
# print("No contours found.")
|
|||
|
|
|||
|
# # 如果信心值超過0.6,則保存圖片
|
|||
|
# if conf > 0.6:
|
|||
|
# # 獲取 bounding box 的座標
|
|||
|
# box = results.pred[0][0, :4].cpu().numpy().astype(int)
|
|||
|
#
|
|||
|
# # 保留原本的推論結果,另存原圖像
|
|||
|
# print(f'Saving {file_name}')
|
|||
|
# cv2.imwrite(f'img_2/{file_name}', img)
|
|||
|
#
|
|||
|
# # 繪製 bounding box 在原圖上
|
|||
|
# cv2.rectangle(img, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 2) # 使用綠色線條繪製
|
|||
|
#
|
|||
|
# # 調整圖像大小
|
|||
|
# resized_frame = cv2.resize(img, (1280, 1280))
|
|||
|
#
|
|||
|
# # 取得原圖檔名稱
|
|||
|
# base_name, ext = os.path.splitext(file_name)
|
|||
|
#
|
|||
|
# # 另存繪製後的圖像,檔名加上 '_2'
|
|||
|
# new_file_name = f'{base_name}_2{ext}'
|
|||
|
# print(f'Saving {new_file_name}')
|
|||
|
# cv2.imwrite(f'img_2/{new_file_name}', resized_frame)
|
|||
|
#
|
|||
|
# else:
|
|||
|
# # 保留原本的推論結果,另存原圖像
|
|||
|
# resized_frame = cv2.resize(results.render()[0], (1280, 1280))
|
|||
|
# print(f'Saving {file_name}')
|
|||
|
# cv2.imwrite(f'img_2/{file_name}', resized_frame)
|
|||
|
|
|||
|
|
|||
|
def img_to_view(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(QMainWindow,Ui_MainWindow):
|
|||
|
def __init__(self, parent=None): #按鍵設定
|
|||
|
super(MainWindow, self).__init__(parent)
|
|||
|
self.setupUi(self)
|
|||
|
# self.view_1.setScaledContents(True)
|
|||
|
# self.view_2.setScaledContents(True)
|
|||
|
# self.view_3.setScaledContents(True)
|
|||
|
# self.view_4.setScaledContents(True)
|
|||
|
|
|||
|
self.bt_1.clicked.connect(self.bt_1_clicked)
|
|||
|
# self.bt_2.clicked.connect(self.bt_2_clicked) # 連接按鈕到新的功能
|
|||
|
self.bt_3.clicked.connect(self.bt_3_clicked)
|
|||
|
|
|||
|
self.cam = Camera_class()
|
|||
|
self.cam.start()
|
|||
|
self.cam.rawdata.connect(self.show_img)
|
|||
|
|
|||
|
self.run_flag = True
|
|||
|
self.com5 = Motor_class()
|
|||
|
self.com5.start()
|
|||
|
self.com5.sinOut.connect(self.com5_str)
|
|||
|
|
|||
|
|
|||
|
self.com4 = Pan_class()
|
|||
|
self.com4.start()
|
|||
|
self.com4.sinOut.connect(self.com4_str)
|
|||
|
self.count = 0
|
|||
|
self.img_count=0
|
|||
|
|
|||
|
self.yolo = yolo_class('weight/best.pt')
|
|||
|
#self.yolo.start()
|
|||
|
# self.img_test_2()
|
|||
|
|
|||
|
|
|||
|
def show_img(self,img):
|
|||
|
self.img = img
|
|||
|
h,w,_ = self.img.shape
|
|||
|
img= img_to_view(img)
|
|||
|
self.view_1.setPixmap(QtGui.QPixmap.fromImage(img))
|
|||
|
|
|||
|
def bt_1_clicked(self):
|
|||
|
self.time_2= time.time()
|
|||
|
self.com5.start_run()
|
|||
|
self.run_flag = True
|
|||
|
self.time_1 = time.time()
|
|||
|
|
|||
|
def com5_str(self,str_1):
|
|||
|
if str_1 =='move':
|
|||
|
self.count = self.count+1
|
|||
|
if self.count< 6:
|
|||
|
print(self.count)
|
|||
|
if str_1 == 'move':
|
|||
|
self.img_count = 0
|
|||
|
self.com4.move()
|
|||
|
if self.count == 5:
|
|||
|
self.run_flag = False
|
|||
|
if str_1 =='2':
|
|||
|
# self.img_test()
|
|||
|
#self.time_1 = time.time()
|
|||
|
#print(f's={self.time_1-self.time_2}')
|
|||
|
# print('save_img')
|
|||
|
self.img_count = self.img_count+1
|
|||
|
cv2.imwrite(f'image_folder\\{str(self.count)}_{self.img_count}.jpg',self.img)
|
|||
|
#self.time_2= time.time()
|
|||
|
|
|||
|
def com4_str(self,str_1):
|
|||
|
if str_1 =='move_end' and self.run_flag == True:
|
|||
|
self.com5.start_run()
|
|||
|
if str_1 == 'Motor emergency stop 010':
|
|||
|
print('010')
|
|||
|
self.run_flag = False
|
|||
|
self.count = 0
|
|||
|
time_2 = time.time()
|
|||
|
print(f'all_time - {time_2 - self.time_1}')
|
|||
|
self.bt_3_clicked()
|
|||
|
|
|||
|
|
|||
|
# def bt_3_clicked(self):
|
|||
|
# options = QFileDialog.Options()
|
|||
|
# options |= QFileDialog.ReadOnly
|
|||
|
# filePath, _ = QFileDialog.getOpenFileName(self, "選擇圖片", "", "圖片文件 (*.bmp *.jpg *.png);;所有文件 (*)",
|
|||
|
# options=options)
|
|||
|
# # print(filePath)
|
|||
|
# img = cv2.imread(filePath)
|
|||
|
# t1 = time.time()
|
|||
|
# results = self.yolo.YoloDetect(img)
|
|||
|
# t2=time.time()
|
|||
|
# # print(f'推論時間 = {t2-t1}')
|
|||
|
# # print(results)
|
|||
|
# # 檢查是否有預測結果
|
|||
|
# if results.pred[0] is None or len(results.pred[0]) == 0:
|
|||
|
# # self.label1.setText("沒有瑕疵物件")
|
|||
|
# return
|
|||
|
#
|
|||
|
# # 獲取預測的類別
|
|||
|
# predicted_classes = results.names[int(results.pred[0][0, -1])] # 取最高信心度的類別
|
|||
|
# resized_frame = cv2.resize(results.render()[0], (1920, 1280))
|
|||
|
# # print(resized_frame)
|
|||
|
# img = img_to_view(resized_frame)
|
|||
|
# self.view_2.setPixmap(QtGui.QPixmap.fromImage(img))
|
|||
|
#
|
|||
|
# def img_test(self,img,file_name):
|
|||
|
# t1 = time.time()
|
|||
|
# results = self.yolo.YoloDetect(img)
|
|||
|
# t2 = time.time()
|
|||
|
# print(f'推論時間 = {t2 - t1}')
|
|||
|
# # print(results)
|
|||
|
# print(f'{file_name}')
|
|||
|
#
|
|||
|
# # 檢查是否有預測結果
|
|||
|
# if results.pred[0] is None or len(results.pred[0]) == 0:
|
|||
|
# # self.label1.setText("沒有瑕疵物件")
|
|||
|
# return
|
|||
|
#
|
|||
|
# # 獲取預測的類別
|
|||
|
# predicted_classes = results.names[int(results.pred[0][0, -1])] # 取最高信心度的類別
|
|||
|
# resized_frame = cv2.resize(results.render()[0], (1920, 1280))
|
|||
|
# # print(resized_frame)
|
|||
|
# # img = img_to_view(resized_frame)
|
|||
|
# # self.view_2.setPixmap(QtGui.QPixmap.fromImage(img))
|
|||
|
# print(f'{file_name}')
|
|||
|
# cv2.imwrite(f'img_2/{file_name}', resized_frame)
|
|||
|
|
|||
|
def img_test_2(self):
|
|||
|
img_list=[]
|
|||
|
for filename in os.listdir(r"./image_folder"):
|
|||
|
if filename.endswith('.jpg'):
|
|||
|
img = cv2.imread('image_folder' + "/" + filename)
|
|||
|
img_list.append(img)
|
|||
|
# self.img_test(img, filename)
|
|||
|
print(f'img讀取完成')
|
|||
|
run_list=[]
|
|||
|
for img in img_list:
|
|||
|
run_list.append(img_yolo( self.yolo,img))
|
|||
|
for i in range (0,len(run_list)):
|
|||
|
run_list[i].start()
|
|||
|
|
|||
|
def bt_3_clicked(self):
|
|||
|
self.T1 = img_yolo(self.yolo)
|
|||
|
self.T1.finished.connect(self.on_yolo_finished) # Connect to finished signal
|
|||
|
self.T1.start()
|
|||
|
|
|||
|
def on_yolo_finished(self):
|
|||
|
img_confidence = {} # Dictionary to store confidence values for images
|
|||
|
# Load images from img_3 folder
|
|||
|
for filename in os.listdir(r"./img_2"):
|
|||
|
if filename.endswith('.jpg'):
|
|||
|
img_path = os.path.join("./img_2", filename)
|
|||
|
img = cv2.imread(img_path)
|
|||
|
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
|||
|
h, w, _ = img_rgb.shape
|
|||
|
qimg = QtGui.QImage(img_rgb.data, w, h, w * 3, QtGui.QImage.Format_RGB888)
|
|||
|
|
|||
|
# Perform YOLO detection and get confidence value
|
|||
|
results = self.yolo.YoloDetect(img)
|
|||
|
if results.pred[0] is not None and len(results.pred[0]) > 0:
|
|||
|
conf = results.pred[0][0, 4] # Confidence value
|
|||
|
else:
|
|||
|
conf = 0
|
|||
|
|
|||
|
img_confidence[filename] = conf
|
|||
|
|
|||
|
# Sort images by confidence value in descending order
|
|||
|
sorted_imgs = sorted(img_confidence.items(), key=lambda x: x[1], reverse=True)
|
|||
|
|
|||
|
count = 0 # Count the number of displayed images
|
|||
|
# Display images in view_2, view_3, and view_4 based on confidence value
|
|||
|
for filename, _ in sorted_imgs:
|
|||
|
img_path = os.path.join("./img_2", filename)
|
|||
|
img = cv2.imread(img_path)
|
|||
|
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
|||
|
h, w, _ = img_rgb.shape
|
|||
|
qimg = QtGui.QImage(img_rgb.data, w, h, w * 3, QtGui.QImage.Format_RGB888)
|
|||
|
|
|||
|
if not self.view_2.pixmap():
|
|||
|
self.view_2.setPixmap(QtGui.QPixmap.fromImage(qimg))
|
|||
|
count += 1
|
|||
|
elif not self.view_3.pixmap():
|
|||
|
self.view_3.setPixmap(QtGui.QPixmap.fromImage(qimg))
|
|||
|
count += 1
|
|||
|
elif not self.view_4.pixmap():
|
|||
|
self.view_4.setPixmap(QtGui.QPixmap.fromImage(qimg))
|
|||
|
count += 1
|
|||
|
|
|||
|
# Break the loop if displayed 3 images
|
|||
|
if count == 3:
|
|||
|
break
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if __name__ == "__main__":
|
|||
|
app = QApplication(sys.argv)
|
|||
|
window = MainWindow()
|
|||
|
window.show()
|
|||
|
sys.exit(app.exec_())
|