451 lines
23 KiB
Python
451 lines
23 KiB
Python
|
import configparser
|
|||
|
import copy
|
|||
|
import threading
|
|||
|
import time
|
|||
|
from datetime import datetime
|
|||
|
import numpy as np
|
|||
|
import os
|
|||
|
import sys
|
|||
|
from PyQt5.QtGui import QImage, QPixmap
|
|||
|
from PyQt5.QtWidgets import QFileDialog, QApplication, QTableWidgetItem, QHeaderView, QHBoxLayout
|
|||
|
import cv2
|
|||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
|
from PyQt5.QtCore import QThread, pyqtSignal, QObject
|
|||
|
from ROI_Window.ROI_Window import Ui_ROI_Window
|
|||
|
from ScrewDrive import ScrewDrive
|
|||
|
from Camera import Camera
|
|||
|
class ROIWindow(QtWidgets.QMainWindow, Ui_ROI_Window):
|
|||
|
def __init__(self, public_camera=None, public_screwdrive=None, public_Motor=None, myini=None):
|
|||
|
QtWidgets.QMainWindow.__init__(self) # 創建主界面對象
|
|||
|
self.setupUi(self)
|
|||
|
self.screwdrive = public_screwdrive
|
|||
|
self.motor = public_Motor
|
|||
|
self.Myini = myini
|
|||
|
self.label_image_Main.setScaledContents(True)
|
|||
|
self.label_image_Grab.setScaledContents(True)
|
|||
|
self.label_image_ForFoucs.setScaledContents(True)
|
|||
|
self.label_image_ROI.setScaledContents(True)
|
|||
|
|
|||
|
self.comboBox_recipe.addItems([recipe for recipe in self.Myini.recipes])
|
|||
|
self.screwdriver_roi = ScrewDriver_ROI(self.comboBox_recipe.currentText())
|
|||
|
self.iniGuiEvent()
|
|||
|
config = configparser.ConfigParser()
|
|||
|
config.read('ScrewDrive.ini')
|
|||
|
self.label_OutputFilePath.setText(config['ROIInformation']["outputfilepath"])
|
|||
|
self.camera = public_camera
|
|||
|
if self.camera.Camera_isOpen:
|
|||
|
self.comboBox_ExposureTime.addItems([str(exposuretime) for exposuretime in self.camera.ExposureTime_List])
|
|||
|
self.comboBox_ForFoucs.addItems([Class_Name for Class_Name in self.Myini.Class_Name_All])
|
|||
|
self.camera.FreeRun.connect(self.FreeRun)
|
|||
|
else:
|
|||
|
self.pushButton_cameralink.setEnabled(False)
|
|||
|
self.pushButton_cameralink.setText('相機未連線')
|
|||
|
self.pushButton_cameralink.setStyleSheet('color: red')
|
|||
|
self.pushButton_cameraGrab.setEnabled(False)
|
|||
|
self.pushButton_cameraGrab_ROI.setEnabled(False)
|
|||
|
self.pushButton_Preview.setEnabled(False)
|
|||
|
self.horizontalSlider_ExposureTime.setEnabled(False)
|
|||
|
self.comboBox_ExposureTime.setEnabled(False)
|
|||
|
def iniGuiEvent(self):
|
|||
|
self.pushButton_start.clicked.connect(self.ROI_WriteIni)
|
|||
|
self.comboBox_recipe.currentIndexChanged.connect(self.Recipe_Change)
|
|||
|
self.pushButton_changeoutputfilepath.clicked.connect(self.ChangeOutputFilePath)
|
|||
|
self.pushButton_cameralink.clicked.connect(self.CameraLink)
|
|||
|
self.pushButton_cameraGrab.clicked.connect(self.CameraGrab)
|
|||
|
self.pushButton_cameraGrab_ROI.clicked.connect(self.CameraGrab_ROI)
|
|||
|
self.pushButton_cameraGrab_ExpTime.clicked.connect(self.CameraGrab_ROI_ExpTime)
|
|||
|
|
|||
|
self.pushButton_CreateExposureTime.clicked.connect(self.HaveNewExposureTime)
|
|||
|
self.horizontalSlider_ExposureTime.valueChanged.connect(self.WantToCreateExposureTime)
|
|||
|
self.comboBox_ExposureTime.currentIndexChanged.connect(self.ExposureTime_Change)
|
|||
|
self.pushButton_ReadImage_ROI.clicked.connect(self.screwdriver_roi.ReadImage_ROI)
|
|||
|
# self.ROI_X.valueChanged.connect(self.WantToCreateExposureTime)
|
|||
|
# self.ROI_Y.valueChanged.connect(self.WantToCreateExposureTime)
|
|||
|
self.pushButton_adjust_ROI.clicked.connect(self.adjust_ROI)
|
|||
|
self.pushButton_Preview.clicked.connect(self.Preview)
|
|||
|
self.comboBox_ForFoucs.currentIndexChanged.connect(self.ForFocus)
|
|||
|
self.pushButton_Next.clicked.connect(self.Next)
|
|||
|
self.pushButton_Previous.clicked.connect(self.Previous)
|
|||
|
self.pushButton_move.clicked.connect(self.motorGO)
|
|||
|
|
|||
|
|
|||
|
def ROI_for_Trainning(self):
|
|||
|
Pre_ROI_List = list()
|
|||
|
config = configparser.ConfigParser()
|
|||
|
config.read('ScrewDrive.ini')
|
|||
|
for key in config[f'Pre_ROI_KleinTool']:
|
|||
|
Pre_ROI_List.append([int(x) for x in config[f'Pre_ROI_KleinTool'][key].split(',')])
|
|||
|
print(f'Pre_ROI_List = {Pre_ROI_List}')
|
|||
|
Input_FilePath = r'D:\ScrewdriverFile\ScrewdriverImage\KlienTools\Image_KleinTool_0201\opposite'
|
|||
|
img_filenames = os.listdir(Input_FilePath)
|
|||
|
for img_filename in img_filenames:
|
|||
|
print(img_filename)
|
|||
|
InputImage = cv2.flip(cv2.imread(fr'{Input_FilePath}/{img_filename}', cv2.IMREAD_COLOR), 1)
|
|||
|
for k, pre_rio in enumerate(Pre_ROI_List):
|
|||
|
threading.Thread(target=self.screwdriver_roi.ROI, args=(InputImage[pre_rio[1]:pre_rio[1]+pre_rio[3], pre_rio[0]:pre_rio[0]+pre_rio[2]], fr'{img_filename}_{k}',)).start()
|
|||
|
|
|||
|
def closeEvent(self, event):
|
|||
|
print('ROI_Window was Closed')
|
|||
|
self.motorGO()
|
|||
|
self.Myini.read_ini()
|
|||
|
|
|||
|
def Next(self):
|
|||
|
print(f"self.comboBox_ForFoucs.currentIndex() = {self.comboBox_ForFoucs.currentIndex()}")
|
|||
|
if self.comboBox_ForFoucs.currentIndex()+1 == len(self.Myini.Class_Name_All):
|
|||
|
self.comboBox_ForFoucs.setCurrentIndex(0)
|
|||
|
else:
|
|||
|
self.comboBox_ForFoucs.setCurrentIndex(self.comboBox_ForFoucs.currentIndex()+1)
|
|||
|
def Previous(self):
|
|||
|
print(f"self.comboBox_ForFoucs.currentIndex() = {self.comboBox_ForFoucs.currentIndex()}")
|
|||
|
if self.comboBox_ForFoucs.currentIndex()-1 < 0:
|
|||
|
self.comboBox_ForFoucs.setCurrentIndex(38)
|
|||
|
else:
|
|||
|
self.comboBox_ForFoucs.setCurrentIndex(self.comboBox_ForFoucs.currentIndex()-1)
|
|||
|
def motorGO(self):
|
|||
|
self.motor.Move()
|
|||
|
def Preview(self):
|
|||
|
self.imageLable_Show(self.label_image_ROI, self.screwdriver_roi.Preview(self.camera.Image_RealTime))
|
|||
|
|
|||
|
def adjust_ROI(self):
|
|||
|
config = configparser.ConfigParser()
|
|||
|
config.read('ScrewDrive.ini')
|
|||
|
if f'AIClass_{self.screwdriver_roi.Recipe}' in config and f'ROI_{self.screwdriver_roi.Recipe}' in config:
|
|||
|
key = ''
|
|||
|
|
|||
|
if self.screwdriver_roi.Recipe == 'Milwaukee':
|
|||
|
roiSize = 100
|
|||
|
else:
|
|||
|
roiSize = 150
|
|||
|
|
|||
|
if self.checkBox_All_adjust_ROI.isChecked():
|
|||
|
for i, roi_data in enumerate(self.screwdriver_roi.ROI_List):
|
|||
|
X = roi_data.X + self.ROI_X.value() if roi_data.X + self.ROI_X.value() >= 0 else 0
|
|||
|
X = roi_data.X + self.ROI_X.value() if roi_data.X + self.ROI_X.value() < self.camera.Width else self.camera.Width - 1
|
|||
|
Y = roi_data.Y + self.ROI_Y.value() if roi_data.Y + self.ROI_Y.value() >= 0 else 0
|
|||
|
Y = roi_data.Y + self.ROI_Y.value() if roi_data.Y + self.ROI_Y.value() < self.camera.Height else self.camera.Height - 1
|
|||
|
config[f'ROI_{self.screwdriver_roi.Recipe}'][str(i)] = f'{X},{Y},{roiSize},{roiSize}'
|
|||
|
else:
|
|||
|
key = self.Myini.Class_Name_All.index(self.comboBox_ForFoucs.currentText())
|
|||
|
roi_data = self.screwdriver_roi.ROI_List[key]
|
|||
|
X = roi_data.X + self.ROI_X.value() if roi_data.X + self.ROI_X.value() >= 0 else 0
|
|||
|
X = roi_data.X + self.ROI_X.value() if roi_data.X + self.ROI_X.value() < self.camera.Width else self.camera.Width - 1
|
|||
|
Y = roi_data.Y + self.ROI_Y.value() if roi_data.Y + self.ROI_Y.value() >= 0 else 0
|
|||
|
Y = roi_data.Y + self.ROI_Y.value() if roi_data.Y + self.ROI_Y.value() < self.camera.Height else self.camera.Height - 1
|
|||
|
config[f'ROI_{self.screwdriver_roi.Recipe}'][str(key)] = f'{X},{Y},{roiSize},{roiSize}'
|
|||
|
|
|||
|
with open('ScrewDrive.ini', 'w') as conf:
|
|||
|
config.write(conf)
|
|||
|
self.screwdriver_roi.read_ini()
|
|||
|
self.ROI_X.setValue(0)
|
|||
|
self.ROI_Y.setValue(0)
|
|||
|
def ForFocus(self):
|
|||
|
self.ROI_X.setValue(0)
|
|||
|
self.ROI_Y.setValue(0)
|
|||
|
|
|||
|
def ExposureTime_Change(self):
|
|||
|
if self.comboBox_ExposureTime.currentText() != '':
|
|||
|
self.camera.SetExposureTime(int(self.comboBox_ExposureTime.currentText()))
|
|||
|
def WantToCreateExposureTime(self):
|
|||
|
self.camera.SetExposureTime(float(self.horizontalSlider_ExposureTime.value()))
|
|||
|
self.label_ExposureTime.setText(str(self.horizontalSlider_ExposureTime.value()))
|
|||
|
def HaveNewExposureTime(self):
|
|||
|
self.camera.ExposureTime_List.append(self.horizontalSlider_ExposureTime.value())
|
|||
|
def ExposureTime_toint(e):
|
|||
|
return int(e)
|
|||
|
self.camera.ExposureTime_List = sorted(self.camera.ExposureTime_List, key=ExposureTime_toint)
|
|||
|
config = configparser.ConfigParser()
|
|||
|
config.read('ScrewDrive.ini')
|
|||
|
for i, e in enumerate(self.camera.ExposureTime_List):
|
|||
|
config.set('ExposureTime', str(i+1), str(e))
|
|||
|
config.write(open('ScrewDrive.ini', "r+")) # r+模式
|
|||
|
self.comboBox_ExposureTime.clear()
|
|||
|
self.comboBox_ExposureTime.addItems([str(exposuretime) for exposuretime in self.camera.ExposureTime_List])
|
|||
|
|
|||
|
|
|||
|
def CameraLink(self):
|
|||
|
self.camera.start()
|
|||
|
def CameraGrab(self):
|
|||
|
image = self.camera.Image_RealTime
|
|||
|
loc_dt = datetime.today()
|
|||
|
image_name = loc_dt.strftime("%Y_%m_%d_%H_%M_%S")
|
|||
|
self.makexml.Create_XML_ForGrab(image_name)
|
|||
|
image = self.screwdriver_roi.ROI(image, image_name)
|
|||
|
self.imageLable_Show(self.label_image_Grab, image)
|
|||
|
def CameraGrab_ROI_ExpTime(self):
|
|||
|
exposure_times = [int(self.comboBox_ExposureTime.itemText(i)) for i in range(self.comboBox_ExposureTime.count())]
|
|||
|
|
|||
|
for exposure_time in exposure_times:
|
|||
|
self.camera.SetExposureTime(exposure_time)
|
|||
|
time.sleep(1)
|
|||
|
image = self.camera.Image_RealTime
|
|||
|
image = self.screwdriver_roi.ROI(image)
|
|||
|
|
|||
|
self.imageLable_Show(self.label_image_Grab, image)
|
|||
|
def CameraGrab_ROI(self):
|
|||
|
current_datetime = datetime.now()
|
|||
|
formatted_datetime = current_datetime.strftime('%Y_%m_%d_%H_%M_%S')
|
|||
|
output_file_name = f'{self.comboBox_ForFoucs.currentText()}_{formatted_datetime}.png'
|
|||
|
output_file_path = os.path.join(self.screwdriver_roi.OutputFilePath, output_file_name)
|
|||
|
cv2.imwrite(output_file_path, self.roi)
|
|||
|
|
|||
|
def FreeRun(self):
|
|||
|
image = self.camera.Image_RealTime
|
|||
|
self.imageLable_Show(self.label_image_Main, image)
|
|||
|
image = cv2.flip(image, 1)
|
|||
|
roi_data = self.screwdriver_roi.ROI_List[
|
|||
|
self.Myini.Class_Name_All.index(self.comboBox_ForFoucs.currentText())]
|
|||
|
X = roi_data.X + self.ROI_X.value() if roi_data.X + self.ROI_X.value() >= 0 else 0
|
|||
|
X = roi_data.X + self.ROI_X.value() if roi_data.X + self.ROI_X.value() < self.camera.Width else self.camera.Width - 1
|
|||
|
Y = roi_data.Y + self.ROI_Y.value() if roi_data.Y + self.ROI_Y.value() >= 0 else 0
|
|||
|
# print(f"roi_data.Y = {roi_data.Y}")
|
|||
|
Y = roi_data.Y + self.ROI_Y.value() if roi_data.Y + self.ROI_Y.value() < self.camera.Height else self.camera.Height - 1
|
|||
|
self.roi = image[Y:Y + roi_data.H, X:X + roi_data.W]
|
|||
|
self.imageLable_Show(self.label_image_ForFoucs, self.roi)
|
|||
|
|
|||
|
def ChangeOutputFilePath(self):
|
|||
|
dir = QFileDialog.getExistingDirectory(self, "Open Directory",
|
|||
|
'./',
|
|||
|
QFileDialog.ShowDirsOnly
|
|||
|
| QFileDialog.DontResolveSymlinks)
|
|||
|
self.label_OutputFilePath.setText(dir)
|
|||
|
config = configparser.ConfigParser()
|
|||
|
config.read('ScrewDrive.ini')
|
|||
|
config.set('ROIInformation', "outputfilepath", dir)
|
|||
|
config.write(open('ScrewDrive.ini', "r+")) # r+模式
|
|||
|
self.screwdriver_roi.OutputFilePath = dir
|
|||
|
def Recipe_Change(self):
|
|||
|
self.screwdriver_roi.recipe_change(self.comboBox_recipe.currentText())
|
|||
|
self.Myini.recipe_change(self.comboBox_recipe.currentText())
|
|||
|
self.comboBox_ForFoucs.clear()
|
|||
|
self.comboBox_ForFoucs.addItems([Class_Name for Class_Name in self.Myini.Class_Name_All])
|
|||
|
|
|||
|
# image = cv2.imread(f'test/{self.screwdriver_roi.Recipe}.bmp')
|
|||
|
# image = cv2.flip(image, 1)
|
|||
|
# for i, roi_data in enumerate(self.screwdriver_roi.ROI_List):
|
|||
|
# cv2.rectangle(image, (roi_data.X, roi_data.Y), (roi_data.X + roi_data.W, roi_data.Y + roi_data.H),
|
|||
|
# (0, 255, 0), 2)
|
|||
|
# self.imageLable_Show(self.label_image_ROI, image)
|
|||
|
def ROI_WriteIni(self):
|
|||
|
image = self.camera.Image_RealTime
|
|||
|
image = cv2.flip(image, 1)
|
|||
|
|
|||
|
# Milwakee_tuple = ('Milwakee', 39, 410, 150, 225, 260, 110, 40)
|
|||
|
# Milwaukee_tuple = ('Milwaukee', 39, 280, 400, 259, 225, 150, 0, 0) # Y軸鏡像
|
|||
|
Milwaukee_tuple = ('Milwaukee', 39, 302, 416, 259, 225, 110, 0, -1) # Y軸鏡像
|
|||
|
|
|||
|
PlatinumTools_tuple = ('PlatinumTools', 30, 768, 355, 180, 215, 150, 2, -1)
|
|||
|
# ThreeCrossThree_tuple = ('ThreeCrossThree', 9, 1410, 747, 165, 170, 150, 2, -1)
|
|||
|
RingSix_tuple = ('RingSix', 6, 0, 0, 0, 0, 150, 0, 0) # 手動
|
|||
|
KleinTool_tuple = ('KleinTool', 32, 1343, 348, 150, 153, 150, 0, 2)
|
|||
|
PhillipsGroup_tuple = ('PhillipsGroup', 10, 0, 0, 0, 0, 150, 0, 0)
|
|||
|
PozidrivGroup_tuple = ('PozidrivGroup', 10, 0, 0, 0, 0, 150, 0, 0)
|
|||
|
TorxGroup_tuple = ('TorxGroup', 10, 770, 392, 160, 0, 150, 1, 0)
|
|||
|
Buffalo_tuple = ('Buffalo', 10, 1590, 208, 0, 150, 150, 0, -2)
|
|||
|
|
|||
|
screwdriverTypeTuple = Milwaukee_tuple
|
|||
|
firstPoint_X = screwdriverTypeTuple[2]
|
|||
|
firstPoint_Y = screwdriverTypeTuple[3]
|
|||
|
gapX = screwdriverTypeTuple[4]
|
|||
|
gapY = screwdriverTypeTuple[5]
|
|||
|
ROI_Size = screwdriverTypeTuple[6]
|
|||
|
ROI_bais_X = screwdriverTypeTuple[7]
|
|||
|
ROI_bais_Y = screwdriverTypeTuple[8]
|
|||
|
y = 0
|
|||
|
x = 0
|
|||
|
w = 0
|
|||
|
h = 0
|
|||
|
count = 0
|
|||
|
config = configparser.ConfigParser()
|
|||
|
config[self.comboBox_recipe.currentText()] = {}
|
|||
|
|
|||
|
if (screwdriverTypeTuple[0] == 'Milwaukee'):
|
|||
|
for i in range(0, 4):
|
|||
|
for j in range(0, 12 if i < 3 else 3):
|
|||
|
x = firstPoint_X + j * gapX + j * ROI_bais_X
|
|||
|
y = firstPoint_Y + i * gapY + i * ROI_bais_Y
|
|||
|
w = h = ROI_Size
|
|||
|
|
|||
|
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
|
|||
|
config[self.comboBox_recipe.currentText()][str(count)] = f'{x},{y},{w},{h}'
|
|||
|
count += 1
|
|||
|
elif (screwdriverTypeTuple[0] == 'PlatinumTools'):
|
|||
|
for i in range(0, 3):
|
|||
|
for j in range(0, 10):
|
|||
|
x = firstPoint_X + j * gapX + j * ROI_bais_X
|
|||
|
y = firstPoint_Y + i * gapY + i * ROI_bais_Y
|
|||
|
w = h = ROI_Size
|
|||
|
|
|||
|
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
|
|||
|
config[self.comboBox_recipe.currentText()][str(count)] = f'{x},{y},{w},{h}'
|
|||
|
count += 1
|
|||
|
elif (screwdriverTypeTuple[0] == 'ThreeCrossThree'):
|
|||
|
for i in range(0, 3):
|
|||
|
for j in range(0, 3):
|
|||
|
x = firstPoint_X + j * gapX + j * ROI_bais_X
|
|||
|
y = firstPoint_Y + i * gapY + i * ROI_bais_Y
|
|||
|
w = h = ROI_Size
|
|||
|
|
|||
|
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 1)
|
|||
|
config[self.comboBox_recipe.currentText()][str(count)] = f'{x},{y},{w},{h}'
|
|||
|
count += 1
|
|||
|
elif (screwdriverTypeTuple[0] == 'KleinTool'):
|
|||
|
for i in range(0, 8):
|
|||
|
for j in range(0, 4):
|
|||
|
x = firstPoint_X + j * gapX + j * ROI_bais_X
|
|||
|
y = firstPoint_Y + i * gapY + i * ROI_bais_Y
|
|||
|
w = h = ROI_Size
|
|||
|
|
|||
|
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 1)
|
|||
|
config[self.comboBox_recipe.currentText()][str(count)] = f'{x},{y},{w},{h}'
|
|||
|
count += 1
|
|||
|
elif (screwdriverTypeTuple[0] == 'TorxGroup'):
|
|||
|
for i in range(0, 1):
|
|||
|
for j in range(0, 10):
|
|||
|
x = firstPoint_X + j * gapX + j * ROI_bais_X
|
|||
|
y = firstPoint_Y + i * gapY + i * ROI_bais_Y
|
|||
|
w = h = ROI_Size
|
|||
|
|
|||
|
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 1)
|
|||
|
config[self.comboBox_recipe.currentText()][str(count)] = f'{x},{y},{w},{h}'
|
|||
|
count += 1
|
|||
|
elif (screwdriverTypeTuple[0] == 'Buffalo'):
|
|||
|
for i in range(0, 10):
|
|||
|
for j in range(0, 1):
|
|||
|
x = firstPoint_X + j * gapX + j * ROI_bais_X
|
|||
|
y = firstPoint_Y + i * gapY + i * ROI_bais_Y
|
|||
|
w = h = ROI_Size
|
|||
|
|
|||
|
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 1)
|
|||
|
config[self.comboBox_recipe.currentText()][str(count)] = f'{x},{y},{w},{h}'
|
|||
|
count += 1
|
|||
|
|
|||
|
with open('ROI.ini', 'w') as f:
|
|||
|
config.write(f)
|
|||
|
self.imageLable_Show(self.label_image_ROI, image)
|
|||
|
def Seach(self):
|
|||
|
filename, _ = QFileDialog.getOpenFileName(self, 'Open Image', './0712Verify/ROI', 'Image Files(*.png *.jpg *.bmp *.jpeg)')
|
|||
|
self.inputimage_filename = filename
|
|||
|
if filename:
|
|||
|
try:
|
|||
|
self.inputimage = cv2.imread(filename, cv2.IMREAD_COLOR)
|
|||
|
self.inputimage = self.rotate_and_mirror(self.inputimage)
|
|||
|
self.imageLable_Show(self.label_image_Main, self.inputimage)
|
|||
|
except BaseException as e:
|
|||
|
print('openFiles:', e)
|
|||
|
|
|||
|
def imageLable_Show(self, image_label, Show_image):
|
|||
|
Show_image = cv2.cvtColor(Show_image, cv2.COLOR_BGR2RGB) # 圖像存儲使用8-8-8 24位RGB格式
|
|||
|
rows, cols, channels = Show_image.shape # 獲取圖片長寬
|
|||
|
image_label.geometry().width = cols
|
|||
|
image_label.geometry().height = rows
|
|||
|
QImg = QImage(Show_image.data, cols, rows, cols*channels, QImage.Format_RGB888)
|
|||
|
pixmap = QPixmap.fromImage(QImg)
|
|||
|
image_label.setPixmap(pixmap)
|
|||
|
|
|||
|
class ScrewDriver_ROI(QThread):
|
|||
|
def __init__(self, recipe):
|
|||
|
super().__init__()
|
|||
|
self.Recipe = recipe
|
|||
|
self.ROI_List = list()
|
|||
|
|
|||
|
self.OutputFilePath = ''
|
|||
|
self.read_ini()
|
|||
|
|
|||
|
def read_ini(self):
|
|||
|
config = configparser.ConfigParser()
|
|||
|
config.read('ScrewDrive.ini')
|
|||
|
self.OutputFilePath = config['ROIInformation']['outputfilepath']
|
|||
|
print(f'AIClass_{self.Recipe}')
|
|||
|
print(f'ROI_{self.Recipe}')
|
|||
|
if f'AIClass_{self.Recipe}' in config and f'ROI_{self.Recipe}' in config:
|
|||
|
self.ROI_List.clear()
|
|||
|
ROIData_List = list(zip(config[f'AIClass_{self.Recipe}'], config[f'ROI_{self.Recipe}']))
|
|||
|
for key_type, key_XYWH in ROIData_List:
|
|||
|
number_list = config[f'ROI_{self.Recipe}'][key_XYWH].split(',')
|
|||
|
print(f'number_list = {number_list}')
|
|||
|
self.ROI_List.append(
|
|||
|
ROI_Data(int(number_list[0]), int(number_list[1]), int(number_list[2]), int(number_list[3]),
|
|||
|
config[f'AIClass_{self.Recipe}'][key_type]))
|
|||
|
|
|||
|
print(f'len(self.ROI_List) = {len(self.ROI_List)}')
|
|||
|
|
|||
|
def recipe_change(self, recipe):
|
|||
|
self.Recipe = recipe
|
|||
|
self.read_ini()
|
|||
|
print('recipe_change')
|
|||
|
def ReadImage_ROI(self):
|
|||
|
if self.Recipe == 'Milwaukee':
|
|||
|
try:
|
|||
|
inpup_file = r'D:\ScrewdriverFile\ScrewdriverImage\0509_verify\AOI'
|
|||
|
img_filenames = os.listdir(inpup_file)
|
|||
|
for img_filename in img_filenames:
|
|||
|
ImageSRC = cv2.imread(f'{inpup_file}/{img_filename}')
|
|||
|
ImageSRC = cv2.flip(ImageSRC, 1)
|
|||
|
result = self.ROI(ImageSRC, img_filename)
|
|||
|
cv2.imwrite(os.path.join(f'{self.OutputFilePath}/origin', img_filename), result)
|
|||
|
except Exception as e:
|
|||
|
print(f'ReadImage_ROI Error\n{e}')
|
|||
|
elif self.Recipe == 'KleinTool':
|
|||
|
Pre_ROI_List = list()
|
|||
|
config = configparser.ConfigParser()
|
|||
|
config.read('ScrewDrive.ini')
|
|||
|
for key in config[f'Pre_ROI_KleinTool']:
|
|||
|
Pre_ROI_List.append([int(x) for x in config[f'Pre_ROI_KleinTool'][key].split(',')])
|
|||
|
Input_FilePath = r'D:\Screwdriver_Data\Image_KleinTool_0201\AOI'
|
|||
|
img_filenames = os.listdir(Input_FilePath)
|
|||
|
for img_filename in img_filenames:
|
|||
|
print(img_filename)
|
|||
|
InputImage = cv2.flip(cv2.imread(fr'{Input_FilePath}/{img_filename}', cv2.IMREAD_COLOR), 1)
|
|||
|
for k, pre_rio in enumerate(Pre_ROI_List):
|
|||
|
threading.Thread(target=self.ROI, args=(
|
|||
|
InputImage[pre_rio[1]:pre_rio[1] + pre_rio[3], pre_rio[0]:pre_rio[0] + pre_rio[2]],
|
|||
|
fr'{img_filename}_{k}',)).start()
|
|||
|
def ROI(self, ImageSRC, image_name=None):
|
|||
|
if image_name == None:
|
|||
|
loc_dt = datetime.today()
|
|||
|
image_name = loc_dt.strftime("%Y_%m_%d_%H_%M_%S")
|
|||
|
os.makedirs(f'{self.OutputFilePath}/origin', exist_ok=True)
|
|||
|
cv2.imwrite(os.path.join(f'{self.OutputFilePath}/origin', f'{image_name}.png'), cv2.flip(ImageSRC, 1))
|
|||
|
# 進行順時針旋轉90度
|
|||
|
# rotated_img = cv2.rotate(ImageSRC, cv2.ROTATE_90_CLOCKWISE)
|
|||
|
# 沿著Y軸鏡射
|
|||
|
mirrored_img = cv2.flip(ImageSRC, 1)
|
|||
|
ImageSRC_Gray = cv2.cvtColor(mirrored_img, cv2.COLOR_BGR2GRAY)
|
|||
|
roi_image = copy.deepcopy(ImageSRC_Gray)
|
|||
|
for i, rd in enumerate(self.ROI_List):
|
|||
|
roi_data = copy.deepcopy(rd)
|
|||
|
roi_data.X = roi_data.X#-15
|
|||
|
roi_data.Y = roi_data.Y#-15
|
|||
|
roi_data.W = roi_data.W#+30
|
|||
|
roi_data.H = roi_data.H#+30
|
|||
|
cv2.rectangle(mirrored_img, (roi_data.X, roi_data.Y), (roi_data.X + roi_data.W, roi_data.Y + roi_data.H), (0, 255, 0), 2)
|
|||
|
roi = roi_image[roi_data.Y:roi_data.Y+roi_data.H, roi_data.X:roi_data.X+roi_data.W]
|
|||
|
filename = f'{image_name}_roi_{i}.png'
|
|||
|
os.makedirs(f'{self.OutputFilePath}/ROI/{roi_data.Type}', exist_ok=True)
|
|||
|
cv2.imwrite(os.path.join(f'{self.OutputFilePath}/ROI/{roi_data.Type}', filename), roi)
|
|||
|
# cv2.imwrite(os.path.join(f'{self.OutputFilePath}/origin', f'{image_name}_mirrored_img.png'), mirrored_img)
|
|||
|
return mirrored_img
|
|||
|
def CameraGrab_ROI_ExpTime(self, ImageSRC, image_name=None):
|
|||
|
image = self.camera.Image_RealTime
|
|||
|
image = self.screwdriver_roi.ROI(image)
|
|||
|
self.imageLable_Show(self.label_image_Grab, image)
|
|||
|
def Preview(self, ImageSRC):
|
|||
|
mirrored_img = cv2.flip(ImageSRC, 1)
|
|||
|
for i, roi_data in enumerate(self.ROI_List):
|
|||
|
cv2.rectangle(mirrored_img, (roi_data.X, roi_data.Y), (roi_data.X + roi_data.W, roi_data.Y + roi_data.H), (255, 255, 0), 2)
|
|||
|
return mirrored_img
|
|||
|
|
|||
|
class ROI_Data:
|
|||
|
def __init__(self, x=0, y=0, w=0, h=0, type=''):
|
|||
|
self.X = x
|
|||
|
self.Y = y
|
|||
|
self.W = w
|
|||
|
self.H = h
|
|||
|
self.Type = type
|
|||
|
|
|||
|
if __name__ == '__main__':
|
|||
|
app = QApplication(sys.argv) # 固定的,PyQt5程式都需要QApplication對象。sys.argv是命令列參數清單,確保程式可以按兩下運行
|
|||
|
MyWindow = ROIWindow() # 初始化
|
|||
|
MyWindow.show() # 將視窗控制項顯示在螢幕上
|
|||
|
sys.exit(app.exec_()) # 程式運行,sys.exit方法確保程式完整退出
|