From 98cf134cca637d1c9c4fc2d079b8fb10d2f3aa5e Mon Sep 17 00:00:00 2001 From: tangchao0503 <735056338@qq.com> Date: Tue, 6 Sep 2022 22:54:14 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E6=AC=A1=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=201=E3=80=81hpi=E7=9A=84=E5=8F=AF=E7=94=A8=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=9B=202=E3=80=81=E4=BF=AE=E5=A4=8D=E4=BA=86=E5=A4=9A?= =?UTF-8?q?=E6=AC=A1=E7=82=B9=E5=87=BB=E6=9B=9D=E5=85=89=E5=90=8E=EF=BC=8C?= =?UTF-8?q?=E7=A6=8F=E4=BA=AE=E5=BA=A6=E6=95=B0=E6=8D=AE=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9B=203=E3=80=81=E5=AE=9A?= =?UTF-8?q?=E6=A0=87=E6=96=B9=E5=BC=8F=E4=B8=BA=E5=A4=A7=E7=9A=84=E8=93=9D?= =?UTF-8?q?=E8=8F=B2=E7=A7=AF=E5=88=86=E7=90=83=E7=9A=84=E6=A0=87=E5=87=86?= =?UTF-8?q?=E8=83=BD=E9=87=8F=E6=9B=B2=E7=BA=BF=EF=BC=8C=E8=80=8C=E4=B8=8D?= =?UTF-8?q?=E6=98=AF=E5=9F=BA=E4=BA=8Easd=E7=9A=84=E8=83=BD=E9=87=8F?= =?UTF-8?q?=E6=9B=B2=E7=BA=BF=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 258 ++ 0.1remove dark noise.py | 117 + 0.2stretch.py | 141 + corning_config.ini | 15 + delete.py | 23 + library/__init__.py | 0 library/config.py | 514 ++++ library/dir_manager.py | 29 + library/functions.py | 144 + library/image_reader_writer.py | 40 + library/log.py | 50 + library/log/corning_config.ini | 25 + library/matplotlib_display_image_spectral.py | 161 ++ library/message_box.py | 53 + library/message_box_ui.py | 90 + library/message_box_ui.ui | 106 + library/multithread.py | 81 + pyqt_multithread.py | 143 + record_system_v11/1record_system_v1.1.py | 230 ++ record_system_v12/1record_system_v1.2.py | 142 + record_system_v13/1record_system_v1.3.py | 158 ++ record_system_v21/2record_system_v2.1.py | 569 ++++ record_system_v21/arcus_control_ui.py | 48 + record_system_v21/arcus_control_ui.ui | 81 + record_system_v21/enter_window.py | 47 + record_system_v21/enter_window.ui | 73 + record_system_v21/image_Window.py | 231 ++ record_system_v21/image_Window.ui | 377 +++ record_system_v21/spectral_Window.py | 94 + record_system_v21/spectral_Window.ui | 180 ++ record_system_v22/2record_system_v2.2.py | 1203 +++++++++ record_system_v22/arcus_control_ui.py | 48 + record_system_v22/arcus_control_ui.ui | 81 + record_system_v22/enter_window.py | 47 + record_system_v22/enter_window.ui | 73 + record_system_v22/image_Window.py | 231 ++ record_system_v22/image_Window.ui | 377 +++ record_system_v22/spectral_Window.py | 94 + record_system_v22/spectral_Window.ui | 180 ++ record_system_v23/2record_system_v2.3.py | 1438 ++++++++++ record_system_v23/arcus_control_ui.py | 48 + record_system_v23/arcus_control_ui.ui | 81 + record_system_v23/enter_window.py | 47 + record_system_v23/enter_window.ui | 73 + record_system_v23/image_Window.py | 231 ++ record_system_v23/image_Window.ui | 377 +++ record_system_v23/spectral_Window.py | 94 + record_system_v23/spectral_Window.ui | 180 ++ record_system_v24/2record_system_v24.py | 1828 +++++++++++++ record_system_v24/ArcusDevice.py | 75 + record_system_v24/corning_config.ini | 23 + record_system_v24/delete.py | 42 + record_system_v24/ui/__init__.py | 0 record_system_v24/ui/arcus_control_ui.py | 48 + record_system_v24/ui/arcus_control_ui.ui | 81 + record_system_v24/ui/enter_window.py | 47 + record_system_v24/ui/enter_window.ui | 73 + record_system_v24/ui/image_Window.py | 246 ++ record_system_v24/ui/image_Window.ui | 405 +++ record_system_v24/ui/spectral_Window.py | 104 + record_system_v24/ui/spectral_Window.ui | 212 ++ record_system_v25/2record_system_v25.py | 1801 +++++++++++++ record_system_v25/delete.py | 3 + record_system_v25/log/corning_config.ini | 23 + record_system_v25/ui/__init__.py | 0 record_system_v25/ui/arcus_control_ui.py | 48 + record_system_v25/ui/arcus_control_ui.ui | 81 + record_system_v25/ui/enter_window.py | 47 + record_system_v25/ui/enter_window.ui | 73 + record_system_v25/ui/image_Window.py | 268 ++ record_system_v25/ui/image_Window.ui | 468 ++++ record_system_v25/ui/image_Window_phone.ui | 1083 ++++++++ record_system_v25/ui/spectral_Window.py | 104 + record_system_v25/ui/spectral_Window.ui | 215 ++ record_system_v25/ui/spectral_Window_phone.ui | 377 +++ record_system_v26/2record_system_v26.py | 2215 ++++++++++++++++ record_system_v26/log/corning_config.ini | 27 + record_system_v26/ui/__init__.py | 0 record_system_v26/ui/enter_window.py | 150 ++ record_system_v26/ui/enter_window.ui | 178 ++ record_system_v26/ui/image_Window_phone.py | 830 ++++++ record_system_v26/ui/image_Window_phone.ui | 1323 ++++++++++ record_system_v26/ui/spectral_Window_phone.py | 629 +++++ record_system_v26/ui/spectral_Window_phone.ui | 1057 ++++++++ record_system_v27/2record_system_v27.py | 2304 ++++++++++++++++ record_system_v27/log/corning_config.ini | 27 + record_system_v27/ui/__init__.py | 0 record_system_v27/ui/enter_window.py | 150 ++ record_system_v27/ui/enter_window.ui | 178 ++ .../ui/image_Window_phone - 副本 (2).ui | 1358 ++++++++++ record_system_v27/ui/image_Window_phone.py | 868 +++++++ record_system_v27/ui/image_Window_phone.ui | 1395 ++++++++++ record_system_v27/ui/spectral_Window_phone.py | 629 +++++ record_system_v27/ui/spectral_Window_phone.ui | 1057 ++++++++ record_system_v28/2record_system_v28.py | 2313 +++++++++++++++++ record_system_v28/delete.py | 63 + .../log/corning_config - 20220627.ini | 48 + record_system_v28/log/corning_config.ini | 48 + record_system_v28/ui/__init__.py | 0 record_system_v28/ui/enter_window.py | 150 ++ record_system_v28/ui/enter_window.ui | 178 ++ .../ui/image_Window_phone - 副本 (2).ui | 1358 ++++++++++ record_system_v28/ui/image_Window_phone.py | 868 +++++++ record_system_v28/ui/image_Window_phone.ui | 1395 ++++++++++ record_system_v28/ui/spectral_Window_phone.py | 635 +++++ record_system_v28/ui/spectral_Window_phone.ui | 1071 ++++++++ 106 files changed, 39400 insertions(+) create mode 100644 .gitignore create mode 100644 0.1remove dark noise.py create mode 100644 0.2stretch.py create mode 100644 corning_config.ini create mode 100644 delete.py create mode 100644 library/__init__.py create mode 100644 library/config.py create mode 100644 library/dir_manager.py create mode 100644 library/functions.py create mode 100644 library/image_reader_writer.py create mode 100644 library/log.py create mode 100644 library/log/corning_config.ini create mode 100644 library/matplotlib_display_image_spectral.py create mode 100644 library/message_box.py create mode 100644 library/message_box_ui.py create mode 100644 library/message_box_ui.ui create mode 100644 library/multithread.py create mode 100644 pyqt_multithread.py create mode 100644 record_system_v11/1record_system_v1.1.py create mode 100644 record_system_v12/1record_system_v1.2.py create mode 100644 record_system_v13/1record_system_v1.3.py create mode 100644 record_system_v21/2record_system_v2.1.py create mode 100644 record_system_v21/arcus_control_ui.py create mode 100644 record_system_v21/arcus_control_ui.ui create mode 100644 record_system_v21/enter_window.py create mode 100644 record_system_v21/enter_window.ui create mode 100644 record_system_v21/image_Window.py create mode 100644 record_system_v21/image_Window.ui create mode 100644 record_system_v21/spectral_Window.py create mode 100644 record_system_v21/spectral_Window.ui create mode 100644 record_system_v22/2record_system_v2.2.py create mode 100644 record_system_v22/arcus_control_ui.py create mode 100644 record_system_v22/arcus_control_ui.ui create mode 100644 record_system_v22/enter_window.py create mode 100644 record_system_v22/enter_window.ui create mode 100644 record_system_v22/image_Window.py create mode 100644 record_system_v22/image_Window.ui create mode 100644 record_system_v22/spectral_Window.py create mode 100644 record_system_v22/spectral_Window.ui create mode 100644 record_system_v23/2record_system_v2.3.py create mode 100644 record_system_v23/arcus_control_ui.py create mode 100644 record_system_v23/arcus_control_ui.ui create mode 100644 record_system_v23/enter_window.py create mode 100644 record_system_v23/enter_window.ui create mode 100644 record_system_v23/image_Window.py create mode 100644 record_system_v23/image_Window.ui create mode 100644 record_system_v23/spectral_Window.py create mode 100644 record_system_v23/spectral_Window.ui create mode 100644 record_system_v24/2record_system_v24.py create mode 100644 record_system_v24/ArcusDevice.py create mode 100644 record_system_v24/corning_config.ini create mode 100644 record_system_v24/delete.py create mode 100644 record_system_v24/ui/__init__.py create mode 100644 record_system_v24/ui/arcus_control_ui.py create mode 100644 record_system_v24/ui/arcus_control_ui.ui create mode 100644 record_system_v24/ui/enter_window.py create mode 100644 record_system_v24/ui/enter_window.ui create mode 100644 record_system_v24/ui/image_Window.py create mode 100644 record_system_v24/ui/image_Window.ui create mode 100644 record_system_v24/ui/spectral_Window.py create mode 100644 record_system_v24/ui/spectral_Window.ui create mode 100644 record_system_v25/2record_system_v25.py create mode 100644 record_system_v25/delete.py create mode 100644 record_system_v25/log/corning_config.ini create mode 100644 record_system_v25/ui/__init__.py create mode 100644 record_system_v25/ui/arcus_control_ui.py create mode 100644 record_system_v25/ui/arcus_control_ui.ui create mode 100644 record_system_v25/ui/enter_window.py create mode 100644 record_system_v25/ui/enter_window.ui create mode 100644 record_system_v25/ui/image_Window.py create mode 100644 record_system_v25/ui/image_Window.ui create mode 100644 record_system_v25/ui/image_Window_phone.ui create mode 100644 record_system_v25/ui/spectral_Window.py create mode 100644 record_system_v25/ui/spectral_Window.ui create mode 100644 record_system_v25/ui/spectral_Window_phone.ui create mode 100644 record_system_v26/2record_system_v26.py create mode 100644 record_system_v26/log/corning_config.ini create mode 100644 record_system_v26/ui/__init__.py create mode 100644 record_system_v26/ui/enter_window.py create mode 100644 record_system_v26/ui/enter_window.ui create mode 100644 record_system_v26/ui/image_Window_phone.py create mode 100644 record_system_v26/ui/image_Window_phone.ui create mode 100644 record_system_v26/ui/spectral_Window_phone.py create mode 100644 record_system_v26/ui/spectral_Window_phone.ui create mode 100644 record_system_v27/2record_system_v27.py create mode 100644 record_system_v27/log/corning_config.ini create mode 100644 record_system_v27/ui/__init__.py create mode 100644 record_system_v27/ui/enter_window.py create mode 100644 record_system_v27/ui/enter_window.ui create mode 100644 record_system_v27/ui/image_Window_phone - 副本 (2).ui create mode 100644 record_system_v27/ui/image_Window_phone.py create mode 100644 record_system_v27/ui/image_Window_phone.ui create mode 100644 record_system_v27/ui/spectral_Window_phone.py create mode 100644 record_system_v27/ui/spectral_Window_phone.ui create mode 100644 record_system_v28/2record_system_v28.py create mode 100644 record_system_v28/delete.py create mode 100644 record_system_v28/log/corning_config - 20220627.ini create mode 100644 record_system_v28/log/corning_config.ini create mode 100644 record_system_v28/ui/__init__.py create mode 100644 record_system_v28/ui/enter_window.py create mode 100644 record_system_v28/ui/enter_window.ui create mode 100644 record_system_v28/ui/image_Window_phone - 副本 (2).ui create mode 100644 record_system_v28/ui/image_Window_phone.py create mode 100644 record_system_v28/ui/image_Window_phone.ui create mode 100644 record_system_v28/ui/spectral_Window_phone.py create mode 100644 record_system_v28/ui/spectral_Window_phone.ui diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1245444 --- /dev/null +++ b/.gitignore @@ -0,0 +1,258 @@ +# tc +/0/* +/problem880_960/* +/installer/* +/test/* +*.hdr +*.enp +*.log # 自己写的log文件 +/.idea +20220627 +20220628 +20220628_focus +20220629_focus +corning410_test +corning410_test.hdr +data + + + + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser diff --git a/0.1remove dark noise.py b/0.1remove dark noise.py new file mode 100644 index 0000000..600cfb4 --- /dev/null +++ b/0.1remove dark noise.py @@ -0,0 +1,117 @@ +''' +1、读取影像 +2、bin +3、去除暗电流 + 转反射率 +4、保存光谱 +''' +import numpy as np +import matplotlib.pyplot as plt +import sys +from osgeo import gdal #读写影像数据 + +class GRID: + + #读图像文件 + @classmethod + def read_img(cls, filename): + try: + dataset = gdal.Open(filename) # 打开文件 + im_width = dataset.RasterXSize # 栅格矩阵的列数 + im_height = dataset.RasterYSize # 栅格矩阵的行数 + num_bands = dataset.RasterCount # 栅格矩阵的波段数 + im_geotrans = dataset.GetGeoTransform() # 仿射矩阵 + im_proj = dataset.GetProjection() # 地图投影信息 + im_data = dataset.ReadAsArray(0, 0, im_width, im_height) # 将数据写成数组,对应栅格矩阵 + del dataset + return im_proj, im_geotrans, im_data + except: + sys.exit() + + #写文件,以写成tif为例 + @classmethod + def write_img(cls, dst_filename, data): + format = "ENVI" + driver = gdal.GetDriverByName(format) + RasterXSize = data.shape[2] # 遥感影像的sample(列数) + RasterYSize = data.shape[1] # 遥感影像的line(行数) + band = data.shape[0] + dst_ds = driver.Create(dst_filename, RasterXSize, RasterYSize, + band, + gdal.GDT_Float32) # driver.Create()函数中RasterXSize代表影像的sample(列数),RasterYSize代表影像的line(行数) + for i in range(band): + dst_ds.GetRasterBand(i + 1).WriteArray(data[i, :, :]) # gdal的band从1开始,所以dst_ds.GetRasterBand(i+1) + dst_ds = None + + # bin + @classmethod + def bin(cls, img, nBin): + if nBin == 1: + return img + image_bin = np.empty((int(img.shape[0] / nBin), img.shape[1], img.shape[2])) + k = np.arange(img.shape[0])[0::nBin] + for i in range(image_bin.shape[0]): + for j in range(nBin): + image_bin[i] += img[k[i] + j] + return image_bin + +# 文件名 +image = r'D:\py_program\corning410\test_spectral\lib_spectral2_20帧\delete\leaf' +dark_image = r'D:\py_program\corning410\test_spectral\lib_spectral2_20帧\delete\dark' +baiban_image = r'D:\py_program\corning410\test_spectral\lib_spectral2_20帧\delete\baiban' + +# 读取影像 +print('读取影像') +im_proj, im_geotrans, im_data = GRID.read_img(image) +d1, d2, dark_noise = GRID.read_img(dark_image) +b1, b2, baiban = GRID.read_img(baiban_image) + + + +n_bin = 1 +im_data = GRID.bin(im_data, n_bin) +dark_noise = GRID.bin(dark_noise, n_bin) +baiban = GRID.bin(baiban, n_bin) + + +# (1)去除暗电流;(2)转反射率 +dark_noise_mean = dark_noise.mean(axis=1) +baiban_mean = baiban.mean(axis=1) +im_data = im_data.astype(np.float) +for i in range(im_data.shape[1]): + im_data[:, i, :] = (im_data[:, i, :] - dark_noise_mean).astype(np.float) / baiban_mean.astype(np.float) + + +print('将影像写入到文件') +GRID.write_img(image + '_reflectivity', im_data) + + +# 计算波长 +def calculate_wavelength(x): + wavelength = x * 1.999564 - 279.893 + return wavelength +wavelength_tmp = np.empty(300) +for i in range(340, 640): + wavelength_tmp[i - 340] = calculate_wavelength(i) +wavelength = np.empty(im_data.shape[0]) +k = np.arange(300)[0::n_bin] +for i in range(wavelength.shape[0]): + tmp = 0 + for j in range(n_bin): + tmp += wavelength_tmp[k[i] + j] + wavelength[i] = tmp / n_bin + + + + +# 保存光谱为txt文件 +spectralNumber = 1 +spectral_container = np.empty((im_data.shape[0], spectralNumber)).astype(np.float) +spectral_container = np.insert(spectral_container, 0, wavelength, axis=1) + + +spectral = im_data.mean(1).mean(1) +spectral_container = np.insert(spectral_container, 1, spectral, axis=1) +np.savetxt(r'D:\py_program\corning410\test_spectral\lib_spectral2_20帧\delete\spectral.txt', spectral_container[:, [0, 1]], fmt='%f') + +plt.plot(wavelength, spectral) +plt.show() diff --git a/0.2stretch.py b/0.2stretch.py new file mode 100644 index 0000000..d9e49cc --- /dev/null +++ b/0.2stretch.py @@ -0,0 +1,141 @@ +''' +1、读取影像 +2、bin +3、去除暗电流 + 转反射率 +4、保存光谱 +''' +import numpy as np +import matplotlib.pyplot as plt +import sys +from osgeo import gdal #读写影像数据 +from PIL import Image +import cv2 + + +class GRID: + + #读图像文件 + @classmethod + def read_img(cls, filename): + try: + dataset = gdal.Open(filename) # 打开文件 + im_width = dataset.RasterXSize # 栅格矩阵的列数 + im_height = dataset.RasterYSize # 栅格矩阵的行数 + num_bands = dataset.RasterCount # 栅格矩阵的波段数 + im_geotrans = dataset.GetGeoTransform() # 仿射矩阵 + im_proj = dataset.GetProjection() # 地图投影信息 + im_data = dataset.ReadAsArray(0, 0, im_width, im_height) # 将数据写成数组,对应栅格矩阵 + del dataset + return im_proj, im_geotrans, im_data + except: + sys.exit() + + #写文件,以写成tif为例 + @classmethod + def write_img(cls, dst_filename, data): + format = "ENVI" + driver = gdal.GetDriverByName(format) + RasterXSize = data.shape[2] # 遥感影像的sample(列数) + RasterYSize = data.shape[1] # 遥感影像的line(行数) + band = data.shape[0] + dst_ds = driver.Create(dst_filename, RasterXSize, RasterYSize, + band, + gdal.GDT_Float32) # driver.Create()函数中RasterXSize代表影像的sample(列数),RasterYSize代表影像的line(行数) + for i in range(band): + dst_ds.GetRasterBand(i + 1).WriteArray(data[i, :, :]) # gdal的band从1开始,所以dst_ds.GetRasterBand(i+1) + dst_ds = None + + # bin + @classmethod + def bin(cls, img, nBin): + if nBin == 1: + return img + image_bin = np.empty((int(img.shape[0] / nBin), img.shape[1], img.shape[2])) + k = np.arange(img.shape[0])[0::nBin] + for i in range(image_bin.shape[0]): + for j in range(nBin): + image_bin[i] += img[k[i] + j] + return image_bin + + # 计算波长 + @classmethod + def calculate_wavelength(cls, x): + wavelength = x * 1.999564 - 279.893 + return wavelength + +wavelength = np.empty(639 - 339) +for i in range(339, 639): + wavelength[i - 339] = GRID.calculate_wavelength(i) + + +# 等效于ENVI拉伸:No stretch +def stretch(img, minimum=0, maximum=255): + if len(img.shape) == 2: + img_new = (img - minimum) / (maximum - minimum) + img_new[img_new < 0] = 0 + img_new[img_new > 1] = 1 + return img_new + else: + img_new = np.empty(img.shape) + for i in range(img.shape[2]): + img_new[:, :, i] = (img[:, :, i] - minimum) / (maximum - minimum) + img_new[:, :, i][img_new[:, :, i] < 0] = 0 + img_new[:, :, i][img_new[:, :, i] > 1] = 1 + return img_new + + +# 当lowPercentile=0, highPercentile=100时,等效于Min-Max Stretching +# lowPercentile=2, highPercentile=98时,等效于ENVI拉伸:Linear 2% +# https://blog.csdn.net/LEILEI18A/article/details/80180483 +def percentile_stretching(img, lowPercentile=0, highPercentile=100, minout=0, maxout=255): + if len(img.shape) == 2: + low = np.percentile(img, lowPercentile) + up = np.percentile(img, highPercentile) + + img_new = ((img - low) / (up - low)) * (maxout - minout) + minout + img_new[img_new < minout] = minout + img_new[img_new > maxout] = maxout + img_out = np.uint8(img_new) + return img_out + else: # 对于彩色照片,需要先单独对每个波段拉伸 + img_new = np.empty(img.shape) + for i in range(img.shape[2]): + low = np.percentile(img[:, :, i], lowPercentile) + up = np.percentile(img[:, :, i], highPercentile) + + img_new[:, :, i] = minout + ((img[:, :, i] - low) / (up - low)) * (maxout - minout) + img_new[:, :, i][img_new[:, :, i] < minout] = minout + img_new[:, :, i][img_new[:, :, i] > maxout] = maxout + img_out = np.uint8(img_new) + return img_out + + +# 画出图像直方图 +# https://blog.csdn.net/fly_wt/article/details/83904207 +def image_hist(image): # 画三通道图像的直方图 + color = ("blue", "green", "red") # 画笔颜色的值可以为大写或小写或只写首字母或大小写混合 + for i, color in enumerate(color): + hist = cv2.calcHist([image], [i], None, [256], [0, 256]) + plt.plot(hist, color=color) + plt.xlim([0, 256]) + plt.show() + + +print("读取影像") +#image = r'D:\py_program\corning410\2%拉伸显示问题 + 漏帧\x270\dn值\corning410_test10' +image = r'D:\corning410_test10' +im_proj, im_geotrans, im_data = GRID.read_img(image) + + +print("挑取波段用于真彩色显示") +rgb_raw = np.dstack((im_data[121], im_data[76], im_data[36])) +rgb = rgb_raw.astype(np.uint8) + + +x1 = stretch(rgb_raw) #等效于ENVI拉伸:No stretch +x2 = percentile_stretching(rgb_raw) # Min-Max Stretching +x3 = percentile_stretching(rgb_raw, 2, 98) # 2% Stretching + +print("画出影像") +plt.imshow(x3) +plt.show() diff --git a/corning_config.ini b/corning_config.ini new file mode 100644 index 0000000..399ca2f --- /dev/null +++ b/corning_config.ini @@ -0,0 +1,15 @@ +[basic] +binning = 1 +default_dir = D:\py_program\corning410 +default_file_name = test + +[effective_window] +start_column_binning_1 = 12 +end_column_binning_1 = 1376 +start_row_binning_1 = 1 +end_row_binning_1 = 300 +start_column_binning_2 = 13 +end_column_binning_2 = 695 +start_row_binning_2 = 1 +end_row_binning_2 = 150 + diff --git a/delete.py b/delete.py new file mode 100644 index 0000000..1b3968e --- /dev/null +++ b/delete.py @@ -0,0 +1,23 @@ +def add(x, y): + return x+y + +class A(): + x = add(3,4) + + + def p(self): + print(self.x) + + +class B(A): + pass + + + + +class Dog: + tricks = [] # mistaken use of a class variable + def __init__(self, name): + self.name = name + def add_trick(self, trick): + self.tricks.append(trick) diff --git a/library/__init__.py b/library/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/library/config.py b/library/config.py new file mode 100644 index 0000000..7251636 --- /dev/null +++ b/library/config.py @@ -0,0 +1,514 @@ +# 标准库 +import traceback, os + +# 三方库 +import configparser +from PyQt5.QtCore import QObject, pyqtSignal + +# 自己写的库 +from library.dir_manager import DirManager + + +# class ConfigFile(): +# def __init__(self): +# self.base_dir = get_path() +# +# self.log_dir = self.base_dir + '//log' +# self.create_directory(self.log_dir) +# +# self.corning_config_file = self.log_dir + '//corning_config.ini' +# +# self.read_config_file() +# +# self.signals = WorkerSignals() +# self.signals.image_signal.connect(self.image_record_param_changed) +# self.signals.spectral_signal.connect(self.spectral_record_param_changed) +# +# +# # 查看是否存在保存光谱和影像文件的目录,如果没有就创建 +# def create_directory(self, directory): +# if not os.path.exists(directory): +# print('创建文件夹:', directory) +# os.makedirs(directory) +# +# # 读取配置文件,如果没有就创建 +# def read_config_file(self): +# if os.path.exists(self.corning_config_file): +# ''' +# 如果存在配置文件,就从配置文件中读取软件配置信息 +# ''' +# print('配置文件存在!') +# +# config = configparser.ConfigParser() +# config.read(self.corning_config_file) +# +# self.image_dir = config.get('image_record_param', 'image_dir') +# self.create_directory(self.image_dir) +# self.default_image_name = config.get('image_record_param', 'default_image_name') +# self.framerate = int(config.get('image_record_param', 'framerate')) +# self.exposure_time = int(config.get('image_record_param', 'exposure_time')) +# self.gain = int(float(config.get('image_record_param', 'gain'))) +# self.frame_number = int(config.get('image_record_param', 'frame_number')) +# +# self.spectral_dir = config.get('spectral_record_param', 'spectral_dir') +# self.create_directory(self.spectral_dir) +# self.default_spectral_name = config.get('spectral_record_param', 'default_spectral_name') +# +# self.binning = int(config.get('bin', 'binning')) +# if self.binning == 1: +# self.start_column = int(config.get('bin', 'start_column_binning_1')) +# self.end_column = int(config.get('bin', 'end_column_binning_1')) +# self.start_row = int(config.get('bin', 'start_row_binning_1')) +# self.end_row = int(config.get('bin', 'end_row_binning_1')) +# elif self.binning == 2: +# self.start_column = int(config.get('bin', 'start_column_binning_2')) +# self.end_column = int(config.get('bin', 'end_column_binning_2')) +# self.start_row = int(config.get('bin', 'start_row_binning_2')) +# self.end_row = int(config.get('bin', 'end_row_binning_2')) +# +# # print(self.default_dir, self.binning, self.start_column, self.end_column, self.start_row, self.end_row) +# +# else: +# ''' +# 1、如果不存在配置文件,就建立配置文件; +# 2、并且手动创建配置变量 +# ''' +# config = configparser.ConfigParser() +# +# # config.add_section('effective_window') +# # startRow = 339 +# # endRow = 639 +# # startColumn = 285 +# # endColumn = 1649 +# +# +# config.add_section('bin') +# config.set('bin', 'binning', '1') +# +# config.set('bin', 'start_column_binning_1', '12') +# config.set('bin', 'end_column_binning_1', '1376') +# config.set('bin', 'start_row_binning_1', '1') +# config.set('bin', 'end_row_binning_1', '301') +# +# config.set('bin', 'start_column_binning_2', '13') +# config.set('bin', 'end_column_binning_2', '695') +# config.set('bin', 'start_row_binning_2', '1') +# config.set('bin', 'end_row_binning_2', '150') +# +# config.add_section('image_record_param') +# config.set('image_record_param', 'image_dir', self.base_dir + '/image') +# config.set('image_record_param', 'default_image_name', 'testimage') +# config.set('image_record_param', 'framerate', '20') +# config.set('image_record_param', 'exposure_time', '500') +# config.set('image_record_param', 'gain', '0') +# config.set('image_record_param', 'frame_number', '20') +# +# config.add_section('spectral_record_param') +# config.set('spectral_record_param', 'spectral_dir', self.base_dir + '/spectral') +# config.set('spectral_record_param', 'default_spectral_name', 'testspectral') +# # config.set('spectral_record_param', 'start_column_binning_1', '12') +# +# with open(self.corning_config_file, mode='w') as f: +# config.write(f) +# print('创建配置文件成功!') +# +# # 如果没有配置文件,就手动创建配置变量 +# self.image_dir = self.base_dir + '/image' +# self.create_directory(self.image_dir) +# self.default_image_name = 'testimage' +# self.framerate = 20 +# self.exposure_time = 500 +# self.gain = 0 +# self.frame_number = 20 +# +# self.spectral_dir = self.base_dir + '/spectral' +# self.create_directory(self.spectral_dir) +# self.default_spectral_name = 'testspectral' +# +# self.binning = int(config.get('bin', 'binning')) +# self.start_column = int(config.get('bin', 'start_column_binning_1')) +# self.end_column = int(config.get('bin', 'end_column_binning_1')) +# self.start_row = int(config.get('bin', 'start_row_binning_1')) +# self.end_row = int(config.get('bin', 'end_row_binning_1')) +# +# # self.start_column = 12 +# # self.end_column = 1376 +# # self.start_row = 1 +# # self.end_row = 300 +# +# def image_record_param_changed(self, dictionary): +# ''' +# :param dictionary: {'image_dir':值, 'image_record_param': 值} +# :return: +# ''' +# try: +# # print('接收的参数个数:', len(dictionary.keys())) +# +# config = configparser.ConfigParser() +# config.read(self.corning_config_file) +# +# for key in dictionary.keys(): +# if key == 'image_dir': +# self.image_dir = dictionary[key] +# config.set('image_record_param', key, dictionary[key]) +# if key == 'default_image_name': +# self.default_image_name = dictionary[key] +# config.set('image_record_param', key, dictionary[key]) +# if key == 'framerate': +# self.framerate = dictionary[key] +# config.set('image_record_param', key, str(dictionary[key])) +# if key == 'exposure_time': +# self.exposure_time = dictionary[key] +# config.set('image_record_param', key, str(dictionary[key])) +# if key == 'gain': +# self.gain = dictionary[key] +# config.set('image_record_param', key, str(dictionary[key])) +# if key == 'frame_number': +# self.frame_number = dictionary[key] +# config.set('image_record_param', key, str(dictionary[key])) +# except: +# traceback.print_exc() +# +# with open(self.corning_config_file, 'w') as f: +# config.write(f) +# +# def spectral_record_param_changed(self, dictionary): +# ''' +# :param dictionary: {'image_dir':值, 'image_record_param': 值} +# :return: +# ''' +# print(len(dictionary.keys())) +# +# config = configparser.ConfigParser() +# config.read(self.corning_config_file) +# +# try: +# for key in dictionary.keys(): +# if key == 'spectral_dir': +# self.spectral_dir = dictionary[key] +# config.set('spectral_record_param', key, dictionary[key]) +# if key == 'default_spectral_name': +# self.default_spectral_name = dictionary[key] +# config.set('spectral_record_param', key, dictionary[key]) +# except: +# traceback.print_exc() +# +# with open(self.corning_config_file, 'w') as f: +# config.write(f) + + +class ConfigFile(QObject, DirManager): + # 信号必须定义为类属性,不能放在__init__方法里 + image_signal = pyqtSignal(dict) + spectral_signal = pyqtSignal(dict) + + def __init__(self): + ''' + 配置文件读取和写入类,采集数据需要的帧率、曝光、帧数、文件名等等都由此类从文件中读取并保存在此类中, + ''' + super(ConfigFile, self).__init__() + + self.corning_config_file = self.log_dir + '//corning_config.ini' + + self.read_config_file() + + self.image_signal.connect(self.image_record_param_changed) + self.spectral_signal.connect(self.spectral_record_param_changed) + + # 读取配置文件,如果没有就创建 + def read_config_file(self): + if os.path.exists(self.corning_config_file): + ''' + 如果存在配置文件,就从配置文件中读取软件配置信息 + ''' + print('配置文件存在!') + + config = configparser.ConfigParser() + config.read(self.corning_config_file) + + # self.image_dir = config.get('image_record_param', 'image_dir') + # self.create_directory(self.image_dir) + # self.default_image_name = config.get('image_record_param', 'default_image_name') + # self.framerate = int(config.get('image_record_param', 'framerate')) + # self.exposure_time = int(float(config.get('image_record_param', 'exposure_time'))) + # self.gain = int(float(config.get('image_record_param', 'gain'))) + # self.frame_number = int(config.get('image_record_param', 'frame_number')) + # self.arcus_speed = int(config.get('image_record_param', 'arcus_speed')) + # + # self.spectral_dir = config.get('spectral_record_param', 'spectral_dir') + # self.create_directory(self.spectral_dir) + # self.default_spectral_name = config.get('spectral_record_param', 'default_spectral_name') + # self.spectral_number = int(config.get('spectral_record_param', 'spectral_number')) + # self.framenumber_average = int(config.get('spectral_record_param', 'framenumber_average')) + # self.exposure_time_spectral = int(config.get('spectral_record_param', 'exposure_time_spectral')) + # + # self.binning = int(config.get('bin', 'binning')) + # if self.binning == 1: + # self.start_column = int(config.get('bin', 'start_column_binning_1')) + # self.end_column = int(config.get('bin', 'end_column_binning_1')) + # self.start_row = int(config.get('bin', 'start_row_binning_1')) + # self.end_row = int(config.get('bin', 'end_row_binning_1')) + # elif self.binning == 2: + # self.start_column = int(config.get('bin', 'start_column_binning_2')) + # self.end_column = int(config.get('bin', 'end_column_binning_2')) + # self.start_row = int(config.get('bin', 'start_row_binning_2')) + # self.end_row = int(config.get('bin', 'end_row_binning_2')) + # + # # print(self.default_dir, self.binning, self.start_column, self.end_column, self.start_row, self.end_row) + else: + ''' + 1、如果不存在配置文件,就建立配置文件; + 2、并且手动创建配置变量 + ''' + config = configparser.ConfigParser() + + + + config.add_section('bin') + config.set('bin', 'binning', '1') + + # # Serial number = 008 + # config.set('bin', 'start_column_binning_1', '12') + # config.set('bin', 'end_column_binning_1', '1376') + # config.set('bin', 'start_row_binning_1', '2') + # config.set('bin', 'end_row_binning_1', '302') + # + # config.set('bin', 'start_column_binning_2', '13') + # config.set('bin', 'end_column_binning_2', '695') + # config.set('bin', 'start_row_binning_2', '0') + # config.set('bin', 'end_row_binning_2', '150') + + # # Serial number = 0073 + # config.set('bin', 'start_column_binning_1', '12') + # config.set('bin', 'end_column_binning_1', '1376') + # config.set('bin', 'start_row_binning_1', '1') + # config.set('bin', 'end_row_binning_1', '301') + # + # config.set('bin', 'start_column_binning_2', '13') + # config.set('bin', 'end_column_binning_2', '695') + # config.set('bin', 'start_row_binning_2', '0') + # config.set('bin', 'end_row_binning_2', '150') + + # # Serial number = 0095 + # config.set('bin', 'start_column_binning_1', '12') + # config.set('bin', 'end_column_binning_1', '1376') + # config.set('bin', 'start_row_binning_1', '1') + # config.set('bin', 'end_row_binning_1', '301') + # + # config.set('bin', 'start_column_binning_2', '13') + # config.set('bin', 'end_column_binning_2', '695') + # config.set('bin', 'start_row_binning_2', '0') + # config.set('bin', 'end_row_binning_2', '150') + + # Serial number = 0031 + config.set('bin', 'start_column_binning_1', '12') + config.set('bin', 'end_column_binning_1', '1376') + config.set('bin', 'start_row_binning_1', '1') + config.set('bin', 'end_row_binning_1', '301') + + config.set('bin', 'start_column_binning_2', '13') + config.set('bin', 'end_column_binning_2', '695') + config.set('bin', 'start_row_binning_2', '1') + config.set('bin', 'end_row_binning_2', '151') + + # # Serial number = 0099 + # config.set('bin', 'start_column_binning_1', '12') + # config.set('bin', 'end_column_binning_1', '1376') + # config.set('bin', 'start_row_binning_1', '1') + # config.set('bin', 'end_row_binning_1', '301') + # + # config.set('bin', 'start_column_binning_2', '13') + # config.set('bin', 'end_column_binning_2', '695') + # config.set('bin', 'start_row_binning_2', '1') + # config.set('bin', 'end_row_binning_2', '151') + + + + config.add_section('effective_window') + config.set('effective_window', 'width_binning_1', '1392') + config.set('effective_window', 'offsetX_binning_1', '272') + config.set('effective_window', 'height_binning_1', '302') + config.set('effective_window', 'offsetY_binning_1', '364') + + config.set('effective_window', 'width_binning_2', '696') + config.set('effective_window', 'offsetX_binning_2', '128') + config.set('effective_window', 'height_binning_2', '151') + config.set('effective_window', 'offsetY_binning_2', '182') + + config.add_section('calibration_file') + config.set('calibration_file', 'cal_file_name_image_bining_1', 'lens_bin1_gain_SN0073') + config.set('calibration_file', 'cal_file_name_image_bining_2', 'lens_bin2_gain_SN0073') + + config.set('calibration_file', 'cal_file_it_image_bining_1', '6969') + config.set('calibration_file', 'cal_file_it_image_bining_2', '1628') + + config.set('calibration_file', 'cal_file_name_spectral_bining_1', 'optical_fiber_bin1_gain_SN0073') + config.set('calibration_file', 'cal_file_it_spectrl_bining_1', '42300') + + + + + config.add_section('wavelength_file_name') + config.set('wavelength_file_name', 'file_name', 'wavelength0073.txt') + + + + + + config.add_section('image_record_param') + config.set('image_record_param', 'image_dir', self.base_dir + '/image') + config.set('image_record_param', 'default_image_name', 'testimage') + config.set('image_record_param', 'framerate', '20') + config.set('image_record_param', 'exposure_time', '500') + config.set('image_record_param', 'gain', '0') + config.set('image_record_param', 'frame_number', '20') + config.set('image_record_param', 'arcus_speed', '1000') + + config.add_section('spectral_record_param') + config.set('spectral_record_param', 'spectral_dir', self.base_dir + '/spectral') + config.set('spectral_record_param', 'default_spectral_name', 'testspectral') + config.set('spectral_record_param', 'spectral_number', '10') + config.set('spectral_record_param', 'framenumber_average', '10') + config.set('spectral_record_param', 'exposure_time_spectral', '1000') + # config.set('spectral_record_param', 'start_column_binning_1', '12') + + with open(self.corning_config_file, mode='w') as f: + config.write(f)# 如果没有配置文件,就手动创建配置变量 + print('创建配置文件成功!') + + + + # 读取配置文件中的参数 + self.binning = int(config.get('bin', 'binning')) + print('读取配置文件中参数:', self.binning) + + if self.binning == 1: + self.effective_window_width = int(config.get('effective_window', 'width_binning_1')) + self.effective_window_offsetx = int(config.get('effective_window', 'offsetx_binning_1')) + self.effective_window_height = int(config.get('effective_window', 'height_binning_1')) + self.effective_window_offsety = int(config.get('effective_window', 'offsety_binning_1')) + + self.start_column = int(config.get('bin', 'start_column_binning_1')) + self.end_column = int(config.get('bin', 'end_column_binning_1')) + self.start_row = int(config.get('bin', 'start_row_binning_1')) + self.end_row = int(config.get('bin', 'end_row_binning_1')) + + self.calibration_file_name_image=config.get('calibration_file', 'cal_file_name_image_bining_1') + self.calibration_file_it_image = int(config.get('calibration_file', 'cal_file_it_image_bining_1')) + self.calibration_file_name_spectral = config.get('calibration_file', 'cal_file_name_spectral_bining_1') + self.calibration_file_it_spectral = int(config.get('calibration_file', 'cal_file_it_spectrl_bining_1')) + elif self.binning == 2: + self.effective_window_width = int(config.get('effective_window', 'width_binning_2')) + self.effective_window_offsetx = int(config.get('effective_window', 'offsetx_binning_2')) + self.effective_window_height = int(config.get('effective_window', 'height_binning_2')) + self.effective_window_offsety = int(config.get('effective_window', 'offsety_binning_2')) + + self.start_column = int(config.get('bin', 'start_column_binning_2')) + self.end_column = int(config.get('bin', 'end_column_binning_2')) + self.start_row = int(config.get('bin', 'start_row_binning_2')) + self.end_row = int(config.get('bin', 'end_row_binning_2')) + + self.calibration_file_name_image = config.get('calibration_file', 'cal_file_name_image_bining_2') + self.calibration_file_it_image = int(config.get('calibration_file', 'cal_file_it_image_bining_2')) + + self.wavelength_file_name = config.get('wavelength_file_name', 'file_name') + + self.image_dir = config.get('image_record_param', 'image_dir') + self.create_directory(self.image_dir) + self.default_image_name = config.get('image_record_param', 'default_image_name') + self.framerate = int(float(config.get('image_record_param', 'framerate'))) + self.exposure_time = int(float(config.get('image_record_param', 'exposure_time'))) + self.gain = int(float(config.get('image_record_param', 'gain'))) + self.frame_number = int(float(config.get('image_record_param', 'frame_number'))) + self.arcus_speed = int(float(config.get('image_record_param', 'arcus_speed'))) + + self.spectral_dir = config.get('spectral_record_param', 'spectral_dir') + self.create_directory(self.spectral_dir) + self.default_spectral_name = config.get('spectral_record_param', 'default_spectral_name') + self.spectral_number = int(float(config.get('spectral_record_param', 'spectral_number'))) + self.framenumber_average = int(float(config.get('spectral_record_param', 'framenumber_average'))) + self.exposure_time_spectral = int(float(config.get('spectral_record_param', 'exposure_time_spectral'))) + + # self.start_column = 12 + # self.end_column = 1376 + # self.start_row = 1 + # self.end_row = 300 + + def image_record_param_changed(self, dictionary): + ''' + :param dictionary: {'image_dir':值, 'image_record_param': 值} + :return: + ''' + try: + # print('接收的参数个数:', len(dictionary.keys())) + + config = configparser.ConfigParser() + config.read(self.corning_config_file) + + for key in dictionary.keys(): + # self.key = dictionary[key] + # config.set('image_record_param', key, dictionary[key]) + + if key == 'image_dir': + self.image_dir = dictionary[key] + config.set('image_record_param', key, dictionary[key]) + if key == 'default_image_name': + self.default_image_name = dictionary[key] + config.set('image_record_param', key, dictionary[key]) + if key == 'framerate': + self.framerate = dictionary[key] + config.set('image_record_param', key, str(dictionary[key])) + if key == 'exposure_time': + self.exposure_time = dictionary[key] + config.set('image_record_param', key, str(dictionary[key])) + if key == 'gain': + self.gain = dictionary[key] + config.set('image_record_param', key, str(dictionary[key])) + if key == 'frame_number': + self.frame_number = dictionary[key] + config.set('image_record_param', key, str(dictionary[key])) + if key == 'arcus_speed': + self.arcus_speed = dictionary[key] + config.set('image_record_param', key, str(dictionary[key])) + except: + traceback.print_exc() + + with open(self.corning_config_file, 'w') as f: + config.write(f) + + def spectral_record_param_changed(self, dictionary): + ''' + :param dictionary: {'image_dir':值, 'image_record_param': 值} + :return: + ''' + print(len(dictionary.keys())) + + config = configparser.ConfigParser() + config.read(self.corning_config_file) + + try: + for key in dictionary.keys(): + if key == 'spectral_dir': + self.spectral_dir = dictionary[key] + config.set('spectral_record_param', key, dictionary[key]) + if key == 'default_spectral_name': + self.default_spectral_name = dictionary[key] + config.set('spectral_record_param', key, dictionary[key]) + if key == 'spectral_number': + self.spectral_number = dictionary[key] + config.set('spectral_record_param', key, str(dictionary[key])) + if key == 'framenumber_average': + self.framenumber_average = dictionary[key] + config.set('spectral_record_param', key, str(dictionary[key])) + if key == 'exposure_time_spectral': + self.exposure_time_spectral = dictionary[key] + config.set('spectral_record_param', key, str(dictionary[key])) + except: + traceback.print_exc() + + with open(self.corning_config_file, 'w') as f: + config.write(f) + + +if __name__ == '__main__': + x = ConfigFile() diff --git a/library/dir_manager.py b/library/dir_manager.py new file mode 100644 index 0000000..84e3a3d --- /dev/null +++ b/library/dir_manager.py @@ -0,0 +1,29 @@ +import os +from library.functions import get_path + + +class DirManager(): + def __init__(self): + self.base_dir = get_path() + self.log_dir = self.base_dir + '//log' + + self.create_directory(self.log_dir) + print(self.log_dir) + + + # 查看是否存在保存光谱和影像文件的目录,如果没有就创建 + def create_directory(self, directory): + ''' + :param directory: 需要创建的文件夹绝对路径,不能将参数directory省略而在此函数内部使用self.log_dir, + 因为本类的继承类也需要使用此函数 + :return: + ''' + if not os.path.exists(directory): + print('创建文件夹:', directory) + os.makedirs(directory) + # else: + # print('文件夹存在:%s' % self.log_dir) + + +if __name__ == '__main__': + x = DirManager() diff --git a/library/functions.py b/library/functions.py new file mode 100644 index 0000000..29e73d6 --- /dev/null +++ b/library/functions.py @@ -0,0 +1,144 @@ +# -*- coding:utf-8 -*- + +''' +本模块是各种工具函数 +''' + +import sys, os +import numpy as np + +def get_path(): + ''' + 本函数说明:https://pythonhosted.org/PyInstaller/runtime-information.html#using-sys-executable-and-sys-argv-0 + :return: 返回运行程序的绝对路径 + ''' + frozen = 'not' + if getattr(sys, 'frozen', False): + # we are running in a bundle + bundle_dir = sys._MEIPASS + + # print('we are running in a bundle(pyinstaller打包程序)!') + else: + # we are running in a normal Python environment + # bundle_dir = os.path.dirname(os.path.abspath(__file__)) # 此行代码返回的是本文件的路径,而不是本文件所导入的文件的路径 + bundle_dir = os.getcwd() + # print('we are running in a normal Python environment(非pyinstaller打包程序)!') + + return bundle_dir + + +def get_resource_path(relative_path): + ''' + 本函数说明:https://www.zacoding.com/en/post/python-selenium-to-exe/ + :param relative_path: + :return: + ''' + try: + base_path = sys._MEIPASS + except Exception: + base_path = os.getcwd() + return os.path.join(base_path, relative_path) + + +def percentile_stretching(img, lowPercentile=0, highPercentile=100, minout=0, maxout=255): + ''' + 本程序用于拉伸影像 + :param img: + :param lowPercentile: + :param highPercentile: + :param minout: + :param maxout: + :return: + ''' + if len(img.shape) == 2: + low = np.percentile(img, lowPercentile) + up = np.percentile(img, highPercentile) + + img_new = ((img - low) / (up - low)) * (maxout - minout) + minout + img_new[img_new < minout] = minout + img_new[img_new > maxout] = maxout + img_out = np.uint8(img_new) + return img_out + else: # 对于彩色照片,需要先单独对每个波段拉伸 + img_new = np.empty(img.shape) + for i in range(img.shape[2]): + low = np.percentile(img[:, :, i], lowPercentile) + up = np.percentile(img[:, :, i], highPercentile) + + img_new[:, :, i] = minout + ((img[:, :, i] - low) / (up - low)) * (maxout - minout) + img_new[:, :, i][img_new[:, :, i] < minout] = minout + img_new[:, :, i][img_new[:, :, i] > maxout] = maxout + img_out = np.uint8(img_new) + return img_out + + +def return_file_path(out, filepath, filename, model='image'): + ''' + 本程序功能:在filepath中寻找所有包含filename所有文件(filename1、filename2),然后返回一个filename3 + :param out: 永远传入一个空list:[];用于存储所有递归调用 + :param filepath: + :param filename: + :param model: 有两个模式:image 和 spectral + :return: + ''' + + # 出现此处代码的原因是:当次函数定义执行后,函数定义就包含了out参数的引用, + # 而out参数是可变参数,每一次调用次函数都会改变out的值,所有不能保证每次调用此函数时out==[]。 + # 当第二次调用此方程时 + # if out != []: + # if filename not in os.path.splitext(out[-1]): + # out = [] + + if model == 'image': + files = os.listdir(filepath) + for s in files: + abspath = os.path.join(filepath, s) + if os.path.isfile(abspath): + tmp = os.path.splitext(os.path.split(abspath)[1])[0] + if tmp not in out: # 防止重复记录 + if filename in tmp: + out.append(tmp) + else: + pass + # print('没有进来') + elif os.path.isdir(abspath): + return_file_path(out, abspath, filename) + out.sort(key=lambda x: int(x.replace(filename, ''))) + + if out == []: + x = filename + str(0) + return os.path.join(filepath, x), 0 + if out != []: + number = int(out[-1].replace(filename, '')) + 1 + x = filename + str(number) + return os.path.join(filepath, x), number + elif model == 'spectral': + files = os.listdir(filepath) + for s in files: + abspath = os.path.join(filepath, s) + if os.path.isfile(abspath) and os.path.splitext(s)[1] == '.txt': + tmp = os.path.splitext(os.path.split(abspath)[1])[0] + if tmp not in out: # 防止重复记录 + if filename in tmp: + out.append(tmp) + elif os.path.isdir(abspath): + return_file_path(out, abspath, filename) + out.sort(key=lambda x: int(x.replace(filename, ''))) + + if out == []: + x = filename + str(0) + '.txt' + return os.path.join(filepath, x), 0 + if out != []: + number = int(out[-1].replace(filename, '')) + 1 # 现存最大文件号 + 1 + x = filename + str(number) + '.txt' + return os.path.join(filepath, x), number + + +if __name__ == '__main__': + # print(get_path()) + + x = return_file_path([], r'D:\delete', 'sss', model='spectral') + print(x) + + # y = return_file_path([], r'D:\delete', 'rr') + # print(y) diff --git a/library/image_reader_writer.py b/library/image_reader_writer.py new file mode 100644 index 0000000..e2719f5 --- /dev/null +++ b/library/image_reader_writer.py @@ -0,0 +1,40 @@ +import sys, traceback +from osgeo import gdal + +# 读写影像类 +class ImageReaderWriter(object): + + #读图像文件 + @classmethod + def read_img(cls, filename, xoff=0, yoff=0, im_width=None, im_height=None): + try: + dataset = gdal.Open(filename) # 打开文件 + if im_width == None: + im_width = dataset.RasterXSize # 栅格矩阵的列数 + if im_height == None: + im_height = dataset.RasterYSize # 栅格矩阵的行数 + num_bands = dataset.RasterCount # 栅格矩阵的波段数 + im_geotrans = dataset.GetGeoTransform() # 仿射矩阵 + im_proj = dataset.GetProjection() # 地图投影信息 + im_data = dataset.ReadAsArray(xoff, yoff, im_width, im_height) # 将数据写成数组,对应栅格矩阵 + del dataset + return im_proj, im_geotrans, im_data + except AttributeError: + print('gdal打开影像:没有文件!') + except Exception: + traceback.print_exc() + pass + + #写文件,以写成tif为例 + @classmethod + def write_img(cls, dst_filename, data): + format = "ENVI" + driver = gdal.GetDriverByName(format) + RasterXSize = data.shape[2] # 遥感影像的sample(列数) + RasterYSize = data.shape[1] # 遥感影像的line(行数) + band = data.shape[0] + # driver.Create()函数中RasterXSize代表影像的sample(列数),RasterYSize代表影像的line(行数) + dst_ds = driver.Create(dst_filename, RasterXSize, RasterYSize, band, gdal.GDT_Float32) + for i in range(band): + dst_ds.GetRasterBand(i + 1).WriteArray(data[i, :, :]) # gdal的band从1开始,所以dst_ds.GetRasterBand(i+1) + dst_ds = None \ No newline at end of file diff --git a/library/log.py b/library/log.py new file mode 100644 index 0000000..8198e57 --- /dev/null +++ b/library/log.py @@ -0,0 +1,50 @@ +# 标准库 +import traceback, os, logging + +# 三方库 +import configparser + +# 自己写的库 +from library.dir_manager import DirManager + + +class Log(DirManager): + def __init__(self): + super(Log, self).__init__() + + self.log() + + def log(self): + # 判断是否存在log文件,如果不存在就创建 + if not os.path.exists(self.log_dir + '//all_operate.log'): + with open(self.log_dir + '//all_operate.log', 'w') as f: + pass + if not os.path.exists(self.log_dir + '//error.log'): + with open(self.log_dir + '//error.log', 'w') as f: + pass + + # 初始化log + root_logger = logging.getLogger('root') + root_logger.setLevel(level=logging.DEBUG) # logger级别设置为低级别,代表这个logger可以处理很多级别的日志,更灵活的处理放在logger中的各种handler中 + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + + all_operate_file_handler = logging.FileHandler(self.log_dir + '//all_operate.log') # 输出到文件 + all_operate_file_handler.setLevel(logging.INFO) + all_operate_file_handler.setFormatter(formatter) + + error_file_handler = logging.FileHandler(self.log_dir + '//error.log') # 输出到文件 + error_file_handler.setLevel(logging.ERROR) + error_file_handler.setFormatter(formatter) + + stream_handler = logging.StreamHandler() # 输出到控制台 + stream_handler.setLevel(logging.INFO) + stream_handler.setFormatter(formatter) + + root_logger.addHandler(all_operate_file_handler) + root_logger.addHandler(error_file_handler) + root_logger.addHandler(stream_handler) + + +if __name__ == '__main__': + x = Log() diff --git a/library/log/corning_config.ini b/library/log/corning_config.ini new file mode 100644 index 0000000..5951427 --- /dev/null +++ b/library/log/corning_config.ini @@ -0,0 +1,25 @@ +[bin] +binning = 1 +start_column_binning_1 = 12 +end_column_binning_1 = 1376 +start_row_binning_1 = 1 +end_row_binning_1 = 301 +start_column_binning_2 = 13 +end_column_binning_2 = 695 +start_row_binning_2 = 1 +end_row_binning_2 = 150 + +[image_record_param] +image_dir = D:\py_program\corning410\library/image +default_image_name = test_image +framerate = 20 +exposure_time = 500 +gain = 0 +frame_number = 20 + +[spectral_record_param] +spectral_dir = D:\py_program\corning410\library/spectral +default_spectral_name = test_spectral +spectral_number = 10 +framenumber_average = 10 + diff --git a/library/matplotlib_display_image_spectral.py b/library/matplotlib_display_image_spectral.py new file mode 100644 index 0000000..81a925f --- /dev/null +++ b/library/matplotlib_display_image_spectral.py @@ -0,0 +1,161 @@ +import matplotlib +matplotlib.use("Qt5Agg") # 声明使用QT5 +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.figure import Figure +import traceback +import time, sys +from functions import percentile_stretching + +from PyQt5 import QtWidgets, QtCore, uic +import pyqtgraph as pg +from random import randint + + +class ArgsError(Exception): + pass + +# 画图类,用于:画出采集到的光谱;调焦(影响模式调焦) +class MatplotlibSpectralViewer(FigureCanvas): + def __init__(self, xlabel=None, ylabel=None, width=5, height=4, dpi=100): + # 第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + + # 第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MatplotlibSpectralViewer, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + + # 第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + self.axes.set_xlabel('Wavelength (nm)') + self.axes.set_ylabel('reflectance') + + self.xlabel = xlabel + self.ylabel = ylabel + + self._plotref = None # 这里代表曲线 + + self.axes.set_ylim(0, 1.2) + + # 第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def plot_wrap(self, *args): + if self.xlabel is not None: + self.axes.set_xlabel(self.xlabel) + if self.ylabel is not None: + self.axes.set_ylabel(self.ylabel) + + try: + if self._plotref == None: + if len(args) == 0: + raise ArgsError('传入了0个参数,本函数只能传入1/2个参数!') + elif len(args) == 1: + self.axes.cla() + + # self.axes.set_ylim(0, 1.2) + + self._plotref = self.axes.plot(list(range(len(args[0]))), args[0])[0] + self.draw() + elif len(args) == 2: + self.axes.cla() + + # self.axes.set_ylim(0, 1.2) + + self._plotref = self.axes.plot(args[0], args[1])[0] + self.draw() + elif len(args) > 2: + raise ArgsError('传入了大于2个参数,本函数只能传入1/2个参数!') + elif self._plotref is not None: + if len(args) == 0: + raise ArgsError('传入了0个参数,本函数只能传入1/2个参数!') + elif len(args) == 1: + self._plotref.set_data(list(range(len(args[0]))), args[0]) + + # 更新显示区域 + self.axes.set_xlim(min(list(range(len(args[0])))), max(list(range(len(args[0]))))) + self.axes.set_ylim(min(args[0]), max(args[0])) + + # self.axes.set_ylim(0, 1.2) + + # 绘制图像 + self.draw() + elif len(args) == 2: + self._plotref.set_data(args[0], args[1]) + + # 更新显示区域 + self.axes.set_xlim(min(args[0]), max(args[0])) + self.axes.set_ylim(min(args[1]), max(args[1])) + + # self.axes.set_ylim(0, 1.2) + + # 绘制图像 + self.draw() + elif len(args) > 2: + raise ArgsError('传入了大于2个参数,本函数只能传入1/2个参数!') + except Exception: + traceback.print_exc() + + +# 画图类,用于:画出采集到的图像;显示帧流(光谱模式对准光纤) +class MatplotlibImageViewer(FigureCanvas): + def __init__(self, width=5, height=4, dpi=100): + # 第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + # 第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MatplotlibImageViewer, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + # 第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + + self._plotref = None # 这里代表图像 + + # 第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def setImage(self, image, lowPercentile=0, highPercentile=100): + self.axes.set_xticks([]) + self.axes.set_yticks([]) + + if self._plotref == None: + self._plotref = self.axes.imshow(image) + self.draw() + elif self._plotref is not None: + self._plotref.set_data(percentile_stretching(image, lowPercentile, highPercentile)) + self.draw() + + +class MainWindow(QtWidgets.QMainWindow): + def __init__(self, *args, **kwargs): + super(MainWindow, self).__init__(*args, **kwargs) + + # self.graphWidget = QtSpectralViewer() + self.graphWidget = MatplotlibSpectralViewer(xlabel='Wavelength (nm)', ylabel='reflectance') + self.setCentralWidget(self.graphWidget) + + self.x = list(range(100)) # 100 time points + self.y = [randint(0, 100) for _ in range(100)] # 100 data points + + # self.graphWidget.setBackground('w') + + pen = pg.mkPen(color=(255, 0, 0)) + self.graphWidget.plot_wrap(self.x, self.y) + + self.timer = QtCore.QTimer() + self.timer.timeout.connect(self.update_plot_data) + self.timer.start(10) + + def update_plot_data(self): + self.x = self.x[1:] # Remove the first y element. + self.x.append(self.x[-1] + 1) # Add a new value 1 higher than the last. + + self.y = self.y[1:] # Remove the first + self.y.append(randint(0, 100)) # Add a new random value. + + # self.data_line.setData(self.x, self.y) # Update the data. + + self.graphWidget.plot_wrap(self.x, self.y) + + +if __name__ == '__main__': + app = QtWidgets.QApplication(sys.argv) + w = MainWindow() + w.show() + sys.exit(app.exec_()) diff --git a/library/message_box.py b/library/message_box.py new file mode 100644 index 0000000..035cbb0 --- /dev/null +++ b/library/message_box.py @@ -0,0 +1,53 @@ +from PyQt5.QtWidgets import QApplication, QDialog +from PyQt5.QtCore import Qt + +import sys + +from library.message_box_ui import * + + +class MessageBox(QDialog, Ui_message_box_ui): + def __init__(self, txt, parent=None): + ''' + The super().__init__() method invokes the base class constructor from the MyForm class, + that is, the constructor of the QDialog class is invoked from MyForm class to indicate that + QDialog is displayed through this class iss a top-level window. + ''' + super(MessageBox, self).__init__(parent) + self.setupUi(self) + + # self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + self.setWindowModality(Qt.ApplicationModal) # 阻塞此窗口:只能在关闭此窗口之后才能操作后面的窗口,但是不会阻塞调用此窗口的进程的代码;此行代码必须放在show()函数之前 + # self.setWindowModality(Qt.WindowModal) + + # 无边框 + # self.setWindowFlags(Qt.FramelessWindowHint) + + self.txt = txt + + self.info() + + self.confirm_bt.clicked.connect(self.shutdown) + + # 禁止调整大小 + # self.setFixedSize(self.width(), self.height()) + + def info(self): + self.info_label.setText(self.txt) + + # self.exec() # 阻塞调用此窗口后的进程的代码,只有此窗口返回后才能执行此窗口外的代码 + + # self.show() # 只是显示,不会阻塞任何代码 + + def shutdown(self): + self.close() + + +if __name__ == '__main__': + app = QApplication(sys.argv) + + x = MessageBox('请先曝光和采集暗电流!') + + # x.show() + + sys.exit(app.exec_()) diff --git a/library/message_box_ui.py b/library/message_box_ui.py new file mode 100644 index 0000000..833cb29 --- /dev/null +++ b/library/message_box_ui.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'message_box_ui.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_message_box_ui(object): + def setupUi(self, message_box_ui): + message_box_ui.setObjectName("message_box_ui") + message_box_ui.resize(487, 385) + self.gridLayout = QtWidgets.QGridLayout(message_box_ui) + self.gridLayout.setObjectName("gridLayout") + self.info_label = QtWidgets.QLabel(message_box_ui) + self.info_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:30pt;\n" +" /*字体颜色为白色*/\n" +" /*color:white;*/\n" +" /*背景颜色*/\n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:8px;*/\n" +"}") + self.info_label.setAlignment(QtCore.Qt.AlignCenter) + self.info_label.setObjectName("info_label") + self.gridLayout.addWidget(self.info_label, 0, 0, 1, 1) + self.confirm_bt = QtWidgets.QPushButton(message_box_ui) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.confirm_bt.sizePolicy().hasHeightForWidth()) + self.confirm_bt.setSizePolicy(sizePolicy) + self.confirm_bt.setMinimumSize(QtCore.QSize(0, 130)) + self.confirm_bt.setAcceptDrops(False) + self.confirm_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.confirm_bt.setObjectName("confirm_bt") + self.gridLayout.addWidget(self.confirm_bt, 1, 0, 1, 1) + + self.retranslateUi(message_box_ui) + QtCore.QMetaObject.connectSlotsByName(message_box_ui) + + def retranslateUi(self, message_box_ui): + _translate = QtCore.QCoreApplication.translate + message_box_ui.setWindowTitle(_translate("message_box_ui", "提示")) + self.info_label.setText(_translate("message_box_ui", "提示信息")) + self.confirm_bt.setText(_translate("message_box_ui", "确定")) diff --git a/library/message_box_ui.ui b/library/message_box_ui.ui new file mode 100644 index 0000000..97fa41d --- /dev/null +++ b/library/message_box_ui.ui @@ -0,0 +1,106 @@ + + + message_box_ui + + + + 0 + 0 + 487 + 385 + + + + 提示 + + + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:30pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 提示信息 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 130 + + + + false + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0); + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 确定 + + + + + + + + diff --git a/library/multithread.py b/library/multithread.py new file mode 100644 index 0000000..769188c --- /dev/null +++ b/library/multithread.py @@ -0,0 +1,81 @@ +import sys, traceback +from PyQt5.QtCore import QRunnable, QObject, pyqtSignal, pyqtSlot + +class WorkerSignals(QObject): + ''' + Defines the signals available from a running worker thread. + + Supported signals are: + + finished + No data + + error + `tuple` (exctype, value, traceback.format_exc() ) + + result + `object` data returned from processing, anything + + progress + `int` indicating % progress + + # 信号必须定义为类属性,不能放在__init__方法里 + ''' + finished = pyqtSignal() + error = pyqtSignal(tuple) + result = pyqtSignal(object) + progress = pyqtSignal(int) # 可以用作进度条 + + serial = pyqtSignal(object) # 2record_system_v26的此信号移动到类SerialPort中了 + + image_signal = pyqtSignal(dict) # 只用在2record_system_v25中 + spectral_signal = pyqtSignal(dict) # 只用在2record_system_v25中 + + openinfo = pyqtSignal(int) # 只用在2record_system_v25中 + plotsignal = pyqtSignal() # 2record_system_v26的此信号移动到类ImageWindowPhone中了 + +# https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ +# 用于qt多线程:运行long-time task +class Worker(QRunnable): + ''' + Worker thread + + Inherits from QRunnable to handler worker thread setup, signals and wrap-up. + + :param callback: The function callback to run on this worker thread. Supplied args and + kwargs will be passed through to the runner. + :type callback: function + :param args: Arguments to pass to the callback function + :param kwargs: Keywords to pass to the callback function + + ''' + + def __init__(self, fn, *args, **kwargs): + super(Worker, self).__init__() + + # Store constructor arguments (re-used for processing) + self.fn = fn + self.args = args + self.kwargs = kwargs + self.signals = WorkerSignals() + + # Add the callback to our kwargs + # self.kwargs['progress_callback'] = self.signals.progress + + @pyqtSlot() + def run(self): + ''' + Initialise the runner function with passed args, kwargs. + ''' + try: # 如果有错,就捕捉错误 + result = self.fn(*self.args, **self.kwargs) + except Exception: # 根据错误进行处理 + traceback.print_exc() + exctype, value = sys.exc_info()[:2] + + self.signals.error.emit((exctype, value, traceback.format_exc())) + else: # 如果没有错误执行下面代码 + self.signals.finished.emit() # Done + self.signals.result.emit(result) # Return the result of the processing + finally: # 不管有错无错,都要执行下面代码 + pass \ No newline at end of file diff --git a/pyqt_multithread.py b/pyqt_multithread.py new file mode 100644 index 0000000..a16ae77 --- /dev/null +++ b/pyqt_multithread.py @@ -0,0 +1,143 @@ +from PyQt5.QtGui import * +from PyQt5.QtWidgets import * +from PyQt5.QtCore import * + +import time +import traceback, sys + + +class WorkerSignals(QObject): + ''' + Defines the signals available from a running worker thread. + + Supported signals are: + + finished + No data + + error + `tuple` (exctype, value, traceback.format_exc() ) + + result + `object` data returned from processing, anything + + progress + `int` indicating % progress + + ''' + finished = pyqtSignal() + error = pyqtSignal(tuple) + result = pyqtSignal(object) + progress = pyqtSignal(int) + + +class Worker(QRunnable): + ''' + Worker thread + + Inherits from QRunnable to handler worker thread setup, signals and wrap-up. + + :param callback: The function callback to run on this worker thread. Supplied args and + kwargs will be passed through to the runner. + :type callback: function + :param args: Arguments to pass to the callback function + :param kwargs: Keywords to pass to the callback function + + ''' + + def __init__(self, fn, *args, **kwargs): + super(Worker, self).__init__() + + # Store constructor arguments (re-used for processing) + self.fn = fn + self.args = args + self.kwargs = kwargs + self.signals = WorkerSignals() + + # Add the callback to our kwargs + self.kwargs['progress_callback'] = self.signals.progress + + @pyqtSlot() + def run(self): + ''' + Initialise the runner function with passed args, kwargs. + ''' + + # Retrieve args/kwargs here; and fire processing using them + try: + result = self.fn(*self.args, **self.kwargs) + except: + traceback.print_exc() + exctype, value = sys.exc_info()[:2] + self.signals.error.emit((exctype, value, traceback.format_exc())) + else: + self.signals.result.emit(result) # Return the result of the processing + finally: + self.signals.finished.emit() # Done + + +class MainWindow(QMainWindow): + + def __init__(self, *args, **kwargs): + super(MainWindow, self).__init__(*args, **kwargs) + + self.counter = 0 + + layout = QVBoxLayout() + + self.l = QLabel("Start") + b = QPushButton("DANGER!") + b.pressed.connect(self.oh_no) + + layout.addWidget(self.l) + layout.addWidget(b) + + w = QWidget() + w.setLayout(layout) + + self.setCentralWidget(w) + + self.show() + + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + self.timer = QTimer() + self.timer.setInterval(1000) + self.timer.timeout.connect(self.recurring_timer) + self.timer.start() + + def progress_fn(self, n): + print("%d%% done" % n) + + def execute_this_fn(self, progress_callback): + for n in range(0, 5): + time.sleep(1) + progress_callback.emit(n * 100 / 4) + + return "Done." + + def print_output(self, s): + print(s) + + def thread_complete(self): + print("THREAD COMPLETE!") + + def oh_no(self): + # Pass the function to execute + worker = Worker(self.execute_this_fn) # Any other args, kwargs are passed to the run function + worker.signals.result.connect(self.print_output) + worker.signals.finished.connect(self.thread_complete) + worker.signals.progress.connect(self.progress_fn) + + # Execute + self.threadpool.start(worker) + + def recurring_timer(self): + self.counter += 1 + self.l.setText("Counter: %d" % self.counter) + + +app = QApplication([]) +window = MainWindow() +app.exec_() \ No newline at end of file diff --git a/record_system_v11/1record_system_v1.1.py b/record_system_v11/1record_system_v1.1.py new file mode 100644 index 0000000..998e772 --- /dev/null +++ b/record_system_v11/1record_system_v1.1.py @@ -0,0 +1,230 @@ +from ximea import xiapi +import cv2 +import numpy as np +import matplotlib.pyplot as plt +from osgeo import gdal #读写影像数据 +import os, sys, traceback +import datetime # 几种Python执行时间的计算方法:https://blog.csdn.net/wangshuang1631/article/details/54286551 + +#create instance for first connected camera +cam = xiapi.Camera() + +#start communication to open specific device, use: cam.open_device_by_SN('41305651') +print('Opening first camera...') +cam.open_device() + +# 打开相机后,显示相机信息 +print('SN: %s'% str(cam.get_device_sn(), encoding = "utf-8")) +print('Device name: %s'% str(cam.get_device_name(), encoding = "utf-8")) +print('Device name: %s'% str(cam.get_device_type(), encoding = "utf-8")) +print('Instance path: %s'% str(cam.get_device_inst_path(), encoding = "utf-8")) # Returns device instance path in operating system. +print('Location path: %s'% str(cam.get_device_loc_path(), encoding = "utf-8")) + +# debug_level、线程数和horizontal flip +print('Debug level: %s' % cam.get_debug_level()) +print('Default number of threads per image processor: %d' % cam.get_proc_num_threads()) +cam.set_proc_num_threads(8) +print('Current number of threads per image processor: %d' % cam.get_proc_num_threads()) +print('Is horizontal flip enabled?, %s' % str(cam.is_horizontal_flip())) + + +#采集模式:This mode is supported by selected camera families: CB, MC, MT, MX +cam.set_acq_timing_mode('XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') +mode_used = cam.get_acq_timing_mode() +if mode_used == 'XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT': + print('Mode is XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') +else: + print('Mode is not XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + sys.exit() + +#settings,cam.set_param("exposure",10000) +exposure = 50 +framerate = 2 +cam.set_exposure(exposure)#曝光时间单位为微秒,1s共有1000000微秒 +cam.set_framerate(framerate) +print('Exposure was set to %i us' % cam.get_exposure()) +print('Framerate was set to %i FPS' % cam.get_framerate()) + +# # 设置binning参数 +# # XI_BIN_MODE_SUM(默认): The response from the combined pixels will be added, resulting in increased sensitivity. +# # XI_BIN_MODE_AVERAGE: The response from the combined pixels will be averaged, resulting in increased signal/noise ratio. +bin_spec = 2 +bin_spatial = 2 + +cam.set_binning_selector('XI_BIN_SELECT_HOST_CPU') # 默认为XI_BIN_SELECT_SENSOR(会报错),不可用:XI_BIN_SELECT_DEVICE_FPGA +cam.set_binning_horizontal_mode('XI_BIN_MODE_SUM') +cam.set_binning_horizontal(bin_spatial) +cam.set_binning_vertical_mode('XI_BIN_MODE_SUM') +cam.set_binning_vertical(bin_spec) + + +# cam.get_width_increment() -->16 +# cam.get_height_increment() -->2 +# cam.get_offsetX_increment() -->16 +# cam.get_offsetY_increment() -->2 +# 设置有效输出窗口 + +if bin_spatial == 1: + cam.set_width(1392) + cam.set_offsetX(272) + + cam.set_height(302) + cam.set_offsetY(338) +elif bin_spatial == 2: + cam.set_width(696) + cam.set_offsetX(128) + + cam.set_height(151) + cam.set_offsetY(168) + + +# 创建img = xiapi.Image()前需要设置一系列img参数,例如:格式、位深度、 +# 如果格式设置为XI_RAW8,image_raw_numpy.dtype -> dtype('uint8'), uint8 +# 如果格式设置为XI_RAW16,image_raw_numpy.dtype -> dtype(' dtype(' + + arcus_ui + + + + 0 + 0 + 354 + 171 + + + + MainWindow + + + + + + 100 + 90 + 61 + 21 + + + + + + + + + + 170 + 90 + 61 + 23 + + + + + + + + + + 101 + 10 + 131 + 20 + + + + + + + 100 + 40 + 131 + 20 + + + + Qt::Horizontal + + + + + + + 0 + 0 + 354 + 23 + + + + + + + + diff --git a/record_system_v21/enter_window.py b/record_system_v21/enter_window.py new file mode 100644 index 0000000..9f5f1cd --- /dev/null +++ b/record_system_v21/enter_window.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'enter_window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_enter_Window(object): + def setupUi(self, enter_Window): + enter_Window.setObjectName("enter_Window") + enter_Window.resize(651, 474) + self.centralwidget = QtWidgets.QWidget(enter_Window) + self.centralwidget.setObjectName("centralwidget") + self.image_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.image_mode_bt.setGeometry(QtCore.QRect(200, 180, 111, 51)) + self.image_mode_bt.setObjectName("image_mode_bt") + self.spectral_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.spectral_mode_bt.setGeometry(QtCore.QRect(360, 180, 111, 51)) + self.spectral_mode_bt.setObjectName("spectral_mode_bt") + self.camstatus_tb = QtWidgets.QTextBrowser(self.centralwidget) + self.camstatus_tb.setGeometry(QtCore.QRect(200, 240, 271, 81)) + self.camstatus_tb.setObjectName("camstatus_tb") + enter_Window.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(enter_Window) + self.menubar.setGeometry(QtCore.QRect(0, 0, 651, 26)) + self.menubar.setObjectName("menubar") + enter_Window.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(enter_Window) + self.statusbar.setObjectName("statusbar") + enter_Window.setStatusBar(self.statusbar) + self.actionwew_e = QtWidgets.QAction(enter_Window) + self.actionwew_e.setObjectName("actionwew_e") + + self.retranslateUi(enter_Window) + QtCore.QMetaObject.connectSlotsByName(enter_Window) + + def retranslateUi(self, enter_Window): + _translate = QtCore.QCoreApplication.translate + enter_Window.setWindowTitle(_translate("enter_Window", "主窗口")) + self.image_mode_bt.setText(_translate("enter_Window", "影像模式")) + self.spectral_mode_bt.setText(_translate("enter_Window", "光谱模式")) + self.actionwew_e.setText(_translate("enter_Window", "wew e")) diff --git a/record_system_v21/enter_window.ui b/record_system_v21/enter_window.ui new file mode 100644 index 0000000..4c39418 --- /dev/null +++ b/record_system_v21/enter_window.ui @@ -0,0 +1,73 @@ + + + enter_Window + + + + 0 + 0 + 651 + 474 + + + + 主窗口 + + + + + + 200 + 180 + 111 + 51 + + + + 影像模式 + + + + + + 360 + 180 + 111 + 51 + + + + 光谱模式 + + + + + + 200 + 240 + 271 + 81 + + + + + + + + 0 + 0 + 651 + 26 + + + + + + + wew e + + + + + + diff --git a/record_system_v21/image_Window.py b/record_system_v21/image_Window.py new file mode 100644 index 0000000..53dc349 --- /dev/null +++ b/record_system_v21/image_Window.py @@ -0,0 +1,231 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'image_Window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_image_Window(object): + def setupUi(self, image_Window): + image_Window.setObjectName("image_Window") + image_Window.setEnabled(True) + image_Window.resize(1181, 683) + image_Window.setMouseTracking(False) + image_Window.setAutoFillBackground(False) + image_Window.setSizeGripEnabled(False) + image_Window.setModal(False) + self.verticalLayout_7 = QtWidgets.QVBoxLayout(image_Window) + self.verticalLayout_7.setObjectName("verticalLayout_7") + self.groupBox_5 = QtWidgets.QGroupBox(image_Window) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth()) + self.groupBox_5.setSizePolicy(sizePolicy) + self.groupBox_5.setObjectName("groupBox_5") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox_5) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem) + self.splitter_3 = QtWidgets.QSplitter(self.groupBox_5) + self.splitter_3.setOrientation(QtCore.Qt.Horizontal) + self.splitter_3.setObjectName("splitter_3") + self.layoutWidget = QtWidgets.QWidget(self.splitter_3) + self.layoutWidget.setObjectName("layoutWidget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.label = QtWidgets.QLabel(self.layoutWidget) + self.label.setObjectName("label") + self.verticalLayout.addWidget(self.label) + self.label_4 = QtWidgets.QLabel(self.layoutWidget) + self.label_4.setObjectName("label_4") + self.verticalLayout.addWidget(self.label_4) + self.layoutWidget1 = QtWidgets.QWidget(self.splitter_3) + self.layoutWidget1.setObjectName("layoutWidget1") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.layoutWidget1) + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.filepath_le = QtWidgets.QLineEdit(self.layoutWidget1) + self.filepath_le.setObjectName("filepath_le") + self.verticalLayout_2.addWidget(self.filepath_le) + self.filename_le = QtWidgets.QLineEdit(self.layoutWidget1) + self.filename_le.setObjectName("filename_le") + self.verticalLayout_2.addWidget(self.filename_le) + self.layoutWidget2 = QtWidgets.QWidget(self.splitter_3) + self.layoutWidget2.setObjectName("layoutWidget2") + self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.layoutWidget2) + self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.filepath_bt = QtWidgets.QPushButton(self.layoutWidget2) + self.filepath_bt.setObjectName("filepath_bt") + self.verticalLayout_3.addWidget(self.filepath_bt) + self.save_bt = QtWidgets.QPushButton(self.layoutWidget2) + self.save_bt.setObjectName("save_bt") + self.verticalLayout_3.addWidget(self.save_bt) + self.horizontalLayout_4.addWidget(self.splitter_3) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem1) + self.verticalLayout_7.addWidget(self.groupBox_5) + self.splitter = QtWidgets.QSplitter(image_Window) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName("splitter") + self.groupBox_3 = QtWidgets.QGroupBox(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth()) + self.groupBox_3.setSizePolicy(sizePolicy) + self.groupBox_3.setMinimumSize(QtCore.QSize(0, 0)) + self.groupBox_3.setMaximumSize(QtCore.QSize(2000, 16777215)) + self.groupBox_3.setObjectName("groupBox_3") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_3) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.groupBox = QtWidgets.QGroupBox(self.groupBox_3) + self.groupBox.setObjectName("groupBox") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox) + self.horizontalLayout.setObjectName("horizontalLayout") + self.image_glo = QtWidgets.QGridLayout() + self.image_glo.setObjectName("image_glo") + self.horizontalLayout.addLayout(self.image_glo) + self.verticalLayout_4.addWidget(self.groupBox) + self.statu_tb = QtWidgets.QTextBrowser(self.groupBox_3) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.statu_tb.sizePolicy().hasHeightForWidth()) + self.statu_tb.setSizePolicy(sizePolicy) + self.statu_tb.setMaximumSize(QtCore.QSize(8777215, 100)) + self.statu_tb.setReadOnly(True) + self.statu_tb.setObjectName("statu_tb") + self.verticalLayout_4.addWidget(self.statu_tb) + self.groupBox_4 = QtWidgets.QGroupBox(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_4.sizePolicy().hasHeightForWidth()) + self.groupBox_4.setSizePolicy(sizePolicy) + self.groupBox_4.setObjectName("groupBox_4") + self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.groupBox_4) + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.groupBox_2 = QtWidgets.QGroupBox(self.groupBox_4) + self.groupBox_2.setObjectName("groupBox_2") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox_2) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.focus_glo = QtWidgets.QGridLayout() + self.focus_glo.setObjectName("focus_glo") + self.horizontalLayout_2.addLayout(self.focus_glo) + self.verticalLayout_5.addWidget(self.groupBox_2) + self.groupBox_6 = QtWidgets.QGroupBox(self.groupBox_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_6.sizePolicy().hasHeightForWidth()) + self.groupBox_6.setSizePolicy(sizePolicy) + self.groupBox_6.setObjectName("groupBox_6") + self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_6) + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.groupBox_7 = QtWidgets.QGroupBox(self.groupBox_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_7.sizePolicy().hasHeightForWidth()) + self.groupBox_7.setSizePolicy(sizePolicy) + self.groupBox_7.setMaximumSize(QtCore.QSize(500, 500)) + self.groupBox_7.setObjectName("groupBox_7") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_7) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.label_3 = QtWidgets.QLabel(self.groupBox_7) + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.verticalLayout_6.addWidget(self.label_3) + self.focus_bt = QtWidgets.QPushButton(self.groupBox_7) + self.focus_bt.setObjectName("focus_bt") + self.verticalLayout_6.addWidget(self.focus_bt) + self.exposureTime_bt = QtWidgets.QPushButton(self.groupBox_7) + self.exposureTime_bt.setObjectName("exposureTime_bt") + self.verticalLayout_6.addWidget(self.exposureTime_bt) + self.label_5 = QtWidgets.QLabel(self.groupBox_7) + self.label_5.setAlignment(QtCore.Qt.AlignCenter) + self.label_5.setObjectName("label_5") + self.verticalLayout_6.addWidget(self.label_5) + self.wb_bt = QtWidgets.QPushButton(self.groupBox_7) + self.wb_bt.setObjectName("wb_bt") + self.verticalLayout_6.addWidget(self.wb_bt) + self.label_2 = QtWidgets.QLabel(self.groupBox_7) + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.verticalLayout_6.addWidget(self.label_2) + self.record_bt = QtWidgets.QPushButton(self.groupBox_7) + self.record_bt.setObjectName("record_bt") + self.verticalLayout_6.addWidget(self.record_bt) + self.horizontalLayout_3.addLayout(self.verticalLayout_6) + self.verticalLayout_8 = QtWidgets.QVBoxLayout() + self.verticalLayout_8.setObjectName("verticalLayout_8") + self.framerate_le = QtWidgets.QLineEdit(self.groupBox_7) + self.framerate_le.setReadOnly(False) + self.framerate_le.setObjectName("framerate_le") + self.verticalLayout_8.addWidget(self.framerate_le) + self.stop_focus_bt = QtWidgets.QPushButton(self.groupBox_7) + self.stop_focus_bt.setObjectName("stop_focus_bt") + self.verticalLayout_8.addWidget(self.stop_focus_bt) + self.exposureTime_le = QtWidgets.QLineEdit(self.groupBox_7) + self.exposureTime_le.setObjectName("exposureTime_le") + self.verticalLayout_8.addWidget(self.exposureTime_le) + self.gain_le = QtWidgets.QLineEdit(self.groupBox_7) + self.gain_le.setObjectName("gain_le") + self.verticalLayout_8.addWidget(self.gain_le) + self.dc_bt = QtWidgets.QPushButton(self.groupBox_7) + self.dc_bt.setObjectName("dc_bt") + self.verticalLayout_8.addWidget(self.dc_bt) + self.framenumber_le = QtWidgets.QLineEdit(self.groupBox_7) + self.framenumber_le.setObjectName("framenumber_le") + self.verticalLayout_8.addWidget(self.framenumber_le) + self.motor_bt = QtWidgets.QPushButton(self.groupBox_7) + self.motor_bt.setObjectName("motor_bt") + self.verticalLayout_8.addWidget(self.motor_bt) + self.stop_record_bt = QtWidgets.QPushButton(self.groupBox_7) + self.stop_record_bt.setObjectName("stop_record_bt") + self.verticalLayout_8.addWidget(self.stop_record_bt) + self.horizontalLayout_3.addLayout(self.verticalLayout_8) + self.horizontalLayout_5.addWidget(self.groupBox_7) + spacerItem2 = QtWidgets.QSpacerItem(261, 17, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_5.addItem(spacerItem2) + self.verticalLayout_5.addWidget(self.groupBox_6) + self.verticalLayout_7.addWidget(self.splitter) + + self.retranslateUi(image_Window) + QtCore.QMetaObject.connectSlotsByName(image_Window) + + def retranslateUi(self, image_Window): + _translate = QtCore.QCoreApplication.translate + image_Window.setWindowTitle(_translate("image_Window", "影像窗口")) + self.groupBox_5.setTitle(_translate("image_Window", "GroupBox")) + self.label.setText(_translate("image_Window", "保存路径")) + self.label_4.setText(_translate("image_Window", "文件名")) + self.filepath_bt.setText(_translate("image_Window", "浏览")) + self.save_bt.setText(_translate("image_Window", "保存")) + self.groupBox_3.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox.setTitle(_translate("image_Window", "图像")) + self.groupBox_4.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox_2.setTitle(_translate("image_Window", "光谱")) + self.groupBox_6.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox_7.setTitle(_translate("image_Window", "GroupBox")) + self.label_3.setText(_translate("image_Window", "帧率")) + self.focus_bt.setText(_translate("image_Window", "调焦")) + self.exposureTime_bt.setText(_translate("image_Window", "曝光")) + self.label_5.setText(_translate("image_Window", "gain")) + self.wb_bt.setText(_translate("image_Window", "白板")) + self.label_2.setText(_translate("image_Window", "帧数")) + self.record_bt.setText(_translate("image_Window", "采集")) + self.stop_focus_bt.setText(_translate("image_Window", "停止调焦")) + self.dc_bt.setText(_translate("image_Window", "暗电流")) + self.motor_bt.setText(_translate("image_Window", "马达")) + self.stop_record_bt.setText(_translate("image_Window", "停止采集")) diff --git a/record_system_v21/image_Window.ui b/record_system_v21/image_Window.ui new file mode 100644 index 0000000..c2133b3 --- /dev/null +++ b/record_system_v21/image_Window.ui @@ -0,0 +1,377 @@ + + + image_Window + + + true + + + + 0 + 0 + 1181 + 683 + + + + false + + + 影像窗口 + + + false + + + false + + + false + + + + + + + 0 + 0 + + + + GroupBox + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + + + + 保存路径 + + + + + + + 文件名 + + + + + + + + + + + + + + + + + + + + + 浏览 + + + + + + + 保存 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 2000 + 16777215 + + + + GroupBox + + + + + + 图像 + + + + + + + + + + + + + 0 + 0 + + + + + 8777215 + 100 + + + + true + + + + + + + + + 0 + 0 + + + + GroupBox + + + + + + 光谱 + + + + + + + + + + + + + 0 + 0 + + + + GroupBox + + + + + + + 0 + 0 + + + + + 500 + 500 + + + + GroupBox + + + + + + + + 帧率 + + + Qt::AlignCenter + + + + + + + 调焦 + + + + + + + 曝光 + + + + + + + gain + + + Qt::AlignCenter + + + + + + + 白板 + + + + + + + 帧数 + + + Qt::AlignCenter + + + + + + + 采集 + + + + + + + + + + + false + + + + + + + 停止调焦 + + + + + + + + + + + + + 暗电流 + + + + + + + + + + 马达 + + + + + + + 停止采集 + + + + + + + + + + + + Qt::Horizontal + + + + 261 + 17 + + + + + + + + + + + + + + + + diff --git a/record_system_v21/spectral_Window.py b/record_system_v21/spectral_Window.py new file mode 100644 index 0000000..749f060 --- /dev/null +++ b/record_system_v21/spectral_Window.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'spectral_Window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_spectral_Window(object): + def setupUi(self, spectral_Window): + spectral_Window.setObjectName("spectral_Window") + spectral_Window.resize(792, 523) + self.label = QtWidgets.QLabel(spectral_Window) + self.label.setGeometry(QtCore.QRect(54, 10, 51, 20)) + self.label.setObjectName("label") + self.filepath_le = QtWidgets.QLineEdit(spectral_Window) + self.filepath_le.setGeometry(QtCore.QRect(131, 10, 261, 21)) + self.filepath_le.setObjectName("filepath_le") + self.label_2 = QtWidgets.QLabel(spectral_Window) + self.label_2.setGeometry(QtCore.QRect(54, 40, 41, 20)) + self.label_2.setObjectName("label_2") + self.filename_le = QtWidgets.QLineEdit(spectral_Window) + self.filename_le.setGeometry(QtCore.QRect(131, 40, 261, 21)) + self.filename_le.setObjectName("filename_le") + self.filepath_bt = QtWidgets.QPushButton(spectral_Window) + self.filepath_bt.setGeometry(QtCore.QRect(401, 10, 71, 21)) + self.filepath_bt.setObjectName("filepath_bt") + self.statu_tb = QtWidgets.QTextBrowser(spectral_Window) + self.statu_tb.setGeometry(QtCore.QRect(611, 210, 161, 301)) + self.statu_tb.setObjectName("statu_tb") + self.tabWidget = QtWidgets.QTabWidget(spectral_Window) + self.tabWidget.setGeometry(QtCore.QRect(10, 70, 591, 441)) + self.tabWidget.setObjectName("tabWidget") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.gridLayoutWidget = QtWidgets.QWidget(self.tab) + self.gridLayoutWidget.setGeometry(QtCore.QRect(0, 0, 581, 411)) + self.gridLayoutWidget.setObjectName("gridLayoutWidget") + self.spe_glo = QtWidgets.QGridLayout(self.gridLayoutWidget) + self.spe_glo.setContentsMargins(0, 0, 0, 0) + self.spe_glo.setObjectName("spe_glo") + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QtWidgets.QWidget() + self.tab_2.setObjectName("tab_2") + self.gridLayoutWidget_2 = QtWidgets.QWidget(self.tab_2) + self.gridLayoutWidget_2.setGeometry(QtCore.QRect(-1, -1, 581, 411)) + self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2") + self.align_glo = QtWidgets.QGridLayout(self.gridLayoutWidget_2) + self.align_glo.setContentsMargins(0, 0, 0, 0) + self.align_glo.setObjectName("align_glo") + self.tabWidget.addTab(self.tab_2, "") + self.layoutWidget = QtWidgets.QWidget(spectral_Window) + self.layoutWidget.setGeometry(QtCore.QRect(610, 90, 195, 135)) + self.layoutWidget.setObjectName("layoutWidget") + self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.align_bt = QtWidgets.QPushButton(self.layoutWidget) + self.align_bt.setObjectName("align_bt") + self.gridLayout.addWidget(self.align_bt, 0, 0, 1, 1) + self.stop_align_bt = QtWidgets.QPushButton(self.layoutWidget) + self.stop_align_bt.setObjectName("stop_align_bt") + self.gridLayout.addWidget(self.stop_align_bt, 0, 1, 1, 1) + self.wb_bt = QtWidgets.QPushButton(self.layoutWidget) + self.wb_bt.setObjectName("wb_bt") + self.gridLayout.addWidget(self.wb_bt, 1, 0, 1, 2) + self.dc_bt = QtWidgets.QPushButton(self.layoutWidget) + self.dc_bt.setObjectName("dc_bt") + self.gridLayout.addWidget(self.dc_bt, 2, 0, 1, 2) + self.record_bt = QtWidgets.QPushButton(self.layoutWidget) + self.record_bt.setObjectName("record_bt") + self.gridLayout.addWidget(self.record_bt, 3, 0, 1, 2) + + self.retranslateUi(spectral_Window) + self.tabWidget.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(spectral_Window) + + def retranslateUi(self, spectral_Window): + _translate = QtCore.QCoreApplication.translate + spectral_Window.setWindowTitle(_translate("spectral_Window", "光谱窗口")) + self.label.setText(_translate("spectral_Window", "保存路径")) + self.label_2.setText(_translate("spectral_Window", "文件名")) + self.filepath_bt.setText(_translate("spectral_Window", "浏览")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("spectral_Window", "spe")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("spectral_Window", "align")) + self.align_bt.setText(_translate("spectral_Window", "align")) + self.stop_align_bt.setText(_translate("spectral_Window", "stop align")) + self.wb_bt.setText(_translate("spectral_Window", "曝光/白板")) + self.dc_bt.setText(_translate("spectral_Window", "暗电流")) + self.record_bt.setText(_translate("spectral_Window", "采集")) diff --git a/record_system_v21/spectral_Window.ui b/record_system_v21/spectral_Window.ui new file mode 100644 index 0000000..f2641b7 --- /dev/null +++ b/record_system_v21/spectral_Window.ui @@ -0,0 +1,180 @@ + + + spectral_Window + + + + 0 + 0 + 792 + 523 + + + + 光谱窗口 + + + + + 54 + 10 + 51 + 20 + + + + 保存路径 + + + + + + 131 + 10 + 261 + 21 + + + + + + + 54 + 40 + 41 + 20 + + + + 文件名 + + + + + + 131 + 40 + 261 + 21 + + + + + + + 401 + 10 + 71 + 21 + + + + 浏览 + + + + + + 611 + 210 + 161 + 301 + + + + + + + 10 + 70 + 591 + 441 + + + + 0 + + + + spe + + + + + 0 + 0 + 581 + 411 + + + + + + + + align + + + + + -1 + -1 + 581 + 411 + + + + + + + + + + 610 + 90 + 195 + 135 + + + + + + + align + + + + + + + stop align + + + + + + + 曝光/白板 + + + + + + + 暗电流 + + + + + + + 采集 + + + + + + + + + diff --git a/record_system_v22/2record_system_v2.2.py b/record_system_v22/2record_system_v2.2.py new file mode 100644 index 0000000..87f3eaf --- /dev/null +++ b/record_system_v22/2record_system_v2.2.py @@ -0,0 +1,1203 @@ +''' +在2record system_v2.1的基础上新增功能: +1、使用多线程采集数据,解决数据采集过程中界面卡死的情况 +2、实现了自动曝光 +3、实现了arcus马达控制 +4、通过共享变量来实现影像边采集边刷新 +''' + +from ximea import xiapi +import numpy as np +import os, sys, functools, re, shutil, traceback +import subprocess + + +import datetime # 几种Python执行时间的计算方法:https://blog.csdn.net/wangshuang1631/article/details/54286551 +from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, qApp, QDialog, QFileDialog +# from PyQt5.QtCore import pyqtSignal, QObject, QRunnable, QThreadPool +from PyQt5.QtCore import * +from enter_window import * +from image_Window import * +from spectral_Window import * +from arcus_control_ui import * + +import cv2 +import matplotlib +matplotlib.use("Qt5Agg") # 声明使用QT5 +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.figure import Figure +import matplotlib.pyplot as plt + + + +class ArcusWindow(QMainWindow, Ui_arcus_ui): + def __init__(self, parent=None): + super(ArcusWindow, self).__init__(parent) + self.setupUi(self) + + self.left_btn.pressed.connect(self.leftMove) + self.left_btn.released.connect(self.stop) + self.right_btn.pressed.connect(self.rightMove) + self.right_btn.released.connect(self.stop) + + + # self.speed_lineEdit.setText(self.arc.write('HSPD')) + self.speed_lineEdit.textEdited.connect(self.change_speed) + + + def leftMove(self): + python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J-' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('左移ok!') + + def rightMove(self): + python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J+' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + print(output) + # print(error) + print('右移ok!') + + def change_speed(self): + python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py HSPD=' + str(self.speed_lineEdit.text()) + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('改变速度ok!') + + def stop(self): + python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py STOP' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('停止ok!') + + +#EnterWindow +# 主窗口 +class EnterWindow(QMainWindow, Ui_enter_Window): + def __init__(self, parent=None): + super(EnterWindow, self).__init__(parent) + self.setupUi(self) + + # 在刚打开软件在本窗口显示相机状态(是否打开) + self.c = Communicate() + self.c.openinfo.connect(self.printCamInfo) + # self.end_Btn.clicked.connect(self.end_event) # 绑定登陆函数 + # self.exit_Btn.clicked.connect(sys.exit) + + def printCamInfo(self): + self.camstatus_tb.append('相机已打开!') + +# 主窗口信号类 +class Communicate(QObject): + openinfo = pyqtSignal() + plotsignal = pyqtSignal() + + +#ImageWindow +# 图像窗口 +class ImageWindow(QDialog, Ui_image_Window): + def __init__(self, parent=None): + ''' + The super().__init__() method invokes the base class constructor from the MyForm class, + that is, the constructor of the QDialog class is invoked from MyForm class to indicate that + QDialog is displayed through this class iss a top-level window. + ''' + super(ImageWindow, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + + + + # 采集影像时,边采集边刷新显示 + # self.plotsignal = pyqtSignal() # 直接这样建立信号执行时会报错 + self.plotsignal = Communicate() + self.plotsignal.plotsignal.connect(self.plotimg) + + #建立进程池 + # https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + #初始化窗口中的值 + self.framenumber_le.setText(str(camera_operation.framenumber_input)) + self.framerate_le.setText(str(camera_operation.framerate_input)) + self.exposureTime_le.setText(str(camera_operation.exposureTime_input)) + self.gain_le.setText(str(camera_operation.gain_input)) + self.filename_le.setText('test') + self.filepath_le.setText(os.getcwd()) + + + #手动改变窗口中的值,然后将值写入camera_operation类对应的变量中 + self.exposureTime_le.textEdited.connect(self.onchange2) + self.exposureTime_le.textChanged.connect(self.onchange)# 将 自动曝光返回到QLineEdit中的值 写入到camera_operation.exposureTime_input + self.gain_le.textEdited.connect(self.onchange2) + self.gain_le.textChanged.connect(self.onchange)# 将 自动曝光返回到QLineEdit中的值 写入到camera_operation.gain_input + self.framerate_le.textEdited.connect(self.onchange2) + self.filename_le.textEdited.connect(self.onchange) + self.filepath_bt.clicked.connect(self.directory_select) + self.framenumber_le.textEdited.connect(self.onchange) + self.filepath_le.textEdited.connect(self.onchange) + + # 显示影像和调焦 + self.myImageFigure = MyImageFigure() + self.image_glo.addWidget(self.myImageFigure) + self.myFocusFigure = MySpectralFigureFocus() + self.focus_glo.addWidget(self.myFocusFigure) + + #操作光谱仪 + ## 注释的代码没有使用多线程,所以会造成一采集数据界面就卡死的情况 + # self.focus_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.dc_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.save_bt.clicked.connect(camera_operation.savedata) + self.exposureTime_bt.clicked.connect(self.autoExposure) + self.focus_bt.clicked.connect(self.run) + # 停止调焦和采集操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.stop_focus_bt.clicked.connect(self.stop_focus) + self.stop_record_bt.clicked.connect(self.stop_record) + self.dc_bt.clicked.connect(self.run) + self.wb_bt.clicked.connect(self.run) + self.record_bt.clicked.connect(self.run) + self.save_bt.clicked.connect(self.save_image) + + def plotimg(self): + worker = Worker(camera_operation.plotimg) + self.threadpool.start(worker) + + def stop_focus(self): + camera_operation.focus = False + + def stop_record(self): + camera_operation.record = False + + # 调焦、采集暗电流、采集白板、采集影像 都通过此函数 + def run(self): + qt_sender = self.sender().objectName() + + # 操作状态显示 + if qt_sender == 'focus_bt': + self.statu_tb.append('调焦...') + elif qt_sender == 'dc_bt': + self.statu_tb.append('采集暗电流...') + elif qt_sender == 'wb_bt': + self.statu_tb.append('采集白板...') + elif qt_sender == 'record_bt': + self.statu_tb.append('采集影像...') + + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(camera_operation.start_AcquireData, camera, qt_sender) + self.threadpool.start(worker) + + # 操作状态显示 + 为相机设置exposure和gain + if qt_sender == 'focus_bt': + worker.signals.finished.connect(lambda: self.statu_tb.append('调焦成功!')) + elif qt_sender == 'dc_bt': + worker.signals.finished.connect(lambda: self.statu_tb.append('采集暗电流成功!')) + elif qt_sender == 'wb_bt': + worker.signals.finished.connect(lambda: self.statu_tb.append('采集白板成功!')) + elif qt_sender == 'record_bt': + worker.signals.finished.connect(lambda: self.statu_tb.append('采集影像成功!')) + + # 获取曝光参数:exposure和gain;并将值返回显示到界面中对应的QLineEdit中 + def autoExposure(self): + qt_sender = self.sender().objectName() + self.statu_tb.append('自动曝光...') + worker = Worker(camera_operation.start_AcquireData, camera, qt_sender) + # 曝光参数的设置过程: + # (1)曝光参数返回到界面中的QLineEdit; + # (2)通过QLineEdit的textChanged事件将值写入到camera_operation对应的变量; + # (3)为相机设置参数:1)通过worker的finished信号【本程序使用】2)也可以通过QLineEdit的textChanged事件调用self.set_exposure函数,为相机设置参数 + # 这种过程的好处是界面显示的曝光参数和实际设置的是同步的 + worker.signals.result.connect(self.changeTXT_QLineEdit) + worker.signals.finished.connect(self.set_exposure) #也可以通过QLineEdit的textChanged事件调用self.set_exposure函数,为相机设置参数 + + self.threadpool.start(worker) + + # 将自动曝光返回值写入到界面中的QLineEdit + def changeTXT_QLineEdit(self, result): + self.exposureTime_le.setText(str(result[0])) + self.gain_le.setText(str(result[1])) + if result[2] == 1: + QMessageBox.information(self, '曝光提示', '光线不足,曝光时间已设置为最大!', QMessageBox.Yes) + camera_operation.autoexposure_feedback = 0 + + # 设置曝光参数:exposure和gain + def set_exposure(self): + self.statu_tb.append('自动曝光成功!') + camera_operation.set_exposureTime(camera) + + def save_image(self): + # 操作状态显示 + self.statu_tb.append('保存影像...') + + worker = Worker(camera_operation.savedata) + self.threadpool.start(worker) + + # 操作状态显示 + worker.signals.finished.connect(lambda: self.statu_tb.append('保存影像成功!')) + + # (textChanged)将 自动曝光返回到QLineEdit中的值 写入camera_operation类对应的变量中 + def onchange(self): + camera_operation.framenumber_input = self.framenumber_le.text() + camera_operation.fn = self.filename_le.text() + camera_operation.fp = self.filepath_le.text() + camera_operation.rgb = np.ones((3, int(camera_operation.framenumber_input), int( + (camera_operation.endColumn - camera_operation.startColumn) / camera_operation.bin_spatial))) + + # 这两个不是手动改变,是自动曝光返回的值 + camera_operation.gain_input = self.gain_le.text() + camera_operation.exposureTime_input = self.exposureTime_le.text() + + # 手动修改(textEdited)界面中的值后,为相机重新设置如下参数:exposure, gain, framerate + def onchange2(self): + camera_operation.gain_input = self.gain_le.text() + camera_operation.exposureTime_input = self.exposureTime_le.text() + camera_operation.framerate_input = self.framerate_le.text() + camera_operation.set_exposureTime(camera) + + def directory_select(self): + dirpath = QFileDialog.getExistingDirectory(self, '选择存储路径文件夹', '/home') + + # 当在文件夹选择窗口中点击取消时,不重设路径 + if dirpath != '': + self.filepath_le.setText(dirpath) + camera_operation.fp = dirpath + +#SpectralWindow +# 光谱窗口 +class SpectralWindow(QDialog, Ui_spectral_Window): + def __init__(self, parent=None): + super(SpectralWindow, self).__init__(parent) + self.setupUi(self) + + # 建立进程池 + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 初始化值 + self.filename_le.setText('test') + self.filepath_le.setText(os.getcwd()) + + #手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + self.filepath_bt.clicked.connect(self.directory_select) + self.filename_le.textEdited.connect(self.onchange) + self.filepath_le.textEdited.connect(self.onchange) + + + # 显示光谱和align + self.spectralFigure = MySpectralFigureSpectral() + self.spe_glo.addWidget(self.spectralFigure) + self.alignFigure = MyImageFigure() + self.align_glo.addWidget(self.alignFigure) + + #操作光谱仪 + # self.dc_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + self.wb_bt.clicked.connect(self.run) # 曝光 + 采集白板 + self.align_bt.clicked.connect(self.run) + self.stop_align_bt.clicked.connect(self.stop_align) # 这个操作非常简单,耗时非常短,瞬间可回到event loop;所以不需要多线程 + self.dc_bt.clicked.connect(self.run) + self.record_bt.clicked.connect(self.run) + + def stop_align(self): + spectral_camera_operation.align = False + + def run(self): + qt_sender = self.sender().objectName() + + # 操作状态显示 + if qt_sender == 'wb_bt': + self.statu_tb.append('曝光/白板...') + elif qt_sender == 'align_bt': + self.statu_tb.append('align...') + elif qt_sender == 'dc_bt': + self.statu_tb.append('采集暗电流...') + elif qt_sender == 'wb_bt': + self.statu_tb.append('采集白板...') + elif qt_sender == 'record_bt': + self.statu_tb.append('采集光谱...') + + + worker = Worker(spectral_camera_operation.start_AcquireData, camera, qt_sender) + self.threadpool.start(worker) + + + # 操作状态显示 + if qt_sender == 'wb_bt': + worker.signals.finished.connect(lambda: self.statu_tb.append('曝光/白板成功!')) + elif qt_sender == 'align_bt': + worker.signals.finished.connect(lambda: self.statu_tb.append('align successfully!')) + elif qt_sender == 'dc_bt': + worker.signals.finished.connect(lambda: self.statu_tb.append('采集暗电流成功!')) + elif qt_sender == 'wb_bt': + worker.signals.finished.connect(lambda: self.statu_tb.append('采集白板成功!')) + elif qt_sender == 'record_bt': + worker.signals.finished.connect(lambda: self.statu_tb.append('采集光谱成功!')) + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + def onchange(self): + spectral_camera_operation.fn = self.filename_le.text() + spectral_camera_operation.fp = self.filepath_le.text() + + def directory_select(self): + dirpath = QFileDialog.getExistingDirectory(self, '选择存储路径文件夹', '/home') + + # 当在文件夹选择窗口中点击取消时,不重设路径 + if dirpath != '': + self.filepath_le.setText(dirpath) + spectral_camera_operation.fp = dirpath + + +#MySpectralFigureFocus +# 画图类,用于:画出采集到的光谱;调焦(影响模式调焦) +class MySpectralFigureFocus(FigureCanvas): + def __init__(self, width=5, height=4, dpi=100): + #第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + + #第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MySpectralFigureFocus, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + + #第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + self.axes.set_xlabel('Wavelength (nm)') + #第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def plot(self, spectral): + self.axes.clear() + self.axes.plot(spectral) + + +#MySpectralFigureSpectral +class MySpectralFigureSpectral(FigureCanvas): + def __init__(self, width=5, height=4, dpi=100): + # 第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + + # 第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MySpectralFigureSpectral, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + + # 第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + self.axes.set_xlabel('Wavelength (nm)') + self.axes + #第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def plot(self, Wavelength, spectral): + self.axes.clear() + self.axes.plot(Wavelength, spectral) + +# 画图类,用于:画出采集到的图像;显示帧流(光谱模式对准光纤) +class MyImageFigure(FigureCanvas): + def __init__(self, width=5, height=4, dpi=100): + # 第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + # 第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MyImageFigure, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + # 第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + self.axes.set_xticks([]) + self.axes.set_yticks([]) + # 第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def plot(self, frame): + self.axes.clear() + self.axes.set_xticks([]) + self.axes.set_yticks([]) + self.axes.imshow(frame) + +class WorkerSignals(QObject): + ''' + Defines the signals available from a running worker thread. + + Supported signals are: + + finished + No data + + error + `tuple` (exctype, value, traceback.format_exc() ) + + result + `object` data returned from processing, anything + + progress + `int` indicating % progress + + ''' + finished = pyqtSignal() + error = pyqtSignal(tuple) + result = pyqtSignal(object) + progress = pyqtSignal(int) + +# https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ +# 用于qt多线程:运行long-time task +class Worker(QRunnable): + ''' + Worker thread + + Inherits from QRunnable to handler worker thread setup, signals and wrap-up. + + :param callback: The function callback to run on this worker thread. Supplied args and + kwargs will be passed through to the runner. + :type callback: function + :param args: Arguments to pass to the callback function + :param kwargs: Keywords to pass to the callback function + + ''' + + def __init__(self, fn, *args, **kwargs): + super(Worker, self).__init__() + + # Store constructor arguments (re-used for processing) + self.fn = fn + self.args = args + self.kwargs = kwargs + self.signals = WorkerSignals() + + # Add the callback to our kwargs + # self.kwargs['progress_callback'] = self.signals.progress + + @pyqtSlot() + def run(self): + ''' + Initialise the runner function with passed args, kwargs. + ''' + + # Retrieve args/kwargs here; and fire processing using them + + try: + result = self.fn(*self.args, **self.kwargs) + except: + traceback.print_exc() + exctype, value = sys.exc_info()[:2] + self.signals.error.emit((exctype, value, traceback.format_exc())) + else: + self.signals.result.emit(result) # Return the result of the processing + finally: + self.signals.finished.emit() # Done + +# 影像模式类:相关的函数和变量 +class camera_operation(object): + + # 传感器有效范围 + # startRow = 339 + # endRow = 639 + # startColumn = 285 + # endColumn = 1650 + # 影像中400-560列:685-845 + startRow = 339 + endRow = 639 + startColumn = 285 + endColumn = 1649 + + # 设置曝光时间和帧率 + framerate_input = 10 #随便给个初始值(初始值要和framerate_le控件初始值一致),从image_window获取的手动输入的帧率 + exposureTime_input = 18 + gain_input = 0 + + @classmethod + def autoexposure(cls, cam, img): + cam.set_framerate(cls.framerate_input) + + + @classmethod + # 手动改变界面上的曝光值和gain值后,设置相机的曝光值和gain值所用 + def set_exposureTime(cls, cam): + # settings,cam.set_param("exposure",10000) + cam.set_framerate(int(cls.framerate_input)) + cam.set_exposure(int(cls.exposureTime_input)) # 曝光时间单位为微秒,1s共有1000000微秒 + cam.set_gain(int(float(cls.gain_input))) #int('0.0')会报错,int(float('0.0'))不会报错 + # print('Exposure was set to %i us' % cam.get_exposure()) + # print('Framerate was set to %i FPS' % cam.get_framerate()) + # ('Framerate: ' + str(cam.get_framerate()) + ' FPS')这样连接字符串会浪费内存 + image_window_instance.statu_tb.append("%s%s%s" % ('Framerate: ', str(cam.get_framerate()), ' FPS')) + image_window_instance.statu_tb.append("%s%s%s" % ('Exposure: ', str(cam.get_exposure()), ' us')) + image_window_instance.statu_tb.append("%s%s%s" % ('Gain: ', str(cam.get_gain()), ' dB')) + + + # 开始采集数据 + framenumber_input = 100 # 随便给个初始值(初始值要和framenumber_le控件初始值一致),从image_window获取的手动输入的帧数 + image_dc = 1 # 随便给个初始值,此变量用于存储采集到的暗电流影像 + image_wb = 1 # 随便给个初始值,此变量用于存储采集到的白板影像 + focus = True # 用于停止调焦 + record = True # 用于停止采集 + img_datatype = 12 # 在头文件中确定影像数据类型 + # bin相关设置 + bin_spectral = 1 # 光谱bin + bin_spatial = 1 # 空间bin + k = np.arange(endRow - startRow)[0::bin_spectral] + l = np.arange(endColumn - startColumn)[0::bin_spatial] + + rgb = np.zeros((3, int(framenumber_input), int((endColumn - startColumn) / bin_spatial))) + + autoexposure_feedback = 0 + @classmethod + def start_AcquireData(cls, cam, qt_sender): # qt_sender是指qt窗口中事件的发生者 + # 创建img = xiapi.Image()前需要设置一系列img参数,例如:格式、位深度、 + # 如果格式设置为XI_RAW8,image_raw_numpy.dtype -> dtype('uint8'), uint8 + # 如果格式设置为XI_RAW16,image_raw_numpy.dtype -> dtype(' int(1 / int(cls.framerate_input) * 10**6): + cam.set_exposure(int(1 / int(cls.framerate_input) * 10**6)) + cls.autoexposure_feedback = 1 + + else: + cam.set_exposure(cam.get_exposure()) + + + print('Framerate was set to %i FPS' % cam.get_framerate()) + print('Exposure was set to %i us' % cam.get_exposure()) + print('Gain was set to %i dB' % cam.get_gain()) + + # 如果点击“调焦”按钮 + if qt_sender == 'focus_bt': + # cls.set_exposureTime(cam) + + # 当关闭调焦后,再次打开调焦功能需要将cls.focus的值从False变为True + if not cls.focus: + cls.focus = True + + cam.start_acquisition() + + while cls.focus: + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + image_window_instance.myImageFigure.plot(image_container) + image_window_instance.myImageFigure.draw() + image_window_instance.myFocusFigure.plot(image_container[150, :]) + image_window_instance.myFocusFigure.draw() + + # 如果点击“白板”按钮,采集并保存白板影像到image_wb + if qt_sender == 'wb_bt': + framenumber = 10 + image_container = np.empty((cls.endRow - cls.startRow, framenumber, cls.endColumn - cls.startColumn)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + image_container = image_container.mean(axis=1) + + # 光谱bin和空间bin + if cls.bin_spectral != 1: + image_container_bin_spectral = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), cls.endColumn - cls.startColumn)) + image_container_bin = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), + int((cls.endColumn - cls.startColumn) / cls.bin_spatial))) + + for i in range(image_container_bin_spectral.shape[0]): + for j in range(cls.bin_spectral): + image_container_bin_spectral[i] += image_container[cls.k[i] + j] + # 光谱bin完成后,进行空间bin + for i in range(image_container_bin.shape[1]): + for j in range(cls.bin_spatial): + image_container_bin[:, i] += image_container_bin_spectral[:, cls.l[i] + j] + else: + image_container_bin = image_container + + cls.image_wb = image_container_bin + + # 如果点击“暗电流”按钮,采集并保存暗电流影像到image_dc + if qt_sender == 'dc_bt': + framenumber = 10 + image_container = np.empty((cls.endRow - cls.startRow, framenumber, cls.endColumn - cls.startColumn)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + image_container = image_container.mean(axis=1) + + # 光谱bin和空间bin + if cls.bin_spectral != 1: + image_container_bin_spectral = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), cls.endColumn - cls.startColumn)) + image_container_bin = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), + int((cls.endColumn - cls.startColumn) / cls.bin_spatial))) + + for i in range(image_container_bin_spectral.shape[0]): + for j in range(cls.bin_spectral): + image_container_bin_spectral[i] += image_container[cls.k[i] + j] + # 光谱bin完成后,进行空间bin + for i in range(image_container_bin.shape[1]): + for j in range(cls.bin_spatial): + image_container_bin[:, i] += image_container_bin_spectral[:, cls.l[i] + j] + else: + image_container_bin = image_container + + cls.image_dc = image_container_bin + + # 如果点击“采集”按钮,自动去除暗电流,并且转化成反射率 + if qt_sender == 'record_bt': + frameCount = 1 # 统计采集的帧数,用于停止采集使用 + + # 当停止采集后,再次开始采集需要将cls.record的值从False变为True + if not cls.record: + cls.record = True + + # 开始马达 + try: + python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR PX=0 EO=1 J+' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + except: + pass + + + # 开始采集数据 并且 将数据写入到硬盘中 + cam.start_acquisition() + with open('corning410_test', 'wb') as f: + + print('Starting data acquisition...') + startTime = datetime.datetime.now() + + while cls.record: + cam.get_image(img) # get data and pass them from camera to img + # image_raw_numpy.dtype -> dtype(' maxout] = maxout + img_out = np.uint8(img_new) + return img_out + else: # 对于彩色照片,需要先单独对每个波段拉伸 + img_new = np.empty(img.shape) + for i in range(img.shape[2]): + low = np.percentile(img[:, :, i], lowPercentile) + up = np.percentile(img[:, :, i], highPercentile) + + img_new[:, :, i] = minout + ((img[:, :, i] - low) / (up - low)) * (maxout - minout) + img_new[:, :, i][img_new[:, :, i] < minout] = minout + img_new[:, :, i][img_new[:, :, i] > maxout] = maxout + img_out = np.uint8(img_new) + return img_out + + @classmethod + def close_camera(cls, cam): + # stop communication + cam.close_device() + + +# 光谱模式类:相关的函数和变量 +class spectral_camera_operation(object): + + # 传感器有效范围 + # startRow = 339 + # endRow = 639 + # startColumn = 285 + # endColumn = 1650 + # 影像中400-560列:685-845 + startRow = 339 + endRow = 639 + startColumn = 285 + endColumn = 1650 + + # 开始采集数据 + fp = os.getcwd() # 随便给个初始值(初始值要和filepath_le控件初始值一致),从spectral_window获取的手动输入的帧率 + fn = 'test' # 随便给个初始值(初始值要和filename_le控件初始值一致),从spectral_window获取的手动输入的帧率 + + framenumber = 10 # 每条光谱为多少帧平均得到 + spectral_container = np.empty((endRow - startRow, framenumber, endColumn - startColumn)).astype(np.float) + # spectral_container = np.empty((300, framenumber, 3)).astype(np.float64) + + align = True # 用于对准光纤 + image_dc = np.empty((endRow - startRow, endColumn - startColumn)) # 此变量用于存储采集到的暗电流,一帧 + spectralNumber_wb = 1 # 每次采集的白板的光谱数 + spectral_wb = np.empty((endRow - startRow, endColumn - startColumn)) # 此变量用于存储采集到的白板,一帧 + spectral_wb_tmp = np.empty((endRow - startRow, framenumber, endColumn - startColumn)).astype( + np.float64) # 随便给个初始值,此变量用于存储采集到的白板影像,后面白板影像去除了暗电流后值赋给spectral_wb + spectralNumber = 10 # 每次采集目标物的光谱数 + spectral = np.empty((endRow - startRow, spectralNumber)).astype(np.float) # 此ndarray用于存储采集到的目标物光谱,每一列为一个光谱 + + @classmethod + def start_AcquireData(cls, cam, qt_sender): + # 创建img = xiapi.Image()前需要设置一系列img参数,例如:格式、位深度、 + cam.set_imgdataformat('XI_RAW16') + # create instance of Image to store image data and metadata + img = xiapi.Image() + + print('Starting data acquisition...') + starttime = datetime.datetime.now() + + + # 如果点击“曝光/白板”按钮:(1)先自动曝光;(2)然后在采集白板 + if qt_sender == 'wb_bt': + + # 自动曝光 + cam.set_framerate(15) + cam.set_aeag_roi_offset_x(cls.startColumn) + cam.set_aeag_roi_offset_y(cls.startRow) + cam.set_aeag_roi_height(cls.endRow - cls.startRow) + cam.set_aeag_roi_width(cls.endColumn - cls.startColumn) + # cam.set_exp_priority(1) # Exposure priority (0.8 - exposure 80%, gain 20%).XI_PRM_EXP_PRIORITY + # cam.set_ae_max_limit(24000) # Maximum time (us) used for exposure in AEAG procedureXI_PRM_AE_MAX_LIMIT + # cam.set_ag_max_limit(12) + # cam.set_aeag_level(50) # Average intensity of output signal AEAG should achieve(in %)XI_PRM_AEAG_LEVEL + # 还有两个不知怎么用的参数:XI_PRM_GAIN_SELECTOR or "gain_selector"和XI_PRM_SHUTTER_TYPE or "shutter_type" + cam.enable_aeag() + cam.start_acquisition() + for i in range(10): + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + cam.disable_aeag() + + # 将自动曝光获得的exposure和gain写入到相机 + cam.set_framerate(15) + cam.set_exposure(cam.get_exposure()) + cam.set_gain(cam.get_gain()) + spectral_window_instance.statu_tb.append('Exposure: ' + str(cam.get_exposure()) + ' us') + spectral_window_instance.statu_tb.append('Framerate: ' + str(cam.get_framerate()) + ' FPS') + + print('Framerate was set to %i FPS' % cam.get_framerate()) + print('Exposure was set to %i us' % cam.get_exposure()) + print('Gain was set to %i dB' % cam.get_gain()) + + # 开始采集白板数据,去除白板暗电流的操作放在采集暗电流时进行 + cam.start_acquisition() + for j in range(cls.spectralNumber_wb): + for i in range(cls.framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + cls.spectral_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, + cls.startColumn:cls.endColumn] + + # 去除白板暗电流的操作放在采集暗电流时进行 + # cls.spectral_container没经过运算,传给cls.spectral_wb_tmp的是cls.spectral_container的内存地址 + cls.spectral_wb_tmp = cls.spectral_container + + # 存储原始白板影像 + filename = cls.fp + '\\' + 'baiban' + with open(filename, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_wb_tmp[:, i, :].flatten().tobytes()) + camera_operation.write_hdr(filename, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + + # 如果点击暗“align”按钮 + if qt_sender == 'align_bt': + + if not cls.align: + cls.align = True + + cam.start_acquisition() + while cls.align: + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + spectral_window_instance.alignFigure.plot(image_raw_numpy) + spectral_window_instance.alignFigure.draw() + + # 如果点击暗“暗电流”按钮 + if qt_sender == 'dc_bt': + # 为cls.spectral_container新建立一个内存地址,以免改变cls.spectral_wb_tmp(传址)的值 + cls.spectral_container = np.empty( + (cls.endRow - cls.startRow, cls.framenumber, cls.endColumn - cls.startColumn)).astype(np.float64) + cam.start_acquisition() + for i in range(cls.framenumber):#此循环为啥会改变649行的赋值的结果呢?怎么会执行那里的代码 + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + cls.spectral_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + + # 存储暗电流影像 + filename1 = cls.fp + '\\' + 'dark' + with open(filename1, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_container[:, i, :].flatten().tobytes()) + camera_operation.write_hdr(filename1, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + # cls.spectral_container经过运算,传给cls.image_dc的不是cls.spectral_container的内存地址,是新运算结果的内存地址;相当于传值 + cls.image_dc = cls.spectral_container.mean(axis=1) # 因为平均,cls.image_dc的数据类型为:dtype('float64') + + + + # 去除白板暗电流 + for i in range(cls.framenumber): + cls.spectral_wb_tmp[:, i, :] = cls.spectral_wb_tmp[:, i, :] - cls.image_dc + + + # 存储扣除暗电流的白板影像 + filename2 = cls.fp + '\\' + 'baiban_rmdark' + with open(filename2, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_wb_tmp[:, i, :].flatten().tobytes()) + camera_operation.write_hdr(filename2, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + cls.spectral_wb = cls.spectral_wb_tmp.mean(axis=1) # 因为平均,cls.spectral_wb的数据类型为:dtype('float64') + + + # 如果点击“采集”按钮,去除暗电流,转化成反射率, + if qt_sender == 'record_bt': + cam.start_acquisition() + for j in range(cls.spectralNumber): + for i in range(cls.framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + cls.spectral_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + # 存储扣除暗电流前的目标物影像 + if j == 1: + filename1 = cls.fp + '\\' + cls.fn + with open(filename1, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_container[:, i, :].flatten().tobytes()) + camera_operation.write_hdr(filename1, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + for i in range(cls.framenumber): # (1)去除暗电流;(2)转反射率 + cls.spectral_container[:, i, :] = (cls.spectral_container[:, i, :] - cls.image_dc) / cls.spectral_wb + + # 存储目标物反射率影像 + if j == 1: + filename2 = cls.fp + '\\' + cls.fn + '_ref' + with open(filename2, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_container[:, i, :].flatten().tobytes()) + camera_operation.write_hdr(filename2, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + # spectral_tmp = cls.spectral_container.sum(axis=1).sum(axis=1) + spectral_tmp = cls.spectral_container.mean(axis=1).mean(axis=1) + + cls.spectral[:, j] = spectral_tmp + + + # 画出光谱 + def calculate_wavelength(x): + wavelength = x * 1.999564 - 279.893 + return wavelength + wavelength = np.empty(cls.endRow - cls.startRow) + for i in range(cls.startRow, cls.endRow): + wavelength[i - cls.startRow] = calculate_wavelength(i) + spectral_window_instance.spectralFigure.plot(wavelength, spectral_tmp) + spectral_window_instance.spectralFigure.draw() + + + # 计算波长 + def calculate_wavelength(x): + wavelength = x * 1.999564 - 279.893 + return wavelength + wavelength = np.empty(cls.endRow - cls.startRow) + for i in range(cls.startRow, cls.endRow): + wavelength[i - cls.startRow] = calculate_wavelength(i) + # 保存光谱为txt文件 + cls.spectral = np.insert(cls.spectral, 0, wavelength, axis=1) + for i in range(cls.spectralNumber): + np.savetxt(cls.fp + '\\' + cls.fn + str(i) + '.txt', cls.spectral[:, [0, i + 1]], fmt='%f') + + + endtime = datetime.datetime.now() + print('光谱采集用时:%d' % (endtime - starttime).seconds) + + # stop data acquisition + print('Stopping acquisition...') + cam.stop_acquisition() + + @classmethod + def close_camera(cls, cam): + # stop communication + cam.close_device() + + +# 打开相机 +def open_camera(): + # create instance for first connected camera + cam = xiapi.Camera() + + # start communication to open specific device, use: cam.open_device_by_SN('41305651') + print('Opening first camera...') + cam.open_device() + + # 打开相机后,显示相机信息 + print('SN: %s' % str(cam.get_device_sn(), encoding="utf-8")) + print('Device name: %s' % str(cam.get_device_name(), encoding="utf-8")) + print('Device name: %s' % str(cam.get_device_type(), encoding="utf-8")) + print('Instance path: %s' % str(cam.get_device_inst_path(), + encoding="utf-8")) # Returns device instance path in operating system. + print('Location path: %s' % str(cam.get_device_loc_path(), encoding="utf-8")) + + print('Debug level: %s' % cam.get_debug_level()) + print('Default number of threads per image processor: %d' % cam.get_proc_num_threads()) + cam.set_proc_num_threads(8) + print('Current number of threads per image processor: %d' % cam.get_proc_num_threads()) + print('Is horizontal flip enabled?, %s' % str(cam.is_horizontal_flip())) + print() + + # This mode is supported by selected camera families: CB, MC, MT, MX + cam.set_acq_timing_mode('XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + mode_used = cam.get_acq_timing_mode() + if mode_used == 'XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT': + print('Mode is XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + else: + print('Mode is not XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + sys.exit() + + return cam + + +if __name__ == '__main__': + app = QApplication(sys.argv) + camera = open_camera() + + + #实例化4个窗口 + enter_window_instance = EnterWindow() + image_window_instance = ImageWindow() + image_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + spectral_window_instance = SpectralWindow() + spectral_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + + arcus_window_instance = ArcusWindow() + + enter_window_instance.c.openinfo.emit() + + + #从主窗口弹出影像窗口和光谱窗口 + enter_window_instance.image_mode_bt.clicked.connect(image_window_instance.show) + enter_window_instance.spectral_mode_bt.clicked.connect(spectral_window_instance.show) + image_window_instance.motor_bt.clicked.connect(arcus_window_instance.show) + + + enter_window_instance.show() + sys.exit(app.exec_()) diff --git a/record_system_v22/arcus_control_ui.py b/record_system_v22/arcus_control_ui.py new file mode 100644 index 0000000..640777f --- /dev/null +++ b/record_system_v22/arcus_control_ui.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'arcus_control_ui.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_arcus_ui(object): + def setupUi(self, arcus_ui): + arcus_ui.setObjectName("arcus_ui") + arcus_ui.resize(354, 171) + self.centralwidget = QtWidgets.QWidget(arcus_ui) + self.centralwidget.setObjectName("centralwidget") + self.left_btn = QtWidgets.QPushButton(self.centralwidget) + self.left_btn.setGeometry(QtCore.QRect(100, 90, 61, 21)) + self.left_btn.setObjectName("left_btn") + self.right_btn = QtWidgets.QPushButton(self.centralwidget) + self.right_btn.setGeometry(QtCore.QRect(170, 90, 61, 23)) + self.right_btn.setObjectName("right_btn") + self.speed_lineEdit = QtWidgets.QLineEdit(self.centralwidget) + self.speed_lineEdit.setGeometry(QtCore.QRect(101, 10, 131, 20)) + self.speed_lineEdit.setObjectName("speed_lineEdit") + self.speed_ScrollBar = QtWidgets.QScrollBar(self.centralwidget) + self.speed_ScrollBar.setGeometry(QtCore.QRect(100, 40, 131, 20)) + self.speed_ScrollBar.setOrientation(QtCore.Qt.Horizontal) + self.speed_ScrollBar.setObjectName("speed_ScrollBar") + arcus_ui.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(arcus_ui) + self.menubar.setGeometry(QtCore.QRect(0, 0, 354, 23)) + self.menubar.setObjectName("menubar") + arcus_ui.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(arcus_ui) + self.statusbar.setObjectName("statusbar") + arcus_ui.setStatusBar(self.statusbar) + + self.retranslateUi(arcus_ui) + QtCore.QMetaObject.connectSlotsByName(arcus_ui) + + def retranslateUi(self, arcus_ui): + _translate = QtCore.QCoreApplication.translate + arcus_ui.setWindowTitle(_translate("arcus_ui", "MainWindow")) + self.left_btn.setText(_translate("arcus_ui", "左")) + self.right_btn.setText(_translate("arcus_ui", "右")) diff --git a/record_system_v22/arcus_control_ui.ui b/record_system_v22/arcus_control_ui.ui new file mode 100644 index 0000000..b494281 --- /dev/null +++ b/record_system_v22/arcus_control_ui.ui @@ -0,0 +1,81 @@ + + + arcus_ui + + + + 0 + 0 + 354 + 171 + + + + MainWindow + + + + + + 100 + 90 + 61 + 21 + + + + + + + + + + 170 + 90 + 61 + 23 + + + + + + + + + + 101 + 10 + 131 + 20 + + + + + + + 100 + 40 + 131 + 20 + + + + Qt::Horizontal + + + + + + + 0 + 0 + 354 + 23 + + + + + + + + diff --git a/record_system_v22/enter_window.py b/record_system_v22/enter_window.py new file mode 100644 index 0000000..9f5f1cd --- /dev/null +++ b/record_system_v22/enter_window.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'enter_window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_enter_Window(object): + def setupUi(self, enter_Window): + enter_Window.setObjectName("enter_Window") + enter_Window.resize(651, 474) + self.centralwidget = QtWidgets.QWidget(enter_Window) + self.centralwidget.setObjectName("centralwidget") + self.image_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.image_mode_bt.setGeometry(QtCore.QRect(200, 180, 111, 51)) + self.image_mode_bt.setObjectName("image_mode_bt") + self.spectral_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.spectral_mode_bt.setGeometry(QtCore.QRect(360, 180, 111, 51)) + self.spectral_mode_bt.setObjectName("spectral_mode_bt") + self.camstatus_tb = QtWidgets.QTextBrowser(self.centralwidget) + self.camstatus_tb.setGeometry(QtCore.QRect(200, 240, 271, 81)) + self.camstatus_tb.setObjectName("camstatus_tb") + enter_Window.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(enter_Window) + self.menubar.setGeometry(QtCore.QRect(0, 0, 651, 26)) + self.menubar.setObjectName("menubar") + enter_Window.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(enter_Window) + self.statusbar.setObjectName("statusbar") + enter_Window.setStatusBar(self.statusbar) + self.actionwew_e = QtWidgets.QAction(enter_Window) + self.actionwew_e.setObjectName("actionwew_e") + + self.retranslateUi(enter_Window) + QtCore.QMetaObject.connectSlotsByName(enter_Window) + + def retranslateUi(self, enter_Window): + _translate = QtCore.QCoreApplication.translate + enter_Window.setWindowTitle(_translate("enter_Window", "主窗口")) + self.image_mode_bt.setText(_translate("enter_Window", "影像模式")) + self.spectral_mode_bt.setText(_translate("enter_Window", "光谱模式")) + self.actionwew_e.setText(_translate("enter_Window", "wew e")) diff --git a/record_system_v22/enter_window.ui b/record_system_v22/enter_window.ui new file mode 100644 index 0000000..4c39418 --- /dev/null +++ b/record_system_v22/enter_window.ui @@ -0,0 +1,73 @@ + + + enter_Window + + + + 0 + 0 + 651 + 474 + + + + 主窗口 + + + + + + 200 + 180 + 111 + 51 + + + + 影像模式 + + + + + + 360 + 180 + 111 + 51 + + + + 光谱模式 + + + + + + 200 + 240 + 271 + 81 + + + + + + + + 0 + 0 + 651 + 26 + + + + + + + wew e + + + + + + diff --git a/record_system_v22/image_Window.py b/record_system_v22/image_Window.py new file mode 100644 index 0000000..53dc349 --- /dev/null +++ b/record_system_v22/image_Window.py @@ -0,0 +1,231 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'image_Window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_image_Window(object): + def setupUi(self, image_Window): + image_Window.setObjectName("image_Window") + image_Window.setEnabled(True) + image_Window.resize(1181, 683) + image_Window.setMouseTracking(False) + image_Window.setAutoFillBackground(False) + image_Window.setSizeGripEnabled(False) + image_Window.setModal(False) + self.verticalLayout_7 = QtWidgets.QVBoxLayout(image_Window) + self.verticalLayout_7.setObjectName("verticalLayout_7") + self.groupBox_5 = QtWidgets.QGroupBox(image_Window) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth()) + self.groupBox_5.setSizePolicy(sizePolicy) + self.groupBox_5.setObjectName("groupBox_5") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox_5) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem) + self.splitter_3 = QtWidgets.QSplitter(self.groupBox_5) + self.splitter_3.setOrientation(QtCore.Qt.Horizontal) + self.splitter_3.setObjectName("splitter_3") + self.layoutWidget = QtWidgets.QWidget(self.splitter_3) + self.layoutWidget.setObjectName("layoutWidget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.label = QtWidgets.QLabel(self.layoutWidget) + self.label.setObjectName("label") + self.verticalLayout.addWidget(self.label) + self.label_4 = QtWidgets.QLabel(self.layoutWidget) + self.label_4.setObjectName("label_4") + self.verticalLayout.addWidget(self.label_4) + self.layoutWidget1 = QtWidgets.QWidget(self.splitter_3) + self.layoutWidget1.setObjectName("layoutWidget1") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.layoutWidget1) + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.filepath_le = QtWidgets.QLineEdit(self.layoutWidget1) + self.filepath_le.setObjectName("filepath_le") + self.verticalLayout_2.addWidget(self.filepath_le) + self.filename_le = QtWidgets.QLineEdit(self.layoutWidget1) + self.filename_le.setObjectName("filename_le") + self.verticalLayout_2.addWidget(self.filename_le) + self.layoutWidget2 = QtWidgets.QWidget(self.splitter_3) + self.layoutWidget2.setObjectName("layoutWidget2") + self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.layoutWidget2) + self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.filepath_bt = QtWidgets.QPushButton(self.layoutWidget2) + self.filepath_bt.setObjectName("filepath_bt") + self.verticalLayout_3.addWidget(self.filepath_bt) + self.save_bt = QtWidgets.QPushButton(self.layoutWidget2) + self.save_bt.setObjectName("save_bt") + self.verticalLayout_3.addWidget(self.save_bt) + self.horizontalLayout_4.addWidget(self.splitter_3) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem1) + self.verticalLayout_7.addWidget(self.groupBox_5) + self.splitter = QtWidgets.QSplitter(image_Window) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName("splitter") + self.groupBox_3 = QtWidgets.QGroupBox(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth()) + self.groupBox_3.setSizePolicy(sizePolicy) + self.groupBox_3.setMinimumSize(QtCore.QSize(0, 0)) + self.groupBox_3.setMaximumSize(QtCore.QSize(2000, 16777215)) + self.groupBox_3.setObjectName("groupBox_3") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_3) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.groupBox = QtWidgets.QGroupBox(self.groupBox_3) + self.groupBox.setObjectName("groupBox") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox) + self.horizontalLayout.setObjectName("horizontalLayout") + self.image_glo = QtWidgets.QGridLayout() + self.image_glo.setObjectName("image_glo") + self.horizontalLayout.addLayout(self.image_glo) + self.verticalLayout_4.addWidget(self.groupBox) + self.statu_tb = QtWidgets.QTextBrowser(self.groupBox_3) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.statu_tb.sizePolicy().hasHeightForWidth()) + self.statu_tb.setSizePolicy(sizePolicy) + self.statu_tb.setMaximumSize(QtCore.QSize(8777215, 100)) + self.statu_tb.setReadOnly(True) + self.statu_tb.setObjectName("statu_tb") + self.verticalLayout_4.addWidget(self.statu_tb) + self.groupBox_4 = QtWidgets.QGroupBox(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_4.sizePolicy().hasHeightForWidth()) + self.groupBox_4.setSizePolicy(sizePolicy) + self.groupBox_4.setObjectName("groupBox_4") + self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.groupBox_4) + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.groupBox_2 = QtWidgets.QGroupBox(self.groupBox_4) + self.groupBox_2.setObjectName("groupBox_2") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox_2) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.focus_glo = QtWidgets.QGridLayout() + self.focus_glo.setObjectName("focus_glo") + self.horizontalLayout_2.addLayout(self.focus_glo) + self.verticalLayout_5.addWidget(self.groupBox_2) + self.groupBox_6 = QtWidgets.QGroupBox(self.groupBox_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_6.sizePolicy().hasHeightForWidth()) + self.groupBox_6.setSizePolicy(sizePolicy) + self.groupBox_6.setObjectName("groupBox_6") + self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_6) + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.groupBox_7 = QtWidgets.QGroupBox(self.groupBox_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_7.sizePolicy().hasHeightForWidth()) + self.groupBox_7.setSizePolicy(sizePolicy) + self.groupBox_7.setMaximumSize(QtCore.QSize(500, 500)) + self.groupBox_7.setObjectName("groupBox_7") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_7) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.label_3 = QtWidgets.QLabel(self.groupBox_7) + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.verticalLayout_6.addWidget(self.label_3) + self.focus_bt = QtWidgets.QPushButton(self.groupBox_7) + self.focus_bt.setObjectName("focus_bt") + self.verticalLayout_6.addWidget(self.focus_bt) + self.exposureTime_bt = QtWidgets.QPushButton(self.groupBox_7) + self.exposureTime_bt.setObjectName("exposureTime_bt") + self.verticalLayout_6.addWidget(self.exposureTime_bt) + self.label_5 = QtWidgets.QLabel(self.groupBox_7) + self.label_5.setAlignment(QtCore.Qt.AlignCenter) + self.label_5.setObjectName("label_5") + self.verticalLayout_6.addWidget(self.label_5) + self.wb_bt = QtWidgets.QPushButton(self.groupBox_7) + self.wb_bt.setObjectName("wb_bt") + self.verticalLayout_6.addWidget(self.wb_bt) + self.label_2 = QtWidgets.QLabel(self.groupBox_7) + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.verticalLayout_6.addWidget(self.label_2) + self.record_bt = QtWidgets.QPushButton(self.groupBox_7) + self.record_bt.setObjectName("record_bt") + self.verticalLayout_6.addWidget(self.record_bt) + self.horizontalLayout_3.addLayout(self.verticalLayout_6) + self.verticalLayout_8 = QtWidgets.QVBoxLayout() + self.verticalLayout_8.setObjectName("verticalLayout_8") + self.framerate_le = QtWidgets.QLineEdit(self.groupBox_7) + self.framerate_le.setReadOnly(False) + self.framerate_le.setObjectName("framerate_le") + self.verticalLayout_8.addWidget(self.framerate_le) + self.stop_focus_bt = QtWidgets.QPushButton(self.groupBox_7) + self.stop_focus_bt.setObjectName("stop_focus_bt") + self.verticalLayout_8.addWidget(self.stop_focus_bt) + self.exposureTime_le = QtWidgets.QLineEdit(self.groupBox_7) + self.exposureTime_le.setObjectName("exposureTime_le") + self.verticalLayout_8.addWidget(self.exposureTime_le) + self.gain_le = QtWidgets.QLineEdit(self.groupBox_7) + self.gain_le.setObjectName("gain_le") + self.verticalLayout_8.addWidget(self.gain_le) + self.dc_bt = QtWidgets.QPushButton(self.groupBox_7) + self.dc_bt.setObjectName("dc_bt") + self.verticalLayout_8.addWidget(self.dc_bt) + self.framenumber_le = QtWidgets.QLineEdit(self.groupBox_7) + self.framenumber_le.setObjectName("framenumber_le") + self.verticalLayout_8.addWidget(self.framenumber_le) + self.motor_bt = QtWidgets.QPushButton(self.groupBox_7) + self.motor_bt.setObjectName("motor_bt") + self.verticalLayout_8.addWidget(self.motor_bt) + self.stop_record_bt = QtWidgets.QPushButton(self.groupBox_7) + self.stop_record_bt.setObjectName("stop_record_bt") + self.verticalLayout_8.addWidget(self.stop_record_bt) + self.horizontalLayout_3.addLayout(self.verticalLayout_8) + self.horizontalLayout_5.addWidget(self.groupBox_7) + spacerItem2 = QtWidgets.QSpacerItem(261, 17, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_5.addItem(spacerItem2) + self.verticalLayout_5.addWidget(self.groupBox_6) + self.verticalLayout_7.addWidget(self.splitter) + + self.retranslateUi(image_Window) + QtCore.QMetaObject.connectSlotsByName(image_Window) + + def retranslateUi(self, image_Window): + _translate = QtCore.QCoreApplication.translate + image_Window.setWindowTitle(_translate("image_Window", "影像窗口")) + self.groupBox_5.setTitle(_translate("image_Window", "GroupBox")) + self.label.setText(_translate("image_Window", "保存路径")) + self.label_4.setText(_translate("image_Window", "文件名")) + self.filepath_bt.setText(_translate("image_Window", "浏览")) + self.save_bt.setText(_translate("image_Window", "保存")) + self.groupBox_3.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox.setTitle(_translate("image_Window", "图像")) + self.groupBox_4.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox_2.setTitle(_translate("image_Window", "光谱")) + self.groupBox_6.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox_7.setTitle(_translate("image_Window", "GroupBox")) + self.label_3.setText(_translate("image_Window", "帧率")) + self.focus_bt.setText(_translate("image_Window", "调焦")) + self.exposureTime_bt.setText(_translate("image_Window", "曝光")) + self.label_5.setText(_translate("image_Window", "gain")) + self.wb_bt.setText(_translate("image_Window", "白板")) + self.label_2.setText(_translate("image_Window", "帧数")) + self.record_bt.setText(_translate("image_Window", "采集")) + self.stop_focus_bt.setText(_translate("image_Window", "停止调焦")) + self.dc_bt.setText(_translate("image_Window", "暗电流")) + self.motor_bt.setText(_translate("image_Window", "马达")) + self.stop_record_bt.setText(_translate("image_Window", "停止采集")) diff --git a/record_system_v22/image_Window.ui b/record_system_v22/image_Window.ui new file mode 100644 index 0000000..c2133b3 --- /dev/null +++ b/record_system_v22/image_Window.ui @@ -0,0 +1,377 @@ + + + image_Window + + + true + + + + 0 + 0 + 1181 + 683 + + + + false + + + 影像窗口 + + + false + + + false + + + false + + + + + + + 0 + 0 + + + + GroupBox + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + + + + 保存路径 + + + + + + + 文件名 + + + + + + + + + + + + + + + + + + + + + 浏览 + + + + + + + 保存 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 2000 + 16777215 + + + + GroupBox + + + + + + 图像 + + + + + + + + + + + + + 0 + 0 + + + + + 8777215 + 100 + + + + true + + + + + + + + + 0 + 0 + + + + GroupBox + + + + + + 光谱 + + + + + + + + + + + + + 0 + 0 + + + + GroupBox + + + + + + + 0 + 0 + + + + + 500 + 500 + + + + GroupBox + + + + + + + + 帧率 + + + Qt::AlignCenter + + + + + + + 调焦 + + + + + + + 曝光 + + + + + + + gain + + + Qt::AlignCenter + + + + + + + 白板 + + + + + + + 帧数 + + + Qt::AlignCenter + + + + + + + 采集 + + + + + + + + + + + false + + + + + + + 停止调焦 + + + + + + + + + + + + + 暗电流 + + + + + + + + + + 马达 + + + + + + + 停止采集 + + + + + + + + + + + + Qt::Horizontal + + + + 261 + 17 + + + + + + + + + + + + + + + + diff --git a/record_system_v22/spectral_Window.py b/record_system_v22/spectral_Window.py new file mode 100644 index 0000000..749f060 --- /dev/null +++ b/record_system_v22/spectral_Window.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'spectral_Window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_spectral_Window(object): + def setupUi(self, spectral_Window): + spectral_Window.setObjectName("spectral_Window") + spectral_Window.resize(792, 523) + self.label = QtWidgets.QLabel(spectral_Window) + self.label.setGeometry(QtCore.QRect(54, 10, 51, 20)) + self.label.setObjectName("label") + self.filepath_le = QtWidgets.QLineEdit(spectral_Window) + self.filepath_le.setGeometry(QtCore.QRect(131, 10, 261, 21)) + self.filepath_le.setObjectName("filepath_le") + self.label_2 = QtWidgets.QLabel(spectral_Window) + self.label_2.setGeometry(QtCore.QRect(54, 40, 41, 20)) + self.label_2.setObjectName("label_2") + self.filename_le = QtWidgets.QLineEdit(spectral_Window) + self.filename_le.setGeometry(QtCore.QRect(131, 40, 261, 21)) + self.filename_le.setObjectName("filename_le") + self.filepath_bt = QtWidgets.QPushButton(spectral_Window) + self.filepath_bt.setGeometry(QtCore.QRect(401, 10, 71, 21)) + self.filepath_bt.setObjectName("filepath_bt") + self.statu_tb = QtWidgets.QTextBrowser(spectral_Window) + self.statu_tb.setGeometry(QtCore.QRect(611, 210, 161, 301)) + self.statu_tb.setObjectName("statu_tb") + self.tabWidget = QtWidgets.QTabWidget(spectral_Window) + self.tabWidget.setGeometry(QtCore.QRect(10, 70, 591, 441)) + self.tabWidget.setObjectName("tabWidget") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.gridLayoutWidget = QtWidgets.QWidget(self.tab) + self.gridLayoutWidget.setGeometry(QtCore.QRect(0, 0, 581, 411)) + self.gridLayoutWidget.setObjectName("gridLayoutWidget") + self.spe_glo = QtWidgets.QGridLayout(self.gridLayoutWidget) + self.spe_glo.setContentsMargins(0, 0, 0, 0) + self.spe_glo.setObjectName("spe_glo") + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QtWidgets.QWidget() + self.tab_2.setObjectName("tab_2") + self.gridLayoutWidget_2 = QtWidgets.QWidget(self.tab_2) + self.gridLayoutWidget_2.setGeometry(QtCore.QRect(-1, -1, 581, 411)) + self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2") + self.align_glo = QtWidgets.QGridLayout(self.gridLayoutWidget_2) + self.align_glo.setContentsMargins(0, 0, 0, 0) + self.align_glo.setObjectName("align_glo") + self.tabWidget.addTab(self.tab_2, "") + self.layoutWidget = QtWidgets.QWidget(spectral_Window) + self.layoutWidget.setGeometry(QtCore.QRect(610, 90, 195, 135)) + self.layoutWidget.setObjectName("layoutWidget") + self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.align_bt = QtWidgets.QPushButton(self.layoutWidget) + self.align_bt.setObjectName("align_bt") + self.gridLayout.addWidget(self.align_bt, 0, 0, 1, 1) + self.stop_align_bt = QtWidgets.QPushButton(self.layoutWidget) + self.stop_align_bt.setObjectName("stop_align_bt") + self.gridLayout.addWidget(self.stop_align_bt, 0, 1, 1, 1) + self.wb_bt = QtWidgets.QPushButton(self.layoutWidget) + self.wb_bt.setObjectName("wb_bt") + self.gridLayout.addWidget(self.wb_bt, 1, 0, 1, 2) + self.dc_bt = QtWidgets.QPushButton(self.layoutWidget) + self.dc_bt.setObjectName("dc_bt") + self.gridLayout.addWidget(self.dc_bt, 2, 0, 1, 2) + self.record_bt = QtWidgets.QPushButton(self.layoutWidget) + self.record_bt.setObjectName("record_bt") + self.gridLayout.addWidget(self.record_bt, 3, 0, 1, 2) + + self.retranslateUi(spectral_Window) + self.tabWidget.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(spectral_Window) + + def retranslateUi(self, spectral_Window): + _translate = QtCore.QCoreApplication.translate + spectral_Window.setWindowTitle(_translate("spectral_Window", "光谱窗口")) + self.label.setText(_translate("spectral_Window", "保存路径")) + self.label_2.setText(_translate("spectral_Window", "文件名")) + self.filepath_bt.setText(_translate("spectral_Window", "浏览")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("spectral_Window", "spe")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("spectral_Window", "align")) + self.align_bt.setText(_translate("spectral_Window", "align")) + self.stop_align_bt.setText(_translate("spectral_Window", "stop align")) + self.wb_bt.setText(_translate("spectral_Window", "曝光/白板")) + self.dc_bt.setText(_translate("spectral_Window", "暗电流")) + self.record_bt.setText(_translate("spectral_Window", "采集")) diff --git a/record_system_v22/spectral_Window.ui b/record_system_v22/spectral_Window.ui new file mode 100644 index 0000000..f2641b7 --- /dev/null +++ b/record_system_v22/spectral_Window.ui @@ -0,0 +1,180 @@ + + + spectral_Window + + + + 0 + 0 + 792 + 523 + + + + 光谱窗口 + + + + + 54 + 10 + 51 + 20 + + + + 保存路径 + + + + + + 131 + 10 + 261 + 21 + + + + + + + 54 + 40 + 41 + 20 + + + + 文件名 + + + + + + 131 + 40 + 261 + 21 + + + + + + + 401 + 10 + 71 + 21 + + + + 浏览 + + + + + + 611 + 210 + 161 + 301 + + + + + + + 10 + 70 + 591 + 441 + + + + 0 + + + + spe + + + + + 0 + 0 + 581 + 411 + + + + + + + + align + + + + + -1 + -1 + 581 + 411 + + + + + + + + + + 610 + 90 + 195 + 135 + + + + + + + align + + + + + + + stop align + + + + + + + 曝光/白板 + + + + + + + 暗电流 + + + + + + + 采集 + + + + + + + + + diff --git a/record_system_v23/2record_system_v2.3.py b/record_system_v23/2record_system_v2.3.py new file mode 100644 index 0000000..51cb85f --- /dev/null +++ b/record_system_v23/2record_system_v2.3.py @@ -0,0 +1,1438 @@ +''' +在2record system_v2.1的基础上新增功能 +1、使用多线程 + 多进程采集数据:解决同一个线程同时采集和bin降低帧率的问题 + 1)多线程:自动曝光、调焦、采集暗电流、采集白板等耗时短的任务 + 2)多进程:把数据采集(进程1将影像数据写入Queue)、bin和数据写入硬盘(进程2从Queue中读取数据)两个步骤分开 + + 遇见问题:最后发现使用多进程来采集数据是会出现内存被用完的情况,如果电脑内存不大,会出现软件死机的情况;这是因为 + 进程1向Queue中写的速度太快,而进程2从Queue中读取的速度太慢导致的 + +2、通过共享变量来实现影像边采集边刷新:因为多进程采集,没有解决这个问题 +''' + +from ximea import xiapi +import numpy as np +import sharedmem as shm +import os, sys, functools, re, shutil, traceback + + +import datetime # 几种Python执行时间的计算方法:https://blog.csdn.net/wangshuang1631/article/details/54286551 +from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, qApp, QDialog, QFileDialog +# from PyQt5.QtCore import pyqtSignal, QObject, QRunnable, QThreadPool +from PyQt5.QtCore import * +from enter_window import * +from image_Window import * +from spectral_Window import * + +import cv2 +import matplotlib +matplotlib.use("Qt5Agg") # 声明使用QT5 +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.figure import Figure +import matplotlib.pyplot as plt + +import multiprocessing +from multiprocessing import Process, Queue + + +# 主窗口 +class enter_window(QMainWindow, Ui_enter_Window): + def __init__(self, parent=None): + super(enter_window, self).__init__(parent) + self.setupUi(self) + + # 在刚打开软件在本窗口显示相机状态(是否打开) + self.c = Communicate() + self.c.openinfo.connect(self.printCamInfo) + # self.end_Btn.clicked.connect(self.end_event) # 绑定登陆函数 + # self.exit_Btn.clicked.connect(sys.exit) + + def printCamInfo(self): + self.camstatus_tb.append('相机已打开!') + +# 主窗口信号类 +class Communicate(QObject): + openinfo = pyqtSignal() + +# 图像窗口 +class image_window(QDialog, Ui_image_Window): + def __init__(self, parent=None): + ''' + The super().__init__() method invokes the base class constructor from the MyForm class, + that is, the constructor of the QDialog class is invoked from MyForm class to indicate that + QDialog is displayed through this class iss a top-level window. + ''' + super(image_window, self).__init__(parent) + self.setupUi(self) + + # 建立进程池 + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 建立多进程共享变量,用于控制数据采集的停止和显示 + self.share_state = multiprocessing.Manager().Value('c_bool', True) + # 思路来源:https://stackoverflow.com/questions/7894791/use-numpy-array-in-shared-memory-for-multiprocessing + self.rgb = np.ones(int(camera_operation.framenumber_input) * int( + (camera_operation.endColumn - camera_operation.startColumn) / camera_operation.bin_spatial)).astype( + np.float32) + self.share_r = multiprocessing.Array('f', self.rgb) + self.share_g = multiprocessing.Array('f', self.rgb) + self.share_b = multiprocessing.Array('f', self.rgb) + + # 初始化窗口中的值 + self.framenumber_le.setText(str(camera_operation.framenumber_input)) + self.framerate_le.setText(str(camera_operation.framerate_input)) + self.exposureTime_le.setText(str(camera_operation.exposureTime_input)) + self.gain_le.setText(str(camera_operation.gain_input)) + self.filename_le.setText('test') + self.filepath_le.setText(os.getcwd()) + + # 手动改变窗口中的值,然后将值写入camera_operation类对应的变量中 + self.filepath_bt.clicked.connect(self.directory_select) + self.exposureTime_le.textEdited.connect(self.onchange2) + self.gain_le.textEdited.connect(self.onchange2) + self.framerate_le.textEdited.connect(self.onchange2) + self.filename_le.textEdited.connect(self.onchange) + self.framenumber_le.textEdited.connect(self.onchange) + self.filepath_le.textEdited.connect(self.onchange) + + # 显示影像和调焦 + self.myImageFigure = MyImageFigure() + self.image_glo.addWidget(self.myImageFigure) + self.myFocusFigure = MySpectralFigure_focus() + self.focus_glo.addWidget(self.myFocusFigure) + + #操作光谱仪 + ## 注释的代码没有使用多线程,所以会造成一采集数据界面就卡死的情况 + # self.focus_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.dc_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.save_bt.clicked.connect(camera_operation.savedata) + self.exposureTime_bt.clicked.connect(self.autoExposure_multithread) + self.focus_bt.clicked.connect(self.record_image_multithread) + # 停止调焦和采集操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.stop_focus_bt.clicked.connect(self.stop_focus) + self.stop_record_bt.clicked.connect(self.stop_record) + self.dc_bt.clicked.connect(self.record_image_multithread) + self.wb_bt.clicked.connect(self.record_image_multithread) + # self.record_bt.clicked.connect() ########################################################################################## + self.save_bt.clicked.connect(self.save_image) + + # 多进程采集影像 + self.workThread = WorkThread() + self.record_bt.clicked.connect(self.record_image_multiprocess) + self.workThread.sinOut.connect(self.record_finish) # 数据采集完成后会发射信号,然后进行画图 + + # 自动曝光获取参数:exposure和gain;并将值返回显示到界面中对应的QLineEdit中 + def autoExposure_multithread(self): + # 当点击曝光按钮后,让这些按钮不能使用,当采集成功后再让这些按钮可以使用 + self.record_bt.setEnabled(False) + self.focus_bt.setEnabled(False) + self.exposureTime_bt.setEnabled(False) + self.dc_bt.setEnabled(False) + self.wb_bt.setEnabled(False) + self.save_bt.setEnabled(False) + + qt_sender = self.sender().objectName() + self.statu_tb.append('自动曝光...') + worker = Worker(camera_operation.start_AcquireData, qt_sender) + # 曝光参数的设置过程: + # (1)曝光参数返回到界面中的QLineEdit; + # (2)通过QLineEdit的textChanged事件将值写入到camera_operation对应的变量; + # 这种过程的好处是界面显示的曝光参数和实际设置的是同步的 + worker.signals.result.connect(self.changeTXT_QLineEdit) + worker.signals.finished.connect( + self.exposure_finish) # 也可以通过QLineEdit的textChanged事件调用self.set_exposure函数,为相机设置参数 + + self.threadpool.start(worker) + + # 调焦、采集暗电流、采集白板 都通过此函数 + def record_image_multithread(self): + qt_sender = self.sender().objectName() + + # 当点击采集后,让这些按钮不能使用,当采集成功后再让这些按钮可以使用 + self.record_bt.setEnabled(False) + self.focus_bt.setEnabled(False) + self.exposureTime_bt.setEnabled(False) + self.dc_bt.setEnabled(False) + self.wb_bt.setEnabled(False) + self.save_bt.setEnabled(False) + + # 操作状态显示 + if qt_sender == 'focus_bt': + self.statu_tb.append('调焦...') + elif qt_sender == 'dc_bt': + self.statu_tb.append('采集暗电流...') + elif qt_sender == 'wb_bt': + self.statu_tb.append('采集白板...') + + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(camera_operation.start_AcquireData, qt_sender) + self.threadpool.start(worker) + + # 操作状态显示 + 为相机设置exposure和gain + if qt_sender == 'focus_bt': + # worker.signals.finished.connect(lambda: self.statu_tb.append('调焦成功!')) + worker.signals.finished.connect(self.focus_finish) + elif qt_sender == 'dc_bt': + worker.signals.finished.connect(self.dc_finish) + elif qt_sender == 'wb_bt': + worker.signals.finished.connect(self.wb_finish) + + # 完成调焦、采集暗电流、采集白板后--------->>>>>采集影像和将影像写到硬盘上 + def record_image_multiprocess(self): + # print('开始按钮点击事件正常!') + self.statu_tb.append('开始采集数据...') + + # 当点击采集后,让这些按钮不能使用,当采集成功后再让这些按钮可以使用 + self.record_bt.setEnabled(False) + self.focus_bt.setEnabled(False) + self.exposureTime_bt.setEnabled(False) + self.dc_bt.setEnabled(False) + self.wb_bt.setEnabled(False) + self.save_bt.setEnabled(False) + + # 此共享变量是用来停止采集进程所用,所以每次开始前要把值设置为True + self.share_state.set(True) + + # 共享变量(主线程和写进程之间共享),每次采集前都要清空上一次采集的内容(其实也不必要,因为采集的过程中也将内容全部都改变了) + self.rgb = np.ones(int(camera_operation.framenumber_input) * int( + (camera_operation.endColumn - camera_operation.startColumn) / camera_operation.bin_spatial)).astype( + np.float32) + self.share_r = multiprocessing.Array('f', self.rgb) + self.share_g = multiprocessing.Array('f', self.rgb) + self.share_b = multiprocessing.Array('f', self.rgb) + + # 新建一个线程,在此线程中新建两个进程来采集数据 + self.workThread.start() + + def plot_img(self, r, g, b): + img_r = np.frombuffer(r.get_obj(), dtype=np.float32).reshape(int(camera_operation.framenumber_input), int( + (camera_operation.endColumn - camera_operation.startColumn) / camera_operation.bin_spatial)) + img_g = np.frombuffer(g.get_obj(), dtype=np.float32).reshape(int(camera_operation.framenumber_input), int( + (camera_operation.endColumn - camera_operation.startColumn) / camera_operation.bin_spatial)) + img_b = np.frombuffer(b.get_obj(), dtype=np.float32).reshape(int(camera_operation.framenumber_input), int( + (camera_operation.endColumn - camera_operation.startColumn) / camera_operation.bin_spatial)) + # img = camera_operation.percentile_stretching(np.dstack((img_r, img_g, img_b)), 2, 98) + # img = np.dstack((img_r, img_g, img_b)) + img = camera_operation.percentile_stretching(img_r, 2, 98) + print(img_r.max()) + print(img.max()) + try: + image_window_instance.myImageFigure.plot(img_r) + image_window_instance.myImageFigure.draw() + # image_window_instance.myImageFigure.plot( + # cls.percentile_stretching(np.dstack((rgb[2, :, :], rgb[1, :, :], rgb[0, :, :])), 2, 98)) + # image_window_instance.myImageFigure.draw() + except: + traceback.print_exc() + finally: + traceback.print_exc() + print('画图出错') + + # 用来停止采集数据 + def stop_record(self): + # camera_operation.record = False + self.share_state.set(False) + + # 用来停止调焦 + def stop_focus(self): + camera_operation.focus = False + + def record_finish(self, x): + print(x) + + # 新建一个线程,用来显示图像 + worker = Worker(self.plot_img, self.share_r, self.share_g, self.share_b) + self.threadpool.start(worker) + + # 数据采集完成后,在界面上给出反馈 + self.statu_tb.append('采集数据成功!') + + # 当采集完成后,让这些按钮恢复使用 + self.record_bt.setEnabled(True) + self.focus_bt.setEnabled(True) + self.exposureTime_bt.setEnabled(True) + self.dc_bt.setEnabled(True) + self.wb_bt.setEnabled(True) + self.save_bt.setEnabled(True) + + def focus_finish(self): + self.statu_tb.append('调焦成功!') + + # 当采集完成后,让这些按钮恢复使用 + self.record_bt.setEnabled(True) + self.focus_bt.setEnabled(True) + self.exposureTime_bt.setEnabled(True) + self.dc_bt.setEnabled(True) + self.wb_bt.setEnabled(True) + self.save_bt.setEnabled(True) + + def dc_finish(self): + self.statu_tb.append('采集暗电流成功!') + + # 当采集完成后,让这些按钮恢复使用 + self.record_bt.setEnabled(True) + self.focus_bt.setEnabled(True) + self.exposureTime_bt.setEnabled(True) + self.dc_bt.setEnabled(True) + self.wb_bt.setEnabled(True) + self.save_bt.setEnabled(True) + + def wb_finish(self): + self.statu_tb.append('采集白板成功!') + + # 当采集完成后,让这些按钮恢复使用 + self.record_bt.setEnabled(True) + self.focus_bt.setEnabled(True) + self.exposureTime_bt.setEnabled(True) + self.dc_bt.setEnabled(True) + self.wb_bt.setEnabled(True) + self.save_bt.setEnabled(True) + + # 设置曝光参数:exposure和gain + def exposure_finish(self): + self.statu_tb.append('自动曝光成功!') + + # 当曝光完成后,让这些按钮恢复使用 + self.record_bt.setEnabled(True) + self.focus_bt.setEnabled(True) + self.exposureTime_bt.setEnabled(True) + self.dc_bt.setEnabled(True) + self.wb_bt.setEnabled(True) + self.save_bt.setEnabled(True) + + # 将自动曝光返回值写入到界面中的QLineEdit + def changeTXT_QLineEdit(self, result): + # 将返回的曝光参数写入到界面中 + self.exposureTime_le.setText(str(result[0])) + self.gain_le.setText(str(result[1])) + # 将返回的曝光参数写入到camera_operation类中 + camera_operation.gain_input = self.gain_le.text() + camera_operation.exposureTime_input = self.exposureTime_le.text() + if result[2] == 1: + QMessageBox.information(self, '曝光提示', '光线不足,曝光时间已设置为最大!', QMessageBox.Yes) + camera_operation.autoexposure_feedback = 0 + + def save_image(self): + # 操作状态显示 + self.statu_tb.append('保存影像...') + + worker = Worker(camera_operation.savedata) + self.threadpool.start(worker) + + # 操作状态显示 + worker.signals.finished.connect(lambda: self.statu_tb.append('保存影像成功!')) + + # (textChanged)将 自动曝光返回到QLineEdit中的值 写入camera_operation类对应的变量中 + def onchange(self): + camera_operation.fn = self.filename_le.text() + camera_operation.fp = self.filepath_le.text() + + # 在界面中改变帧数后,将新帧数写入camera_operation类中 + camera_operation.framenumber_input = self.framenumber_le.text() + + # 在界面中改变帧数后,需要将下面的参数更改一下,然后再传入record_image_multiprocess函数中写进程中去 + self.rgb = np.ones(int(camera_operation.framenumber_input) * int( + (camera_operation.endColumn - camera_operation.startColumn) / camera_operation.bin_spatial)).astype( + np.float32) + self.share_r = multiprocessing.Array('f', self.rgb) + self.share_g = multiprocessing.Array('f', self.rgb) + self.share_b = multiprocessing.Array('f', self.rgb) + + # 手动修改(textEdited)界面中的值后,写入camera_operation类对应的变量中 + def onchange2(self): + camera_operation.gain_input = self.gain_le.text() + camera_operation.exposureTime_input = self.exposureTime_le.text() + camera_operation.framerate_input = self.framerate_le.text() + + def directory_select(self): + dirpath = QFileDialog.getExistingDirectory(self, '选择存储路径文件夹', '/home') + + # 当在文件夹选择窗口中点击取消时,不重设路径 + if dirpath != '': + self.filepath_le.setText(dirpath) + camera_operation.fp = dirpath + +# 光谱窗口 ######################################################################################################################################## +class spectral_window(QDialog, Ui_spectral_Window): + def __init__(self, parent=None): + super(spectral_window, self).__init__(parent) + self.setupUi(self) + + # 建立进程池 + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 初始化值 + self.filename_le.setText('test') + self.filepath_le.setText(os.getcwd()) + + #手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + self.filepath_bt.clicked.connect(self.directory_select) + self.filename_le.textEdited.connect(self.onchange) + self.filepath_le.textEdited.connect(self.onchange) + + + # 显示光谱和align + self.spectralFigure = MySpectralFigure_spectral() + self.spe_glo.addWidget(self.spectralFigure) + self.alignFigure = MyImageFigure() + self.align_glo.addWidget(self.alignFigure) + + #操作光谱仪 + # self.dc_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + self.wb_bt.clicked.connect(self.record_spectral_multithread) # 曝光 + 采集白板 + self.align_bt.clicked.connect(self.record_spectral_multithread) + self.stop_align_bt.clicked.connect(self.stop_align) # 这个操作非常简单,耗时非常短,瞬间可回到event loop;所以不需要多线程 + self.dc_bt.clicked.connect(self.record_spectral_multithread) + self.record_bt.clicked.connect(self.record_spectral_multithread) + + def stop_align(self): + spectral_camera_operation.align = False + + def record_spectral_multithread(self): + # + self.wb_bt.setEnabled(False) + self.align_bt.setEnabled(False) + self.dc_bt.setEnabled(False) + self.record_bt.setEnabled(False) + + qt_sender = self.sender().objectName() + + # 操作状态显示 + if qt_sender == 'wb_bt': + self.statu_tb.append('曝光/白板...') + elif qt_sender == 'align_bt': + self.statu_tb.append('align...') + elif qt_sender == 'dc_bt': + self.statu_tb.append('采集暗电流...') + elif qt_sender == 'record_bt': + self.statu_tb.append('采集光谱...') + + worker = Worker(spectral_camera_operation.start_AcquireData, qt_sender) + self.threadpool.start(worker) + + # 操作状态显示 + if qt_sender == 'wb_bt': + worker.signals.finished.connect(self.wb_finish) + elif qt_sender == 'align_bt': + worker.signals.finished.connect(self.align_finish) + elif qt_sender == 'dc_bt': + worker.signals.finished.connect(self.dc_finish) + elif qt_sender == 'record_bt': + worker.signals.finished.connect(self.record_finish) + + def wb_finish(self): + self.statu_tb.append('曝光/白板成功!') + + # 当采集完成后,让这些按钮恢复使用 + self.wb_bt.setEnabled(True) + self.align_bt.setEnabled(True) + self.dc_bt.setEnabled(True) + self.record_bt.setEnabled(True) + + def align_finish(self): + self.statu_tb.append('align successfully!') + + # 当采集完成后,让这些按钮恢复使用 + self.wb_bt.setEnabled(True) + self.align_bt.setEnabled(True) + self.dc_bt.setEnabled(True) + self.record_bt.setEnabled(True) + + def dc_finish(self): + self.statu_tb.append('采集暗电流成功!') + + # 当采集完成后,让这些按钮恢复使用 + self.wb_bt.setEnabled(True) + self.align_bt.setEnabled(True) + self.dc_bt.setEnabled(True) + self.record_bt.setEnabled(True) + + def record_finish(self): + self.statu_tb.append('采集光谱成功!') + + # 当采集完成后,让这些按钮恢复使用 + self.wb_bt.setEnabled(True) + self.align_bt.setEnabled(True) + self.dc_bt.setEnabled(True) + self.record_bt.setEnabled(True) + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + def onchange(self): + spectral_camera_operation.fn = self.filename_le.text() + spectral_camera_operation.fp = self.filepath_le.text() + + def directory_select(self): + dirpath = QFileDialog.getExistingDirectory(self, '选择存储路径文件夹', '/home') + + # 当在文件夹选择窗口中点击取消时,不重设路径 + if dirpath != '': + self.filepath_le.setText(dirpath) + spectral_camera_operation.fp = dirpath# + +# 画图类,用于:画出采集到的光谱;调焦(影响模式调焦) +class MySpectralFigure_focus(FigureCanvas): + def __init__(self, width=5, height=4, dpi=100): + #第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + + #第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MySpectralFigure_focus, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + + #第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + self.axes.set_xlabel('Wavelength (nm)') + #第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def plot(self, spectral): + self.axes.clear() + self.axes.plot(spectral) + +class MySpectralFigure_spectral(FigureCanvas): + def __init__(self, width=5, height=4, dpi=100): + # 第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + + # 第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MySpectralFigure_spectral, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + + # 第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + self.axes.set_xlabel('Wavelength (nm)') + self.axes + #第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def plot(self, Wavelength, spectral): + self.axes.clear() + self.axes.plot(Wavelength, spectral) + +# 画图类,用于:画出采集到的图像;显示帧流(光谱模式对准光纤) +class MyImageFigure(FigureCanvas): + def __init__(self, width=5, height=4, dpi=100): + # 第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + # 第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MyImageFigure, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + # 第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + # 第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def plot(self, frame): + self.axes.clear() + self.axes.imshow(frame) + +class WorkerSignals(QObject): + ''' + Defines the signals available from a running worker thread. + + Supported signals are: + + finished + No data + + error + `tuple` (exctype, value, traceback.format_exc() ) + + result + `object` data returned from processing, anything + + progress + `int` indicating % progress + + ''' + finished = pyqtSignal() + error = pyqtSignal(tuple) + result = pyqtSignal(object) + progress = pyqtSignal(int) + +# 用于qt多线程:运行long-time task +class Worker(QRunnable): + ''' + Worker thread + + Inherits from QRunnable to handler worker thread setup, signals and wrap-up. + + :param callback: The function callback to run on this worker thread. Supplied args and + kwargs will be passed through to the runner. + :type callback: function + :param args: Arguments to pass to the callback function + :param kwargs: Keywords to pass to the callback function + + ''' + + def __init__(self, fn, *args, **kwargs): + super(Worker, self).__init__() + + # Store constructor arguments (re-used for processing) + self.fn = fn + self.args = args + self.kwargs = kwargs + self.signals = WorkerSignals() + + # Add the callback to our kwargs + # self.kwargs['progress_callback'] = self.signals.progress + + @pyqtSlot() + def run(self): + ''' + Initialise the runner function with passed args, kwargs. + ''' + + # Retrieve args/kwargs here; and fire processing using them + + try: + result = self.fn(*self.args, **self.kwargs) + except: + traceback.print_exc() + exctype, value = sys.exc_info()[:2] + self.signals.error.emit((exctype, value, traceback.format_exc())) + else: + self.signals.result.emit(result) # Return the result of the processing + finally: + self.signals.finished.emit() # Done + + +class WorkThread(QThread): + ''' + 这是工作线程,界面点击“开始采集”按钮后,新建这个线程,避免界面卡死;然后在此线程中新建两个进程(分别负责采集数据和存储数据) + ''' + def __init__(self): + super().__init__() + + + # 多进程代码思路来源:https://stackoverflow.com/questions/14410416/how-to-use-multicore-python-with-pyqt4-process + # https://stackoverflow.com/questions/29310824/how-to-implement-multicore-processing-in-python-3-and-pyqt5 + # (1)网页中的代码使用的是pool.apply_async,但是这样运行有错; + # (2)我自己使用Process就没有问题 + sinOut = pyqtSignal(str) # 自定义信号,执行run()函数时,从相关线程发射此信号 + def run(self): + + # 共享变量必须和Process类实例都在run函数内,共享变量放在在WorkThread类其他地方程序运行都会出错 + q = Queue() + rgb = shm.full((3, int(100), int((1649 - 285) / 2)), 1, dtype=np.float32) + + pr = Process(target=camera_operation.recordimg, args=( + camera_operation.startRow, camera_operation.endRow, camera_operation.startColumn, + camera_operation.endColumn, q, camera_operation.framenumber_input, camera_operation.framerate_input, + camera_operation.exposureTime_input, camera_operation.gain_input, camera_operation.image_dc, + camera_operation.image_wb, camera_operation.bin_spectral, camera_operation.bin_spatial, + image_window_instance.share_state)) + # 如果注释掉写进程,会出现一个问题:第一次点击按钮可以正常采集,当采集完成后,第二次点击俺就就不能正常采集 + pw = Process(target=camera_operation.writeimg, args=( + camera_operation.startRow, camera_operation.endRow, camera_operation.startColumn, + camera_operation.endColumn, q, camera_operation.bin_spectral, camera_operation.bin_spatial, + camera_operation.image_dc, camera_operation.image_wb, image_window_instance.share_r, + image_window_instance.share_g, image_window_instance.share_b)) + + # # 这样有问题,在界面中改变帧数输入后,点击开始;新的帧数并没有被新建的进程获取!!!! + # pr = Process(target=camera_operation.recordimg2, args=(q, image_window_instance.share_state)) + # # 如果注释掉写进程,会出现一个问题:第一次点击按钮可以正常采集,当采集完成后,第二次点击俺就就不能正常采集 + # pw = Process(target=camera_operation.writeimg2, args=(q, 1)) + + pr.start() + pw.start() + pr.join() + pw.terminate() + print('我才代表进程都正常结束!') # 两个进程中的代码都执行到了最后一句,代表进程正常结束了吧?但是为啥执行不到这句代码?????? + self.sinOut.emit('采集完成!') + + +# 影像模式类:相关的函数和变量 +class camera_operation(object): + + # 传感器有效范围 + # startRow = 339 + # endRow = 639 + # startColumn = 285 + # endColumn = 1650 + # 影像中400-560列:685-845 + startRow = 339 + endRow = 639 + startColumn = 285 + endColumn = 1649 + + # bin相关设置 + bin_spectral = 1 # 光谱bin + bin_spatial = 1 # 空间bin + k = np.arange(endRow - startRow)[0::bin_spectral] + l = np.arange(endColumn - startColumn)[0::bin_spatial] + + # 存储曝光时间和帧率 + framerate_input = 30 # 随便给个初始值(初始值要和framerate_le控件初始值一致),从image_window获取的手动输入的帧率 + exposureTime_input = 180 # 曝光时间单位为微秒,1s共有1000000微秒 + gain_input = 0 + + + # 开始采集数据 + framenumber_input = 100 # 随便给个初始值(初始值要和framenumber_le控件初始值一致),从image_window获取的手动输入的帧数 + image_dc = 1 # 随便给个初始值,此变量用于存储采集到的暗电流影像 + image_wb = 1 # 随便给个初始值,此变量用于存储采集到的白板影像 + focus = True # 用于停止调焦 + record = True # 用于停止采集 + # rgb = shm.full((3, int(framenumber_input), int((endColumn - startColumn) / bin_spatial)), 1, dtype=np.float32) + + + + autoexposure_feedback = 0 + @classmethod + def start_AcquireData(cls, qt_sender): # qt_sender是指qt窗口中事件的发生者 + # create instance of Image to store image data and metadata + cam = open_camera2() + cam.set_framerate(int(cls.framerate_input)) + cam.set_exposure(int(cls.exposureTime_input)) # 曝光时间单位为微秒,1s共有1000000微秒 + cam.set_gain(int(float(cls.gain_input))) + img = xiapi.Image() + # cam.get_buffer_policy() + + + if qt_sender == 'exposureTime_bt': + cam.set_framerate(int(cls.framerate_input)) + cam.set_aeag_roi_offset_x(cls.startColumn) + cam.set_aeag_roi_offset_y(cls.startRow) + cam.set_aeag_roi_height(cls.endRow - cls.startRow) + cam.set_aeag_roi_width(cls.endColumn - cls.startColumn) + # cam.set_exp_priority(1) # Exposure priority (0.8 - exposure 80%, gain 20%).XI_PRM_EXP_PRIORITY + # cam.set_ae_max_limit(24000) # Maximum time (us) used for exposure in AEAG procedureXI_PRM_AE_MAX_LIMIT + # cam.set_ag_max_limit(12) + # cam.set_aeag_level(50) # Average intensity of output signal AEAG should achieve(in %)XI_PRM_AEAG_LEVEL + # 还有两个不知怎么用的参数:XI_PRM_GAIN_SELECTOR or "gain_selector"和XI_PRM_SHUTTER_TYPE or "shutter_type" + cam.enable_aeag() # 开启自动曝光 + cam.start_acquisition() + for i in range(10): + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + cam.disable_aeag() # 关闭自动曝光 + + # 判断是否光线不足,如果不足,提示用户 + if cam.get_exposure() > int(1 / int(cls.framerate_input) * 10**6): + cam.set_exposure(int(1 / int(cls.framerate_input) * 10**6)) + cls.autoexposure_feedback = 1 + + else: + cam.set_exposure(cam.get_exposure()) + + print('Framerate was set to %i FPS' % cam.get_framerate()) + print('Exposure was set to %i us' % cam.get_exposure()) + print('Gain was set to %i dB' % cam.get_gain()) + + # 自动曝光返回值放在本函数(start_AcquireData)的最后 + + # 如果点击“调焦”按钮 + if qt_sender == 'focus_bt': + cam.start_acquisition() + cam.set_framerate(10) + # 当关闭调焦后,再次打开调焦功能需要将cls.focus的值从False变为True + if not cls.focus: + cls.focus = True + while cls.focus: + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + image_window_instance.myFocusFigure.plot(image_container[150, :]) + image_window_instance.myFocusFigure.draw() + + # 如果点击“白板”按钮,采集并保存白板影像到image_wb + if qt_sender == 'wb_bt': + framenumber = 10 + image_container = np.empty((cls.endRow - cls.startRow, framenumber, cls.endColumn - cls.startColumn)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + image_container = image_container.mean(axis=1) + + # 光谱bin和空间bin + if cls.bin_spectral != 1: + image_container_bin_spectral = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), cls.endColumn - cls.startColumn)) + image_container_bin = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), + int((cls.endColumn - cls.startColumn) / cls.bin_spatial))) + + for i in range(image_container_bin_spectral.shape[0]): + for j in range(cls.bin_spectral): + image_container_bin_spectral[i] += image_container[cls.k[i] + j] + # 光谱bin完成后,进行空间bin + for i in range(image_container_bin.shape[1]): + for j in range(cls.bin_spatial): + image_container_bin[:, i] += image_container_bin_spectral[:, cls.l[i] + j] + else: + image_container_bin = image_container + + cls.image_wb = image_container_bin + + # 如果点击“暗电流”按钮,采集并保存暗电流影像到image_dc + if qt_sender == 'dc_bt': + framenumber = 10 + image_container = np.empty((cls.endRow - cls.startRow, framenumber, cls.endColumn - cls.startColumn)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + image_container = image_container.mean(axis=1) + + # 光谱bin和空间bin + if cls.bin_spectral != 1: + image_container_bin_spectral = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), cls.endColumn - cls.startColumn)) + image_container_bin = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), + int((cls.endColumn - cls.startColumn) / cls.bin_spatial))) + + for i in range(image_container_bin_spectral.shape[0]): + for j in range(cls.bin_spectral): + image_container_bin_spectral[i] += image_container[cls.k[i] + j] + # 光谱bin完成后,进行空间bin + for i in range(image_container_bin.shape[1]): + for j in range(cls.bin_spatial): + image_container_bin[:, i] += image_container_bin_spectral[:, cls.l[i] + j] + else: + image_container_bin = image_container + + cls.image_dc = image_container_bin + + # stop data acquisition + print('Stopping acquisition...') + + + # 自动曝光所需的返回参数 + cam.stop_acquisition() + exposure = cam.get_exposure() + gain = cam.get_gain() + cam.close_device() + + # 只有自动曝光才用得上的代码 + return exposure, gain, cls.autoexposure_feedback # 只有自动曝光会用返回值,其他时候都用不上返回值 + + @classmethod + def recordimg(cls, startRow, endRow, startColumn, endColumn, q, framenumber_input, framerate_input, + exposureTime_input, gain_input, image_dc, image_wb, bin_spectral, bin_spatial, share_state): + print('已经启动读影像进程!') + + cam = open_camera2() + cam.set_framerate(int(framerate_input)) + cam.set_exposure(int(exposureTime_input)) # 曝光时间单位为微秒,1s共有1000000微秒 + cam.set_gain(int(float(gain_input))) # int('0.0')会报错,int(float('0.0'))不会报错 + img = xiapi.Image() + + print('相机的帧率设置为:%s' % str(cam.get_framerate())) + print('相机的曝光设置为:%s' % str(cam.get_exposure())) + print('相机的Gain设置为:%s' % str(cam.get_gain())) + + cam.start_acquisition() + startTime = datetime.datetime.now() + recordframeCount = 1 + while share_state.value: + # print("record: %s" % recordframeCount) + cam.get_image(img) + # image_raw_numpy.dtype -> dtype(' dtype(' maxout] = maxout + img_out = np.uint8(img_new) + return img_out + else: # 对于彩色照片,需要先单独对每个波段拉伸 + img_new = np.empty(img.shape) + for i in range(img.shape[2]): + low = np.percentile(img[:, :, i], lowPercentile) + up = np.percentile(img[:, :, i], highPercentile) + + img_new[:, :, i] = minout + ((img[:, :, i] - low) / (up - low)) * (maxout - minout) + img_new[:, :, i][img_new[:, :, i] < minout] = minout + img_new[:, :, i][img_new[:, :, i] > maxout] = maxout + img_out = np.uint8(img_new) + return img_out + + @classmethod + def close_camera(cls, cam): + cam.stop_acquisition() + cam.close_device() + + +# 光谱模式类:相关的函数和变量 +class spectral_camera_operation(object): + + # 传感器有效范围 + # startRow = 339 + # endRow = 639 + # startColumn = 285 + # endColumn = 1650 + # 影像中400-560列:685-845 + startRow = 339 + endRow = 639 + startColumn = 285 + endColumn = 1650 + + # 存储曝光时间和帧率 + framerate_input = 15 # 随便给个初始值(初始值要和framerate_le控件初始值一致),从image_window获取的手动输入的帧率 + exposureTime_input = 180 # 曝光时间单位为微秒,1s共有1000000微秒 + gain_input = 0 + + # 开始采集数据 + fp = os.getcwd() # 随便给个初始值(初始值要和filepath_le控件初始值一致),从spectral_window获取的手动输入的帧率 + fn = 'test' # 随便给个初始值(初始值要和filename_le控件初始值一致),从spectral_window获取的手动输入的帧率 + + framenumber = 10 # 每条光谱为多少帧平均得到 + spectral_container = np.empty((endRow - startRow, framenumber, endColumn - startColumn)).astype(np.float) + # spectral_container = np.empty((300, framenumber, 3)).astype(np.float64) + + align = True # 用于对准光纤 + image_dc = np.empty((endRow - startRow, endColumn - startColumn)) # 此变量用于存储采集到的暗电流,一帧 + spectralNumber_wb = 1 # 每次采集的白板的光谱数 + spectral_wb = np.empty((endRow - startRow, endColumn - startColumn)) # 此变量用于存储采集到的白板,一帧 + spectral_wb_tmp = np.empty((endRow - startRow, framenumber, endColumn - startColumn)).astype( + np.float64) # 随便给个初始值,此变量用于存储采集到的白板影像,后面白板影像去除了暗电流后值赋给spectral_wb + spectralNumber = 10 # 每次采集目标物的光谱数 + spectral = np.empty((endRow - startRow, spectralNumber)).astype(np.float) # 此ndarray用于存储采集到的目标物光谱,每一列为一个光谱 + + @classmethod + def start_AcquireData(cls, qt_sender): + + cam = open_camera2() + cam.set_framerate(int(cls.framerate_input)) + cam.set_exposure(int(cls.exposureTime_input)) # 曝光时间单位为微秒,1s共有1000000微秒 + cam.set_gain(int(float(cls.gain_input))) + print('点击函数最开始') + print('Framerate was set to %i FPS' % cam.get_framerate()) + print('Exposure was set to %i us' % cam.get_exposure()) + print('Gain was set to %i dB' % cam.get_gain()) + img = xiapi.Image() + + print('Starting data acquisition...') + starttime = datetime.datetime.now() + + + # 如果点击“曝光/白板”按钮:(1)先自动曝光;(2)然后在采集白板 + if qt_sender == 'wb_bt': + + # 自动曝光 + cam.set_aeag_roi_offset_x(cls.startColumn) + cam.set_aeag_roi_offset_y(cls.startRow) + cam.set_aeag_roi_height(cls.endRow - cls.startRow) + cam.set_aeag_roi_width(cls.endColumn - cls.startColumn) + # cam.set_exp_priority(1) # Exposure priority (0.8 - exposure 80%, gain 20%).XI_PRM_EXP_PRIORITY + # cam.set_ae_max_limit(24000) # Maximum time (us) used for exposure in AEAG procedureXI_PRM_AE_MAX_LIMIT + # cam.set_ag_max_limit(12) + # cam.set_aeag_level(50) # Average intensity of output signal AEAG should achieve(in %)XI_PRM_AEAG_LEVEL + # 还有两个不知怎么用的参数:XI_PRM_GAIN_SELECTOR or "gain_selector"和XI_PRM_SHUTTER_TYPE or "shutter_type" + cam.enable_aeag() + cam.start_acquisition() + for i in range(10): + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + cam.disable_aeag() + + # 将自动曝光获得的exposure和gain写入到相机 + cam.set_exposure(cam.get_exposure()) + cam.set_gain(cam.get_gain()) + # 将自动曝光获得的exposure和gain写入到本类中(spectral_camera_operation) + cls.exposureTime_input = cam.get_exposure() + cls.gain_input = cam.get_gain() + + spectral_window_instance.statu_tb.append('Exposure: ' + str(cam.get_exposure()) + ' us') + spectral_window_instance.statu_tb.append('Framerate: ' + str(cam.get_framerate()) + ' FPS') + + print('Framerate was set to %i FPS' % cam.get_framerate()) + print('Exposure was set to %i us' % cam.get_exposure()) + print('Gain was set to %i dB' % cam.get_gain()) + + # 开始采集白板数据,去除白板暗电流的操作放在采集暗电流时进行 + cam.start_acquisition() + for j in range(cls.spectralNumber_wb): + for i in range(cls.framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + cls.spectral_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, + cls.startColumn:cls.endColumn] + + # 去除白板暗电流的操作放在采集暗电流时进行 + # cls.spectral_container没经过运算,传给cls.spectral_wb_tmp的是cls.spectral_container的内存地址 + cls.spectral_wb_tmp = cls.spectral_container + + # 存储原始白板影像 + filename = cls.fp + '\\' + 'baiban' + with open(filename, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_wb_tmp[:, i, :].flatten().tobytes()) + camera_operation.write_hdr(filename, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + # 如果点击“align”按钮 + if qt_sender == 'align_bt': + + if not cls.align: + cls.align = True + + cam.start_acquisition() + while cls.align: + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + spectral_window_instance.alignFigure.plot(image_raw_numpy) + spectral_window_instance.alignFigure.draw() + + # 如果点击“暗电流”按钮 + if qt_sender == 'dc_bt': + print('点暗电流') + print('Framerate was set to %i FPS' % cam.get_framerate()) + print('Exposure was set to %i us' % cam.get_exposure()) + print('Gain was set to %i dB' % cam.get_gain()) + # 为cls.spectral_container新建立一个内存地址,以免改变cls.spectral_wb_tmp(传址)的值 + cls.spectral_container = np.empty( + (cls.endRow - cls.startRow, cls.framenumber, cls.endColumn - cls.startColumn)).astype(np.float64) + cam.start_acquisition() + for i in range(cls.framenumber):#此循环为啥会改变649行的赋值的结果呢?怎么会执行那里的代码 + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + cls.spectral_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + + # 存储暗电流影像 + filename1 = cls.fp + '\\' + 'dark' + with open(filename1, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_container[:, i, :].flatten().tobytes()) + camera_operation.write_hdr(filename1, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + # cls.spectral_container经过运算,传给cls.image_dc的不是cls.spectral_container的内存地址,是新运算结果的内存地址;相当于传值 + cls.image_dc = cls.spectral_container.mean(axis=1) # 因为平均,cls.image_dc的数据类型为:dtype('float64') + + + + # 去除白板暗电流 + for i in range(cls.framenumber): + cls.spectral_wb_tmp[:, i, :] = cls.spectral_wb_tmp[:, i, :] - cls.image_dc + + + # 存储扣除暗电流的白板影像 + filename2 = cls.fp + '\\' + 'baiban_rmdark' + with open(filename2, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_wb_tmp[:, i, :].flatten().tobytes()) + camera_operation.write_hdr(filename2, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + cls.spectral_wb = cls.spectral_wb_tmp.mean(axis=1) # 因为平均,cls.spectral_wb的数据类型为:dtype('float64') + + # 如果点击“采集”按钮,去除暗电流,转化成反射率 + if qt_sender == 'record_bt': + print('点暗采集') + print('Framerate was set to %i FPS' % cam.get_framerate()) + print('Exposure was set to %i us' % cam.get_exposure()) + print('Gain was set to %i dB' % cam.get_gain()) + cam.start_acquisition() + for j in range(cls.spectralNumber): + for i in range(cls.framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + cls.spectral_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + # 存储扣除暗电流前的目标物影像 + if j == 1: + filename1 = cls.fp + '\\' + cls.fn + with open(filename1, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_container[:, i, :].flatten().tobytes()) + camera_operation.write_hdr(filename1, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + for i in range(cls.framenumber): # (1)去除暗电流;(2)转反射率 + cls.spectral_container[:, i, :] = (cls.spectral_container[:, i, :] - cls.image_dc) / cls.spectral_wb + + # 存储目标物反射率影像 + if j == 1: + filename2 = cls.fp + '\\' + cls.fn + '_ref' + with open(filename2, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_container[:, i, :].flatten().tobytes()) + camera_operation.write_hdr(filename2, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + # spectral_tmp = cls.spectral_container.sum(axis=1).sum(axis=1) + spectral_tmp = cls.spectral_container.mean(axis=1).mean(axis=1) + + cls.spectral[:, j] = spectral_tmp + + + # 画出光谱 + def calculate_wavelength(x): + wavelength = x * 1.999564 - 279.893 + return wavelength + wavelength = np.empty(cls.endRow - cls.startRow) + for i in range(cls.startRow, cls.endRow): + wavelength[i - cls.startRow] = calculate_wavelength(i) + spectral_window_instance.spectralFigure.plot(wavelength, spectral_tmp) + spectral_window_instance.spectralFigure.draw() + + # 计算波长 + def calculate_wavelength(x): + wavelength = x * 1.999564 - 279.893 + return wavelength + wavelength = np.empty(cls.endRow - cls.startRow) + for i in range(cls.startRow, cls.endRow): + wavelength[i - cls.startRow] = calculate_wavelength(i) + # 保存光谱为txt文件 + cls.spectral = np.insert(cls.spectral, 0, wavelength, axis=1) + for i in range(cls.spectralNumber): + np.savetxt(cls.fp + '\\' + cls.fn + str(i) + '.txt', cls.spectral[:, [0, i + 1]], fmt='%f') + + endtime = datetime.datetime.now() + print('光谱采集用时:%d' % (endtime - starttime).seconds) + + # stop data acquisition + print('Stopping acquisition...') + cls.close_camera(cam) + + @classmethod + def close_camera(cls, cam): + cam.stop_acquisition() + cam.close_device() + + +def open_camera2(): + cam = xiapi.Camera() + cam.open_device() + cam.set_proc_num_threads(8) + cam.set_acq_timing_mode('XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + cam.set_imgdataformat('XI_RAW16') + return cam + +# 打开相机 +def open_camera(): + # create instance for first connected camera + cam = xiapi.Camera() + + # start communication to open specific device, use: cam.open_device_by_SN('41305651') + print('Opening first camera...') + cam.open_device() + + # 打开相机后,显示相机信息 + print('SN: %s' % str(cam.get_device_sn(), encoding="utf-8")) + print('Device name: %s' % str(cam.get_device_name(), encoding="utf-8")) + print('Device name: %s' % str(cam.get_device_type(), encoding="utf-8")) + print('Instance path: %s' % str(cam.get_device_inst_path(), + encoding="utf-8")) # Returns device instance path in operating system. + print('Location path: %s' % str(cam.get_device_loc_path(), encoding="utf-8")) + + print('Debug level: %s' % cam.get_debug_level()) + print('Default number of threads per image processor: %d' % cam.get_proc_num_threads()) + cam.set_proc_num_threads(8) + print('Current number of threads per image processor: %d' % cam.get_proc_num_threads()) + print('Is horizontal flip enabled?, %s' % str(cam.is_horizontal_flip())) + print() + + # This mode is supported by selected camera families: CB, MC, MT, MX + cam.set_acq_timing_mode('XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + mode_used = cam.get_acq_timing_mode() + if mode_used == 'XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT': + print('Mode is XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + else: + print('Mode is not XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + sys.exit() + + return cam + + +if __name__ == '__main__': + app = QApplication(sys.argv) + + #实例化3个窗口 + enter_window_instance = enter_window() + image_window_instance = image_window() + image_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + spectral_window_instance = spectral_window() + spectral_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + + enter_window_instance.c.openinfo.emit() + + + #从主窗口弹出影像窗口和光谱窗口 + enter_window_instance.image_mode_bt.clicked.connect(image_window_instance.show) + enter_window_instance.spectral_mode_bt.clicked.connect(spectral_window_instance.show) + + + enter_window_instance.show() + sys.exit(app.exec_()) diff --git a/record_system_v23/arcus_control_ui.py b/record_system_v23/arcus_control_ui.py new file mode 100644 index 0000000..640777f --- /dev/null +++ b/record_system_v23/arcus_control_ui.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'arcus_control_ui.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_arcus_ui(object): + def setupUi(self, arcus_ui): + arcus_ui.setObjectName("arcus_ui") + arcus_ui.resize(354, 171) + self.centralwidget = QtWidgets.QWidget(arcus_ui) + self.centralwidget.setObjectName("centralwidget") + self.left_btn = QtWidgets.QPushButton(self.centralwidget) + self.left_btn.setGeometry(QtCore.QRect(100, 90, 61, 21)) + self.left_btn.setObjectName("left_btn") + self.right_btn = QtWidgets.QPushButton(self.centralwidget) + self.right_btn.setGeometry(QtCore.QRect(170, 90, 61, 23)) + self.right_btn.setObjectName("right_btn") + self.speed_lineEdit = QtWidgets.QLineEdit(self.centralwidget) + self.speed_lineEdit.setGeometry(QtCore.QRect(101, 10, 131, 20)) + self.speed_lineEdit.setObjectName("speed_lineEdit") + self.speed_ScrollBar = QtWidgets.QScrollBar(self.centralwidget) + self.speed_ScrollBar.setGeometry(QtCore.QRect(100, 40, 131, 20)) + self.speed_ScrollBar.setOrientation(QtCore.Qt.Horizontal) + self.speed_ScrollBar.setObjectName("speed_ScrollBar") + arcus_ui.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(arcus_ui) + self.menubar.setGeometry(QtCore.QRect(0, 0, 354, 23)) + self.menubar.setObjectName("menubar") + arcus_ui.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(arcus_ui) + self.statusbar.setObjectName("statusbar") + arcus_ui.setStatusBar(self.statusbar) + + self.retranslateUi(arcus_ui) + QtCore.QMetaObject.connectSlotsByName(arcus_ui) + + def retranslateUi(self, arcus_ui): + _translate = QtCore.QCoreApplication.translate + arcus_ui.setWindowTitle(_translate("arcus_ui", "MainWindow")) + self.left_btn.setText(_translate("arcus_ui", "左")) + self.right_btn.setText(_translate("arcus_ui", "右")) diff --git a/record_system_v23/arcus_control_ui.ui b/record_system_v23/arcus_control_ui.ui new file mode 100644 index 0000000..b494281 --- /dev/null +++ b/record_system_v23/arcus_control_ui.ui @@ -0,0 +1,81 @@ + + + arcus_ui + + + + 0 + 0 + 354 + 171 + + + + MainWindow + + + + + + 100 + 90 + 61 + 21 + + + + + + + + + + 170 + 90 + 61 + 23 + + + + + + + + + + 101 + 10 + 131 + 20 + + + + + + + 100 + 40 + 131 + 20 + + + + Qt::Horizontal + + + + + + + 0 + 0 + 354 + 23 + + + + + + + + diff --git a/record_system_v23/enter_window.py b/record_system_v23/enter_window.py new file mode 100644 index 0000000..9f5f1cd --- /dev/null +++ b/record_system_v23/enter_window.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'enter_window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_enter_Window(object): + def setupUi(self, enter_Window): + enter_Window.setObjectName("enter_Window") + enter_Window.resize(651, 474) + self.centralwidget = QtWidgets.QWidget(enter_Window) + self.centralwidget.setObjectName("centralwidget") + self.image_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.image_mode_bt.setGeometry(QtCore.QRect(200, 180, 111, 51)) + self.image_mode_bt.setObjectName("image_mode_bt") + self.spectral_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.spectral_mode_bt.setGeometry(QtCore.QRect(360, 180, 111, 51)) + self.spectral_mode_bt.setObjectName("spectral_mode_bt") + self.camstatus_tb = QtWidgets.QTextBrowser(self.centralwidget) + self.camstatus_tb.setGeometry(QtCore.QRect(200, 240, 271, 81)) + self.camstatus_tb.setObjectName("camstatus_tb") + enter_Window.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(enter_Window) + self.menubar.setGeometry(QtCore.QRect(0, 0, 651, 26)) + self.menubar.setObjectName("menubar") + enter_Window.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(enter_Window) + self.statusbar.setObjectName("statusbar") + enter_Window.setStatusBar(self.statusbar) + self.actionwew_e = QtWidgets.QAction(enter_Window) + self.actionwew_e.setObjectName("actionwew_e") + + self.retranslateUi(enter_Window) + QtCore.QMetaObject.connectSlotsByName(enter_Window) + + def retranslateUi(self, enter_Window): + _translate = QtCore.QCoreApplication.translate + enter_Window.setWindowTitle(_translate("enter_Window", "主窗口")) + self.image_mode_bt.setText(_translate("enter_Window", "影像模式")) + self.spectral_mode_bt.setText(_translate("enter_Window", "光谱模式")) + self.actionwew_e.setText(_translate("enter_Window", "wew e")) diff --git a/record_system_v23/enter_window.ui b/record_system_v23/enter_window.ui new file mode 100644 index 0000000..4c39418 --- /dev/null +++ b/record_system_v23/enter_window.ui @@ -0,0 +1,73 @@ + + + enter_Window + + + + 0 + 0 + 651 + 474 + + + + 主窗口 + + + + + + 200 + 180 + 111 + 51 + + + + 影像模式 + + + + + + 360 + 180 + 111 + 51 + + + + 光谱模式 + + + + + + 200 + 240 + 271 + 81 + + + + + + + + 0 + 0 + 651 + 26 + + + + + + + wew e + + + + + + diff --git a/record_system_v23/image_Window.py b/record_system_v23/image_Window.py new file mode 100644 index 0000000..53dc349 --- /dev/null +++ b/record_system_v23/image_Window.py @@ -0,0 +1,231 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'image_Window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_image_Window(object): + def setupUi(self, image_Window): + image_Window.setObjectName("image_Window") + image_Window.setEnabled(True) + image_Window.resize(1181, 683) + image_Window.setMouseTracking(False) + image_Window.setAutoFillBackground(False) + image_Window.setSizeGripEnabled(False) + image_Window.setModal(False) + self.verticalLayout_7 = QtWidgets.QVBoxLayout(image_Window) + self.verticalLayout_7.setObjectName("verticalLayout_7") + self.groupBox_5 = QtWidgets.QGroupBox(image_Window) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth()) + self.groupBox_5.setSizePolicy(sizePolicy) + self.groupBox_5.setObjectName("groupBox_5") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox_5) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem) + self.splitter_3 = QtWidgets.QSplitter(self.groupBox_5) + self.splitter_3.setOrientation(QtCore.Qt.Horizontal) + self.splitter_3.setObjectName("splitter_3") + self.layoutWidget = QtWidgets.QWidget(self.splitter_3) + self.layoutWidget.setObjectName("layoutWidget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.label = QtWidgets.QLabel(self.layoutWidget) + self.label.setObjectName("label") + self.verticalLayout.addWidget(self.label) + self.label_4 = QtWidgets.QLabel(self.layoutWidget) + self.label_4.setObjectName("label_4") + self.verticalLayout.addWidget(self.label_4) + self.layoutWidget1 = QtWidgets.QWidget(self.splitter_3) + self.layoutWidget1.setObjectName("layoutWidget1") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.layoutWidget1) + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.filepath_le = QtWidgets.QLineEdit(self.layoutWidget1) + self.filepath_le.setObjectName("filepath_le") + self.verticalLayout_2.addWidget(self.filepath_le) + self.filename_le = QtWidgets.QLineEdit(self.layoutWidget1) + self.filename_le.setObjectName("filename_le") + self.verticalLayout_2.addWidget(self.filename_le) + self.layoutWidget2 = QtWidgets.QWidget(self.splitter_3) + self.layoutWidget2.setObjectName("layoutWidget2") + self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.layoutWidget2) + self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.filepath_bt = QtWidgets.QPushButton(self.layoutWidget2) + self.filepath_bt.setObjectName("filepath_bt") + self.verticalLayout_3.addWidget(self.filepath_bt) + self.save_bt = QtWidgets.QPushButton(self.layoutWidget2) + self.save_bt.setObjectName("save_bt") + self.verticalLayout_3.addWidget(self.save_bt) + self.horizontalLayout_4.addWidget(self.splitter_3) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem1) + self.verticalLayout_7.addWidget(self.groupBox_5) + self.splitter = QtWidgets.QSplitter(image_Window) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName("splitter") + self.groupBox_3 = QtWidgets.QGroupBox(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth()) + self.groupBox_3.setSizePolicy(sizePolicy) + self.groupBox_3.setMinimumSize(QtCore.QSize(0, 0)) + self.groupBox_3.setMaximumSize(QtCore.QSize(2000, 16777215)) + self.groupBox_3.setObjectName("groupBox_3") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_3) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.groupBox = QtWidgets.QGroupBox(self.groupBox_3) + self.groupBox.setObjectName("groupBox") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox) + self.horizontalLayout.setObjectName("horizontalLayout") + self.image_glo = QtWidgets.QGridLayout() + self.image_glo.setObjectName("image_glo") + self.horizontalLayout.addLayout(self.image_glo) + self.verticalLayout_4.addWidget(self.groupBox) + self.statu_tb = QtWidgets.QTextBrowser(self.groupBox_3) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.statu_tb.sizePolicy().hasHeightForWidth()) + self.statu_tb.setSizePolicy(sizePolicy) + self.statu_tb.setMaximumSize(QtCore.QSize(8777215, 100)) + self.statu_tb.setReadOnly(True) + self.statu_tb.setObjectName("statu_tb") + self.verticalLayout_4.addWidget(self.statu_tb) + self.groupBox_4 = QtWidgets.QGroupBox(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_4.sizePolicy().hasHeightForWidth()) + self.groupBox_4.setSizePolicy(sizePolicy) + self.groupBox_4.setObjectName("groupBox_4") + self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.groupBox_4) + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.groupBox_2 = QtWidgets.QGroupBox(self.groupBox_4) + self.groupBox_2.setObjectName("groupBox_2") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox_2) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.focus_glo = QtWidgets.QGridLayout() + self.focus_glo.setObjectName("focus_glo") + self.horizontalLayout_2.addLayout(self.focus_glo) + self.verticalLayout_5.addWidget(self.groupBox_2) + self.groupBox_6 = QtWidgets.QGroupBox(self.groupBox_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_6.sizePolicy().hasHeightForWidth()) + self.groupBox_6.setSizePolicy(sizePolicy) + self.groupBox_6.setObjectName("groupBox_6") + self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_6) + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.groupBox_7 = QtWidgets.QGroupBox(self.groupBox_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_7.sizePolicy().hasHeightForWidth()) + self.groupBox_7.setSizePolicy(sizePolicy) + self.groupBox_7.setMaximumSize(QtCore.QSize(500, 500)) + self.groupBox_7.setObjectName("groupBox_7") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_7) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.label_3 = QtWidgets.QLabel(self.groupBox_7) + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.verticalLayout_6.addWidget(self.label_3) + self.focus_bt = QtWidgets.QPushButton(self.groupBox_7) + self.focus_bt.setObjectName("focus_bt") + self.verticalLayout_6.addWidget(self.focus_bt) + self.exposureTime_bt = QtWidgets.QPushButton(self.groupBox_7) + self.exposureTime_bt.setObjectName("exposureTime_bt") + self.verticalLayout_6.addWidget(self.exposureTime_bt) + self.label_5 = QtWidgets.QLabel(self.groupBox_7) + self.label_5.setAlignment(QtCore.Qt.AlignCenter) + self.label_5.setObjectName("label_5") + self.verticalLayout_6.addWidget(self.label_5) + self.wb_bt = QtWidgets.QPushButton(self.groupBox_7) + self.wb_bt.setObjectName("wb_bt") + self.verticalLayout_6.addWidget(self.wb_bt) + self.label_2 = QtWidgets.QLabel(self.groupBox_7) + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.verticalLayout_6.addWidget(self.label_2) + self.record_bt = QtWidgets.QPushButton(self.groupBox_7) + self.record_bt.setObjectName("record_bt") + self.verticalLayout_6.addWidget(self.record_bt) + self.horizontalLayout_3.addLayout(self.verticalLayout_6) + self.verticalLayout_8 = QtWidgets.QVBoxLayout() + self.verticalLayout_8.setObjectName("verticalLayout_8") + self.framerate_le = QtWidgets.QLineEdit(self.groupBox_7) + self.framerate_le.setReadOnly(False) + self.framerate_le.setObjectName("framerate_le") + self.verticalLayout_8.addWidget(self.framerate_le) + self.stop_focus_bt = QtWidgets.QPushButton(self.groupBox_7) + self.stop_focus_bt.setObjectName("stop_focus_bt") + self.verticalLayout_8.addWidget(self.stop_focus_bt) + self.exposureTime_le = QtWidgets.QLineEdit(self.groupBox_7) + self.exposureTime_le.setObjectName("exposureTime_le") + self.verticalLayout_8.addWidget(self.exposureTime_le) + self.gain_le = QtWidgets.QLineEdit(self.groupBox_7) + self.gain_le.setObjectName("gain_le") + self.verticalLayout_8.addWidget(self.gain_le) + self.dc_bt = QtWidgets.QPushButton(self.groupBox_7) + self.dc_bt.setObjectName("dc_bt") + self.verticalLayout_8.addWidget(self.dc_bt) + self.framenumber_le = QtWidgets.QLineEdit(self.groupBox_7) + self.framenumber_le.setObjectName("framenumber_le") + self.verticalLayout_8.addWidget(self.framenumber_le) + self.motor_bt = QtWidgets.QPushButton(self.groupBox_7) + self.motor_bt.setObjectName("motor_bt") + self.verticalLayout_8.addWidget(self.motor_bt) + self.stop_record_bt = QtWidgets.QPushButton(self.groupBox_7) + self.stop_record_bt.setObjectName("stop_record_bt") + self.verticalLayout_8.addWidget(self.stop_record_bt) + self.horizontalLayout_3.addLayout(self.verticalLayout_8) + self.horizontalLayout_5.addWidget(self.groupBox_7) + spacerItem2 = QtWidgets.QSpacerItem(261, 17, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_5.addItem(spacerItem2) + self.verticalLayout_5.addWidget(self.groupBox_6) + self.verticalLayout_7.addWidget(self.splitter) + + self.retranslateUi(image_Window) + QtCore.QMetaObject.connectSlotsByName(image_Window) + + def retranslateUi(self, image_Window): + _translate = QtCore.QCoreApplication.translate + image_Window.setWindowTitle(_translate("image_Window", "影像窗口")) + self.groupBox_5.setTitle(_translate("image_Window", "GroupBox")) + self.label.setText(_translate("image_Window", "保存路径")) + self.label_4.setText(_translate("image_Window", "文件名")) + self.filepath_bt.setText(_translate("image_Window", "浏览")) + self.save_bt.setText(_translate("image_Window", "保存")) + self.groupBox_3.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox.setTitle(_translate("image_Window", "图像")) + self.groupBox_4.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox_2.setTitle(_translate("image_Window", "光谱")) + self.groupBox_6.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox_7.setTitle(_translate("image_Window", "GroupBox")) + self.label_3.setText(_translate("image_Window", "帧率")) + self.focus_bt.setText(_translate("image_Window", "调焦")) + self.exposureTime_bt.setText(_translate("image_Window", "曝光")) + self.label_5.setText(_translate("image_Window", "gain")) + self.wb_bt.setText(_translate("image_Window", "白板")) + self.label_2.setText(_translate("image_Window", "帧数")) + self.record_bt.setText(_translate("image_Window", "采集")) + self.stop_focus_bt.setText(_translate("image_Window", "停止调焦")) + self.dc_bt.setText(_translate("image_Window", "暗电流")) + self.motor_bt.setText(_translate("image_Window", "马达")) + self.stop_record_bt.setText(_translate("image_Window", "停止采集")) diff --git a/record_system_v23/image_Window.ui b/record_system_v23/image_Window.ui new file mode 100644 index 0000000..c2133b3 --- /dev/null +++ b/record_system_v23/image_Window.ui @@ -0,0 +1,377 @@ + + + image_Window + + + true + + + + 0 + 0 + 1181 + 683 + + + + false + + + 影像窗口 + + + false + + + false + + + false + + + + + + + 0 + 0 + + + + GroupBox + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + + + + 保存路径 + + + + + + + 文件名 + + + + + + + + + + + + + + + + + + + + + 浏览 + + + + + + + 保存 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 2000 + 16777215 + + + + GroupBox + + + + + + 图像 + + + + + + + + + + + + + 0 + 0 + + + + + 8777215 + 100 + + + + true + + + + + + + + + 0 + 0 + + + + GroupBox + + + + + + 光谱 + + + + + + + + + + + + + 0 + 0 + + + + GroupBox + + + + + + + 0 + 0 + + + + + 500 + 500 + + + + GroupBox + + + + + + + + 帧率 + + + Qt::AlignCenter + + + + + + + 调焦 + + + + + + + 曝光 + + + + + + + gain + + + Qt::AlignCenter + + + + + + + 白板 + + + + + + + 帧数 + + + Qt::AlignCenter + + + + + + + 采集 + + + + + + + + + + + false + + + + + + + 停止调焦 + + + + + + + + + + + + + 暗电流 + + + + + + + + + + 马达 + + + + + + + 停止采集 + + + + + + + + + + + + Qt::Horizontal + + + + 261 + 17 + + + + + + + + + + + + + + + + diff --git a/record_system_v23/spectral_Window.py b/record_system_v23/spectral_Window.py new file mode 100644 index 0000000..749f060 --- /dev/null +++ b/record_system_v23/spectral_Window.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'spectral_Window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_spectral_Window(object): + def setupUi(self, spectral_Window): + spectral_Window.setObjectName("spectral_Window") + spectral_Window.resize(792, 523) + self.label = QtWidgets.QLabel(spectral_Window) + self.label.setGeometry(QtCore.QRect(54, 10, 51, 20)) + self.label.setObjectName("label") + self.filepath_le = QtWidgets.QLineEdit(spectral_Window) + self.filepath_le.setGeometry(QtCore.QRect(131, 10, 261, 21)) + self.filepath_le.setObjectName("filepath_le") + self.label_2 = QtWidgets.QLabel(spectral_Window) + self.label_2.setGeometry(QtCore.QRect(54, 40, 41, 20)) + self.label_2.setObjectName("label_2") + self.filename_le = QtWidgets.QLineEdit(spectral_Window) + self.filename_le.setGeometry(QtCore.QRect(131, 40, 261, 21)) + self.filename_le.setObjectName("filename_le") + self.filepath_bt = QtWidgets.QPushButton(spectral_Window) + self.filepath_bt.setGeometry(QtCore.QRect(401, 10, 71, 21)) + self.filepath_bt.setObjectName("filepath_bt") + self.statu_tb = QtWidgets.QTextBrowser(spectral_Window) + self.statu_tb.setGeometry(QtCore.QRect(611, 210, 161, 301)) + self.statu_tb.setObjectName("statu_tb") + self.tabWidget = QtWidgets.QTabWidget(spectral_Window) + self.tabWidget.setGeometry(QtCore.QRect(10, 70, 591, 441)) + self.tabWidget.setObjectName("tabWidget") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.gridLayoutWidget = QtWidgets.QWidget(self.tab) + self.gridLayoutWidget.setGeometry(QtCore.QRect(0, 0, 581, 411)) + self.gridLayoutWidget.setObjectName("gridLayoutWidget") + self.spe_glo = QtWidgets.QGridLayout(self.gridLayoutWidget) + self.spe_glo.setContentsMargins(0, 0, 0, 0) + self.spe_glo.setObjectName("spe_glo") + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QtWidgets.QWidget() + self.tab_2.setObjectName("tab_2") + self.gridLayoutWidget_2 = QtWidgets.QWidget(self.tab_2) + self.gridLayoutWidget_2.setGeometry(QtCore.QRect(-1, -1, 581, 411)) + self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2") + self.align_glo = QtWidgets.QGridLayout(self.gridLayoutWidget_2) + self.align_glo.setContentsMargins(0, 0, 0, 0) + self.align_glo.setObjectName("align_glo") + self.tabWidget.addTab(self.tab_2, "") + self.layoutWidget = QtWidgets.QWidget(spectral_Window) + self.layoutWidget.setGeometry(QtCore.QRect(610, 90, 195, 135)) + self.layoutWidget.setObjectName("layoutWidget") + self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.align_bt = QtWidgets.QPushButton(self.layoutWidget) + self.align_bt.setObjectName("align_bt") + self.gridLayout.addWidget(self.align_bt, 0, 0, 1, 1) + self.stop_align_bt = QtWidgets.QPushButton(self.layoutWidget) + self.stop_align_bt.setObjectName("stop_align_bt") + self.gridLayout.addWidget(self.stop_align_bt, 0, 1, 1, 1) + self.wb_bt = QtWidgets.QPushButton(self.layoutWidget) + self.wb_bt.setObjectName("wb_bt") + self.gridLayout.addWidget(self.wb_bt, 1, 0, 1, 2) + self.dc_bt = QtWidgets.QPushButton(self.layoutWidget) + self.dc_bt.setObjectName("dc_bt") + self.gridLayout.addWidget(self.dc_bt, 2, 0, 1, 2) + self.record_bt = QtWidgets.QPushButton(self.layoutWidget) + self.record_bt.setObjectName("record_bt") + self.gridLayout.addWidget(self.record_bt, 3, 0, 1, 2) + + self.retranslateUi(spectral_Window) + self.tabWidget.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(spectral_Window) + + def retranslateUi(self, spectral_Window): + _translate = QtCore.QCoreApplication.translate + spectral_Window.setWindowTitle(_translate("spectral_Window", "光谱窗口")) + self.label.setText(_translate("spectral_Window", "保存路径")) + self.label_2.setText(_translate("spectral_Window", "文件名")) + self.filepath_bt.setText(_translate("spectral_Window", "浏览")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("spectral_Window", "spe")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("spectral_Window", "align")) + self.align_bt.setText(_translate("spectral_Window", "align")) + self.stop_align_bt.setText(_translate("spectral_Window", "stop align")) + self.wb_bt.setText(_translate("spectral_Window", "曝光/白板")) + self.dc_bt.setText(_translate("spectral_Window", "暗电流")) + self.record_bt.setText(_translate("spectral_Window", "采集")) diff --git a/record_system_v23/spectral_Window.ui b/record_system_v23/spectral_Window.ui new file mode 100644 index 0000000..f2641b7 --- /dev/null +++ b/record_system_v23/spectral_Window.ui @@ -0,0 +1,180 @@ + + + spectral_Window + + + + 0 + 0 + 792 + 523 + + + + 光谱窗口 + + + + + 54 + 10 + 51 + 20 + + + + 保存路径 + + + + + + 131 + 10 + 261 + 21 + + + + + + + 54 + 40 + 41 + 20 + + + + 文件名 + + + + + + 131 + 40 + 261 + 21 + + + + + + + 401 + 10 + 71 + 21 + + + + 浏览 + + + + + + 611 + 210 + 161 + 301 + + + + + + + 10 + 70 + 591 + 441 + + + + 0 + + + + spe + + + + + 0 + 0 + 581 + 411 + + + + + + + + align + + + + + -1 + -1 + 581 + 411 + + + + + + + + + + 610 + 90 + 195 + 135 + + + + + + + align + + + + + + + stop align + + + + + + + 曝光/白板 + + + + + + + 暗电流 + + + + + + + 采集 + + + + + + + + + diff --git a/record_system_v24/2record_system_v24.py b/record_system_v24/2record_system_v24.py new file mode 100644 index 0000000..17ce4d0 --- /dev/null +++ b/record_system_v24/2record_system_v24.py @@ -0,0 +1,1828 @@ +# -*- coding:utf-8 -*- + +''' +在2record system_v2.2的基础上更新: +1、改变了命名以符合PEP 8风格 +2、增加了配置文件 +3、加入温湿度传感器:串口,并将温湿度写入文件 +4、加入异常处理机制(try/except/else/finally),使代码更具有鲁棒性 +5、记录操作流程和异常:通过logging模块实现 +6、 +7、 +''' + +# 内置包 +import os, sys, functools, re, shutil, traceback, time +import subprocess +import datetime # 几种Python执行时间的计算方法:https://blog.csdn.net/wangshuang1631/article/details/54286551 +import logging + +# 三方包 +import numpy as np +from osgeo import gdal +from ximea import xiapi +import configparser +import serial +import serial.tools.list_ports +from serial.serialutil import SerialBase, SerialException + +# 界面包 +import qimage2ndarray +from PyQt5.QtCore import Qt, QRectF, pyqtSignal, QObject, QRunnable, pyqtSlot, QThreadPool, QTimer, QT_VERSION_STR +from PyQt5.QtGui import QPixmap, QImage, QPainterPath +from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, qApp, QDialog, QFileDialog, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem + +from record_system_v24.ui.enter_window import * +from record_system_v24.ui.image_Window import * +from record_system_v24.ui.spectral_Window import * +from record_system_v24.ui.arcus_control_ui import * + +import matplotlib +matplotlib.use("Qt5Agg") # 声明使用QT5 +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.figure import Figure + + +class ArcusWindow(QMainWindow, Ui_arcus_ui): + def __init__(self, parent=None): + super(ArcusWindow, self).__init__(parent) + self.setupUi(self) + + self.left_btn.pressed.connect(self.leftMove) + self.left_btn.released.connect(self.stop) + self.right_btn.pressed.connect(self.rightMove) + self.right_btn.released.connect(self.stop) + + + # self.speed_lineEdit.setText(self.arc.write('HSPD')) + self.speed_lineEdit.textEdited.connect(self.change_speed) + + self.time = time.time() # 控制两次点击后,发送命令的间隔 + + def leftMove(self): + time_now = time.time() + if time_now - self.time > 0.5: + self.time = time.time() + + python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J-' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('左移ok!') + + def rightMove(self): + time_now = time.time() + if time_now - self.time > 0.5: + self.time = time.time() + + python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J+' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + print(output) + # print(error) + print('右移ok!') + + def change_speed(self): + time_now = time.time() + if time_now - self.time > 0.5: + self.time = time.time() + + python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py HSPD=' + str(self.speed_lineEdit.text()) + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('改变速度ok!') + + def stop(self): + self.time = time.time() + + python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py STOP' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('停止ok!') + + +# 主窗口 +class EnterWindow(QMainWindow, Ui_enter_Window): + def __init__(self, parent=None): + super(EnterWindow, self).__init__(parent) + self.setupUi(self) + + # 在刚打开软件在本窗口显示相机状态(是否打开) + self.c = Communicate() + self.c.openinfo.connect(self.printCamInfo) + # self.end_Btn.clicked.connect(self.end_event) # 绑定登陆函数 + # self.exit_Btn.clicked.connect(sys.exit) + + # self.spectral_mode_bt.clicked.connect(self.spectral_window) + self.image_window_instance = ImageWindow() + self.image_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + self.image_mode_bt.clicked.connect(self.image_window_instance.show) + + self.spectral_window_instance = SpectralWindow() + self.spectral_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + self.spectral_mode_bt.clicked.connect(self.spectral_window_instance.show) + + def printCamInfo(self): + self.camstatus_tb.append('相机已打开!') + + +# 主窗口信号类 +class Communicate(QObject): + openinfo = pyqtSignal() + plotsignal = pyqtSignal() + + +class SerialPort(QObject): + def __init__(self): + super(SerialPort, self).__init__() + + self.logger = logging.getLogger('root.serial') + + formatter1 = logging.Formatter('%(asctime)s %(message)s') + temperature_file_handler = logging.FileHandler(os.path.split(__file__)[0] + '//temperature.log') # 输出到文件 + temperature_file_handler.setLevel(logging.DEBUG) + temperature_file_handler.setFormatter(formatter1) + + self.logger.addHandler(temperature_file_handler) + + + + # self.signals = pyqtSignal(tuple) # 为啥这就不行呢? + self.signals = WorkerSignals() + + self.connect_number = 0 # 记录打开串口的次数 + self.serial_port = self.open_serial_port() + + + self.timer = QTimer() + self.timer.timeout.connect(self.receiver_data_from_port) + self.timer.start(1000) + + def open_serial_port(self): + self.connect_number += 1 + port_list = list(serial.tools.list_ports.comports()) # 列出所有可用串口 + # print(port_list) + + if len(port_list) > 0: # 如果可用串口 >0 个 + # 打印出所有串口的信息 + for i in range(0, len(port_list)): + print(port_list[i]) + + # 打开第一个串口 + ser = serial.Serial(port_list[0].device) + # print('温湿度传感器打开成功!') + return ser + elif len(port_list) == 0: # 如果可用串口为0个 + if self.connect_number == 1: + self.logger.info('无可用串口,温湿度传感器不可用!') + else: + self.logger.error('串口连接上之后,断开连接!') + return 1 # 如果返回1,则代表没有可用串口;通过1来判断不执行定时器触发:self.timer.start(1000) + else: # 其他没有考虑到的情况 + return 1 + + def receiver_data_from_port(self): + ''' + 定时器QTimer没隔1s调用此函数一次 → 让串口buffer有足够的数据等待读取 + :return: 无返回值 + + 本函数功能:1、串口中接收字节数据,有两种帧 → 代表两种数据 + 2、判断帧头位置和本帧数据类型 + 3、判断帧尾 → 等效判断本帧数据是否完全 + 4、如果数据帧完整 → 解析数据,将温度湿度显示到界面上和写入到文件中 + ''' + try: + if self.serial_port.in_waiting: # 如果串口buffer有数据等待读取 + bytes_receive = self.serial_port.read(self.serial_port.inWaiting()) # 读取串口buffer的数据 + # print(len(bytes_receive)) + + # 判断帧头位置,通过正则表达式 + hex_receive = bytes_receive.hex() # 一个字节需要一个两位16进制数表示,所以:len(hex_receive) = len(bytes_receive) * 2 + p = re.compile('5a5a*') + index_head = [i.start() / 2 for i in re.finditer(p, hex_receive)] # re.finditer() + # print(hex_receive) + # print(index_head) + except SerialException: # 程序打开时,温湿度传感器的串口工作正常;如果程序运行中拔掉串口就会出现此异常 + self.logger.error('在程序运行中温湿度传感器的串口出现问题!') + + # 再次尝试打开串口 + self.serial_port = self.open_serial_port() + if not isinstance(self.serial_port, int): + self.logger.info('再次尝试连接温湿度传感器成功!') + else: + self.logger.info('再次尝试连接温湿度传感器失败!') + except AttributeError: # int object has no attribute: in_waiting + self.timer.stop() + self.logger.info('停止定时触发器!') + except Exception as e: # 未出现过的异常。当第一次出现时,需要编写代码处理,先写入日志文件(log) + self.logger.critical('未知错误!') + else: # 当没有捕获到异常时,代表串口数据获取成功 → 执行数据解析 + # 解析数据 + try: + if len(index_head) != 0: + Lux = 1.0 + T = 1.0 + P = 1.0 + Hum = 1.0 + H = 1.0 + Lux_full = 0 # 判断光照帧的数据是否完整。0:不完整;1:完整; + T_full = 0 # 判断温度帧的数据是否完整。0:不完整;1:完整; + try: + for i in index_head: # 循环遍历每个帧头 + if bytes_receive[int(i) + 2] == 21: # 0x15=21,判断帧头类型 + if sum(bytes_receive[int(i):int(i) + 8]) & 0xff == bytes_receive[int(i) + 8]: # 判断帧尾是否正确 + # print('光照帧的帧尾正确!') + + Lux_full = 1 # 如果帧尾,此帧数据数完整的 + Lux = ((bytes_receive[int(i) + 4] << 24) | (bytes_receive[int(i) + 5] << 16) | ( + bytes_receive[int(i) + 6] << 8) | bytes_receive[int(i) + 7]) / 100 + if bytes_receive[int(i) + 2] == 69: # 0x45=69,判断帧头类型 + if sum(bytes_receive[int(i):int(i) + 14]) & 0xff == bytes_receive[int(i) + 14]: # 判断帧尾是否正确 + # print('温度帧的帧尾正确!') + + T_full = 1 # 当执行这段代码时,代表帧头帧尾都正常,此帧数据数完整的 + T = ((bytes_receive[int(i) + 4] << 8) | bytes_receive[int(i) + 5]) / 100 + P = ((bytes_receive[int(i) + 6] << 24) | (bytes_receive[int(i) + 7] << 16) | ( + bytes_receive[int(i) + 8] << 8) | bytes_receive[ + int(i) + 9]) / 100 + Hum = ((bytes_receive[int(i) + 10] << 8) | bytes_receive[int(i) + 11]) / 100 + H = ((bytes_receive[int(i) + 12] << 8) | bytes_receive[int(i) + 13]) / 100 + except IndexError as e: # 当出现帧头,但是帧头到帧尾的数据不全 → 在判断帧尾是否正确时就会出现索引越界 + # print('----------------------索引越界!') + pass + except Exception: # 当出现前面没有解决的异常时,前面的异常捕捉就失效。最后通过异常基类来捕捉 → 代表需要修改代码进行处理的新异常 + # print('---------------------------------没遇见过的异常') + pass + + # 将数据显示和写入文件 + if Lux_full + T_full == 2: # x + y == 2代表温度帧和光照帧都完整 + # self.t_label.setVisible(True) + # self.hum_label.setVisible(True) + # self.t_label.setText('温度:' + str(T)) + # self.hum_label.setText('湿度:' + str(Hum)) + print('发送数据') + + self.signals.serial.emit((str(T), str(Hum))) + self.logger.debug('%s %s', str(T), str(Hum)) + + # print('光照强度:%f' % Lux) + # print('温度:%f' % T) + # print('气压:%f' % P) + # print('湿度:%f' % Hum) + # print('海拔:%f' % H) + # print() + elif Lux_full + T_full == 1: + # print('只有一个数据帧是完整的。(光照帧或者温度帧)') + # print() + pass + except UnboundLocalError: + # print(2222222222222222222222222222222) + # traceback.print_exc() + pass + except Exception: + self.logger.critical('未知错误!') + finally: # 不管有没有捕获到异常都会执行,一般用作资源回收 + pass + + +# 图像窗口 +class ImageWindow(QDialog, Ui_image_Window): + def __init__(self, parent=None): + ''' + The super().__init__() method invokes the base class constructor from the MyForm class, + that is, the constructor of the QDialog class is invoked from MyForm class to indicate that + QDialog is displayed through this class iss a top-level window. + ''' + super(ImageWindow, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + + self.arcus_window_instance = ArcusWindow() + self.image_mode_motor_bt.clicked.connect(self.arcus_window_instance.show) + + # log + self.logger = logging.getLogger('root.image') + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + image_operate_file_handler = logging.FileHandler("image_operate.log") # 输出到文件 + image_operate_file_handler.setLevel(logging.INFO) + image_operate_file_handler.setFormatter(formatter) + self.logger.addHandler(image_operate_file_handler) + + # 在窗口中显示串口接收的温度/湿度 + serial_port.signals.serial.connect(self.temperature) + + # 采集影像时,边采集边刷新显示 + # self.plotsignal = pyqtSignal() # 直接这样建立信号执行时会报错 + self.plotsignal = Communicate() + self.plotsignal.plotsignal.connect(self.plotimg) + + #建立进程池 + # https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + #初始化窗口中的值 + self.framenumber_le.setText(str(system_setting.frame_number)) + CameraOperation.framenumber_input = system_setting.frame_number + CameraOperation.rgb = np.ones((3, int(system_setting.frame_number), int( + (CameraOperation.endColumn - CameraOperation.startColumn) / CameraOperation.bin_spatial))) + self.framerate_le.setText(str(system_setting.framerate)) + self.exposureTime_le.setText(str(system_setting.exposure_time)) + self.gain_le.setText(str(system_setting.gain)) + self.filename_le.setText(system_setting.default_image_name) + self.filepath_le.setText(system_setting.image_dir) + + # self.framenumber_le.setText(str(CameraOperation.framenumber_input)) + # self.framerate_le.setText(str(CameraOperation.framerate_input)) + # self.exposureTime_le.setText(str(CameraOperation.exposureTime_input)) + # self.gain_le.setText(str(CameraOperation.gain_input)) + # self.filename_le.setText(system_setting.default_image_name) + # self.filepath_le.setText(system_setting.image_dir) + + # #手动改变窗口中的值,然后将值写入camera_operation类对应的变量中 + # self.exposureTime_le.textEdited.connect(self.onchange2) + # self.exposureTime_le.textChanged.connect(self.onchange)# 将 自动曝光返回到QLineEdit中的值 写入到camera_operation.exposureTime_input + # self.gain_le.textEdited.connect(self.onchange2) + # self.gain_le.textChanged.connect(self.onchange)# 将 自动曝光返回到QLineEdit中的值 写入到camera_operation.gain_input + # self.framerate_le.textEdited.connect(self.onchange2) + # self.framenumber_le.textEdited.connect(self.onchange) + # self.filename_le.textEdited.connect(self.onchange) + # self.filepath_bt.clicked.connect(self.directory_select) + # self.filepath_le.textEdited.connect(self.onchange) + + # 显示影像和调焦 + self.myImageFigure = MyImageFigure() + self.image_glo.addWidget(self.myImageFigure) + self.myFocusFigure = MySpectralFigureFocus() + self.focus_glo.addWidget(self.myFocusFigure) + + #操作光谱仪 + ## 注释的代码没有使用多线程,所以会造成一采集数据界面就卡死的情况 + # self.focus_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.dc_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.save_bt.clicked.connect(camera_operation.savedata) + self.image_mode_exposureTime_bt.clicked.connect(self.run) + self.image_mode_focus_bt.clicked.connect(self.run) + # 停止调焦和采集操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.image_mode_stop_focus_bt.clicked.connect(self.stop_focus) + self.image_mode_stop_record_bt.clicked.connect(self.stop_record) + self.image_mode_dc_bt.clicked.connect(self.run) + self.image_mode_wb_bt.clicked.connect(self.run) + self.image_mode_record_bt.clicked.connect(self.run) + self.save_bt.clicked.connect(self.save_image) + + # 手动改变窗口中的值,然后将值写入camera_operation类对应的变量中 + self.exposureTime_le.textEdited.connect(self.text_edited) + self.gain_le.textEdited.connect(self.text_edited) + self.framerate_le.textEdited.connect(self.text_edited) + self.framenumber_le.textEdited.connect(self.text_edited) + self.filename_le.textEdited.connect(self.text_edited) + self.filepath_le.textEdited.connect(self.text_edited) + + self.filepath_bt.clicked.connect(self.directory_select) + + # 手动修改界面中的值后,为相机重新设置如下参数:exposure, gain, framerate + def text_edited(self): + try: + system_setting.exposure_time = int(self.exposureTime_le.text()) + system_setting.gain = int(float(self.gain_le.text())) + system_setting.framerate = int(self.framerate_le.text()) + system_setting.frame_number = int(self.framenumber_le.text()) + + system_setting.signals.image_signal.emit( + {'exposure_time': int(self.exposureTime_le.text()), 'gain': int(self.gain_le.text()), + 'framerate': int(self.framerate_le.text()), 'frame_number': int(self.framenumber_le.text())}) + except: + traceback.print_exc() + + CameraOperation.set_exposure_gain_framerate(camera) + + CameraOperation.fn = self.filename_le.text() + + CameraOperation.framenumber_input = system_setting.frame_number + CameraOperation.rgb = np.ones((3, int(system_setting.frame_number), int( + (CameraOperation.endColumn - CameraOperation.startColumn) / CameraOperation.bin_spatial))) + + # 将自动曝光返回值写入到界面中的QLineEdit和system_setting对象中 + def post_auto_expose(self, result): + ''' + :param result: return cam.get_exposure(), cam.get_gain(), cls.autoexposure_feedback + :return: + ''' + + # 将自动曝光得到的结果显示到界面(QLineEdit) + print(result) + self.exposureTime_le.setText(str(result[0])) + self.gain_le.setText(str(result[1])) + + # 为了防止后面的信号执行延迟;如果延迟,设置曝光时间就会设置为system_setting.exposure_time的旧值 + system_setting.exposure_time = result[0] + system_setting.gain = result[1] + + try: + system_setting.signals.image_signal.emit({'exposure_time': result[0], 'gain': result[1]}) + except: + traceback.print_exc() + + CameraOperation.set_exposure_gain_framerate(camera) + + if result[2] == 1: + QMessageBox.information(self, '曝光提示', '光线不足,曝光时间已设置为最大!', QMessageBox.Yes) + CameraOperation.autoexposure_feedback = 0 + + def temperature(self, data): + try: + self.t_label.setText('温度:' + data[0]) + self.hum_label.setText('湿度:' + data[1]) + except: + print('有问题') + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + self.t_label.setText('温度:无数据') + self.hum_label.setText('湿度:无数据') + + def timer_start(self): + ''' + 本函数目的是在self.timer.start(1000)外包裹一层(有点装饰器的感觉),加入判断: + 1、如果self.serial_port为串口类型,就触发定时器self.timer.start(1000) + 2、如果self.serial_port == 1(为int类型),则代表硬件中没有温湿度传感器,就没必要触发定时器self.timer.start(1000) + :return: 无返回值 + ''' + + if isinstance(self.serial_port, serial.serialwin32.Serial): + self.timer.start(1000) + elif isinstance(self.serial_port, int): + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + else: + pass + + def plotimg(self): + worker = Worker(CameraOperation.plotimg) + self.threadpool.start(worker) + + def stop_focus(self): + CameraOperation.focus = False + + def stop_record(self): + CameraOperation.record = False + + # 调焦、采集暗电流、采集白板、采集影像 都通过此函数 + def run(self): + self.qt_sender = self.sender().objectName() + + # 操作状态显示 + if self.qt_sender == 'image_mode_exposureTime_bt': + self.statu_tb.append('自动曝光...') + elif self.qt_sender == 'image_mode_focus_bt': + self.statu_tb.append('调焦...') + elif self.qt_sender == 'image_mode_dc_bt': + self.statu_tb.append('采集暗电流...') + elif self.qt_sender == 'image_mode_wb_bt': + self.statu_tb.append('采集白板...') + elif self.qt_sender == 'image_mode_record_bt': + self.statu_tb.append('采集影像...') + + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(CameraOperation.start_AcquireData, camera, self.qt_sender) + + worker.signals.error.connect(self.operate_failed) + worker.signals.finished.connect(self.operate_success) + if self.qt_sender == 'image_mode_exposureTime_bt': + ''' + 曝光参数的设置过程: + (1)曝光参数返回到界面中的QLineEdit; + (2)通过QLineEdit的textChanged事件将值写入到camera_operation对应的变量; + (3)为相机设置参数:1)通过worker的finished信号【本程序使用】2)也可以通过QLineEdit的textChanged事件调用self.set_exposure函数,为相机设置参数 + 这种过程的好处是界面显示的曝光参数和实际设置的是同步的 + ''' + worker.signals.result.connect(self.post_auto_expose) + + self.threadpool.start(worker) + + def operate_failed(self, traceback_info): + if traceback_info[0] == xiapi.Xi_error: + if self.qt_sender == 'image_mode_exposureTime_bt': + self.statu_tb.append('自动曝光失败!') + self.logger.error('自动曝光失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_focus_bt': + self.statu_tb.append('调焦失败!') + self.logger.error('调焦失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_dc_bt': + self.statu_tb.append('采集暗电流失败!') + self.logger.error('采集暗电流失败:光谱仪正在工作中,请稍等\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_wb_bt': + self.statu_tb.append('采集白板失败!') + self.logger.error('采集白板失败:光谱仪正在工作中,请稍等\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_record_bt': + self.statu_tb.append('采集影像失败!') + self.logger.error('采集影像失败:光谱仪正在工作中,请稍等\n%s', traceback_info[2]) + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + + def operate_success(self): + if self.qt_sender == 'image_mode_exposureTime_bt': + self.statu_tb.append('自动曝光成功!') + self.logger.info('自动曝光成功!') + elif self.qt_sender == 'image_mode_focus_bt': + self.statu_tb.append('调焦成功!') + self.logger.info('调焦成功!') + elif self.qt_sender == 'image_mode_dc_bt': + self.statu_tb.append('采集暗电流成功!') + self.logger.info('采集暗电流成功!') + elif self.qt_sender == 'image_mode_wb_bt': + self.statu_tb.append('采集白板成功!') + self.logger.info('采集白板成功!') + elif self.qt_sender == 'image_mode_record_bt': + self.statu_tb.append('采集影像成功!') + self.logger.info('采集影像成功!') + + def save_image(self): + # 操作状态显示 + self.statu_tb.append('保存影像...') + + worker = Worker(CameraOperation.savedata) + self.threadpool.start(worker) + + # 操作状态显示 + worker.signals.finished.connect(lambda: self.statu_tb.append('保存影像成功!')) + + self.logger.info('保存影像!') + + def directory_select(self): + dirpath = QFileDialog.getExistingDirectory(self, '选择存储路径文件夹', '/home') + + # 当在文件夹选择窗口中点击取消时,不重设路径 + if dirpath != '': + self.filepath_le.setText(dirpath) + system_setting.signals.image_signal.emit({'image_dir': dirpath}) + + self.logger.info('选择影像保存路径!') + + +# 光谱窗口 +class SpectralWindow(QDialog, Ui_spectral_Window): + def __init__(self, parent=None): + super(SpectralWindow, self).__init__(parent) + self.setupUi(self) + + # log + self.logger = logging.getLogger('root.spectral') + + # 在窗口中显示串口接收的温度/湿度 + serial_port.signals.serial.connect(self.temperature) + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + spectral_operate_file_handler = logging.FileHandler("spectral_operate.log") # 输出到文件 + spectral_operate_file_handler.setLevel(logging.INFO) + spectral_operate_file_handler.setFormatter(formatter) + self.logger.addHandler(spectral_operate_file_handler) + + # 建立进程池 + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 初始化值 + self.filename_le.setText('test') + self.filepath_le.setText(os.getcwd()) + + #手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + self.filepath_bt.clicked.connect(self.directory_select) + self.filename_le.textEdited.connect(self.onchange) + self.filepath_le.textEdited.connect(self.onchange) + + + # 显示光谱和align + self.spectralFigure = MySpectralFigureSpectral() + self.spe_glo.addWidget(self.spectralFigure) + self.alignFigure = MyImageFigure() + self.align_glo.addWidget(self.alignFigure) + + #操作光谱仪 + # self.dc_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + self.spectral_mode_wb_bt.clicked.connect(self.run) # 曝光 + 采集白板 + self.spectral_mode_align_bt.clicked.connect(self.run) + self.spectral_mode_stop_align_bt.clicked.connect(self.stop_align) # 这个操作非常简单,耗时非常短,瞬间可回到event loop;所以不需要多线程 + self.spectral_mode_dc_bt.clicked.connect(self.run) + self.spectral_mode_record_bt.clicked.connect(self.run) + + def temperature(self, data): + try: + self.t_label.setText('温度:' + data[0]) + self.hum_label.setText('湿度:' + data[1]) + except: + traceback.print_exc() + print('有问题') + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + self.t_label.setText('温度:无数据') + self.hum_label.setText('湿度:无数据') + + def stop_align(self): + SpectralCameraOperation.align = False + + def run(self): + self.qt_sender = self.sender().objectName() + + # 操作状态显示 + if self.qt_sender == 'spectral_mode_wb_bt': + self.statu_tb.append('曝光/白板...') + self.logger.info('曝光/白板...') + elif self.qt_sender == 'spectral_mode_align_bt': + self.statu_tb.append('align...') + self.logger.info('align...') + elif self.qt_sender == 'spectral_mode_dc_bt': + self.statu_tb.append('采集暗电流...') + self.logger.info('采集暗电流...') + elif self.qt_sender == 'spectral_mode_record_bt': + self.statu_tb.append('采集光谱...') + self.logger.info('采集光谱...') + + worker = Worker(SpectralCameraOperation.start_AcquireData, camera, self.qt_sender) + worker.signals.finished.connect(self.operate_success) + worker.signals.error.connect(self.operate_failed) + # worker.signals.result.connect() + + self.threadpool.start(worker) + + def operate_failed(self, traceback_info): + if traceback_info[0] == xiapi.Xi_error: + if self.qt_sender == 'spectral_mode_wb_bt': + self.statu_tb.append('曝光/白板失败!') + self.logger.error('曝光/白板失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_align_bt': + self.statu_tb.append('align 失败!') + self.logger.error('align 失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_dc_bt': + self.statu_tb.append('采集暗电流失败!') + self.logger.error('采集暗电流失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_record_bt': + self.statu_tb.append('采集光谱失败!') + self.logger.error('采集光谱失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + + def operate_success(self): + # 操作状态显示 + if self.qt_sender == 'spectral_mode_wb_bt': + self.statu_tb.append('曝光/白板成功!') + self.logger.info('曝光/白板成功!') + elif self.qt_sender == 'spectral_mode_align_bt': + self.statu_tb.append('align successfully!') + self.logger.info('align successfully!') + elif self.qt_sender == 'spectral_mode_dc_bt': + self.statu_tb.append('采集暗电流成功!') + self.logger.info('采集暗电流成功!') + elif self.qt_sender == 'spectral_mode_record_bt': + self.statu_tb.append('采集光谱成功!') + self.logger.info('采集光谱成功!') + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + def onchange(self): + SpectralCameraOperation.fn = self.filename_le.text() + + def directory_select(self): + dirpath = QFileDialog.getExistingDirectory(self, '选择存储路径文件夹', '/home') + + # 当在文件夹选择窗口中点击取消时,不重设路径 + if dirpath != '': + self.filepath_le.setText(dirpath) + system_setting.signals.spectral_signal.emit({'spectral_dir': dirpath}) + self.logger.info('选择光谱保存路径!') + + +# 画图类,用于:画出采集到的光谱;调焦(影响模式调焦) +class MySpectralFigureFocus(FigureCanvas): + def __init__(self, width=5, height=4, dpi=100): + #第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + + #第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MySpectralFigureFocus, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + + #第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + self.axes.set_xlabel('Wavelength (nm)') + #第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def plot(self, spectral): + self.axes.clear() + self.axes.plot(spectral) + + +class MySpectralFigureSpectral(FigureCanvas): + def __init__(self, width=5, height=4, dpi=100): + # 第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + + # 第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MySpectralFigureSpectral, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + + # 第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + self.axes.set_xlabel('Wavelength (nm)') + self.axes.set_ylim(0, 1.2) + self.axes.set_ylabel('reflectance') + #第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def plot(self, Wavelength, spectral): + self.axes.clear() + self.axes.set_xlabel('Wavelength (nm)') + self.axes.set_ylim(0, 1.2) + self.axes.set_ylabel('reflectance') + self.axes.plot(Wavelength, spectral) + + +# 画图类,用于:画出采集到的图像;显示帧流(光谱模式对准光纤) +class MyImageFigure(FigureCanvas): + def __init__(self, width=5, height=4, dpi=100): + # 第一步:创建一个创建Figure + self.fig = Figure(figsize=(width, height), dpi=dpi) + # 第二步:在父类中激活Figure窗口 + # this is the Canvas Widget that displays the `figure` + # it takes the `figure` instance as a parameter to __init__ + super(MyImageFigure, self).__init__(self.fig) # 此句必不可少,否则不能显示图形 + # 第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) + self.axes = self.fig.add_subplot(1, 1, 1) + self.axes.set_xticks([]) + self.axes.set_yticks([]) + # 第四步:就是画图,【可以在此类中画,也可以在其它类中画】 + def plot(self, frame): + self.axes.clear() + self.axes.set_xticks([]) + self.axes.set_yticks([]) + self.axes.imshow(frame) + + +class WorkerSignals(QObject): + ''' + Defines the signals available from a running worker thread. + + Supported signals are: + + finished + No data + + error + `tuple` (exctype, value, traceback.format_exc() ) + + result + `object` data returned from processing, anything + + progress + `int` indicating % progress + + ''' + finished = pyqtSignal() + error = pyqtSignal(tuple) + result = pyqtSignal(object) + progress = pyqtSignal(int) # 可以用作进度条 + + serial = pyqtSignal(object) + + image_signal = pyqtSignal(dict) + spectral_signal = pyqtSignal(dict) + + +# https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ +# 用于qt多线程:运行long-time task +class Worker(QRunnable): + ''' + Worker thread + + Inherits from QRunnable to handler worker thread setup, signals and wrap-up. + + :param callback: The function callback to run on this worker thread. Supplied args and + kwargs will be passed through to the runner. + :type callback: function + :param args: Arguments to pass to the callback function + :param kwargs: Keywords to pass to the callback function + + ''' + + def __init__(self, fn, *args, **kwargs): + super(Worker, self).__init__() + + # Store constructor arguments (re-used for processing) + self.fn = fn + self.args = args + self.kwargs = kwargs + self.signals = WorkerSignals() + + # Add the callback to our kwargs + # self.kwargs['progress_callback'] = self.signals.progress + + @pyqtSlot() + def run(self): + ''' + Initialise the runner function with passed args, kwargs. + ''' + try: + result = self.fn(*self.args, **self.kwargs) + except Exception: + exctype, value = sys.exc_info()[:2] + self.signals.error.emit((exctype, value, traceback.format_exc())) + else: + self.signals.finished.emit() # Done + self.signals.result.emit(result) # Return the result of the processing + finally: + pass + + +# 读写影像类 +class Grid(object): + + #读图像文件 + @classmethod + def read_img(cls, filename, xoff=0, yoff=0, im_width=None, im_height=None): + try: + dataset = gdal.Open(filename) # 打开文件 + if im_width == None: + im_width = dataset.RasterXSize # 栅格矩阵的列数 + if im_height == None: + im_height = dataset.RasterYSize # 栅格矩阵的行数 + num_bands = dataset.RasterCount # 栅格矩阵的波段数 + im_geotrans = dataset.GetGeoTransform() # 仿射矩阵 + im_proj = dataset.GetProjection() # 地图投影信息 + im_data = dataset.ReadAsArray(xoff, yoff, im_width, im_height) # 将数据写成数组,对应栅格矩阵 + del dataset + return im_proj, im_geotrans, im_data + except: + sys.exit() + + #写文件,以写成tif为例 + @classmethod + def write_img(cls, dst_filename, data): + format = "ENVI" + driver = gdal.GetDriverByName(format) + RasterXSize = data.shape[2] # 遥感影像的sample(列数) + RasterYSize = data.shape[1] # 遥感影像的line(行数) + band = data.shape[0] + # driver.Create()函数中RasterXSize代表影像的sample(列数),RasterYSize代表影像的line(行数) + dst_ds = driver.Create(dst_filename, RasterXSize, RasterYSize, band, gdal.GDT_Float32) + for i in range(band): + dst_ds.GetRasterBand(i + 1).WriteArray(data[i, :, :]) # gdal的band从1开始,所以dst_ds.GetRasterBand(i+1) + dst_ds = None + + +# 影像模式类:相关的函数和变量 +class CameraOperation(object): + + # 传感器有效范围 + # startRow = 339 + # endRow = 639 + # startColumn = 285 + # endColumn = 1650 + # 影像中400-560列:685-845 + startRow = 339 + endRow = 639 + startColumn = 285 + endColumn = 1649 + + # 转辐亮度 + rad_or_not = False + img_gain = r'D:\py_program\corning410\corning410_radiance_calibration\jfq_dn_gain' + _, _, gain = Grid.read_img(img_gain) + gain = gain.astype(np.float) + cal_it = 6059 + target_it = None + gain_scale = None + + @classmethod + # 手动改变界面上的曝光值和gain值后,设置相机的曝光值和gain值所用 + def set_exposure_gain_framerate(cls, cam): + # settings,cam.set_param("exposure",10000) + cam.set_framerate(int(system_setting.framerate)) + cam.set_exposure(int(system_setting.exposure_time)) # 曝光时间单位为微秒,1s共有1000000微秒 + cam.set_gain(int(float(system_setting.gain))) #int('0.0')会报错,int(float('0.0'))不会报错 + + print('Exposure was set to %i us' % cam.get_exposure()) + print('Framerate was set to %i FPS' % cam.get_framerate()) + # ('Framerate: ' + str(cam.get_framerate()) + ' FPS')这样连接字符串会浪费内存 + enter_window_instance.image_window_instance.statu_tb.append("%s%s%s" % ('Framerate: ', str(cam.get_framerate()), ' FPS')) + enter_window_instance.image_window_instance.statu_tb.append("%s%s%s" % ('Exposure: ', str(cam.get_exposure()), ' us')) + enter_window_instance.image_window_instance.statu_tb.append("%s%s%s" % ('Gain: ', str(cam.get_gain()), ' dB')) + + # 开始采集数据 + framenumber_input = 100 # 随便给个初始值(初始值要和framenumber_le控件初始值一致),从image_window获取的手动输入的帧数 + image_dc = 1 # 随便给个初始值,此变量用于存储采集到的暗电流影像 + image_wb = 1 # 随便给个初始值,此变量用于存储采集到的白板影像 + focus = True # 用于停止调焦 + record = True # 用于停止采集 + img_datatype = 12 # 在头文件中确定影像数据类型 + # bin相关设置 + bin_spectral = 1 # 光谱bin + bin_spatial = 1 # 空间bin + k = np.arange(endRow - startRow)[0::bin_spectral] + l = np.arange(endColumn - startColumn)[0::bin_spatial] + + rgb = np.zeros((3, int(framenumber_input), int((endColumn - startColumn) / bin_spatial))) + + autoexposure_feedback = 0 # 指示:自动曝光所得到的shutter值是否为最大;如果为最大→值设置为1 + @classmethod + def start_AcquireData(cls, cam, qt_sender): # qt_sender是指qt窗口中事件的发生者 + # 创建img = xiapi.Image()前需要设置一系列img参数,例如:格式、位深度、 + # 如果格式设置为XI_RAW8,image_raw_numpy.dtype -> dtype('uint8'), uint8 + # 如果格式设置为XI_RAW16,image_raw_numpy.dtype -> dtype(' int(1 / int(system_setting.framerate) * 10**6): + cam.set_exposure(int(1 / int(system_setting.framerate) * 10**6)) + cls.autoexposure_feedback = 1 + + else: + cam.set_exposure(cam.get_exposure()) + + + print('Framerate was set to %i FPS' % cam.get_framerate()) + print('Exposure was set to %i us' % cam.get_exposure()) + print('Gain was set to %i dB' % cam.get_gain()) + + # 如果点击“调焦”按钮 + if qt_sender == 'image_mode_focus_bt': + # cls.set_exposureTime(cam) + + # 当关闭调焦后,再次打开调焦功能需要将cls.focus的值从False变为True + if not cls.focus: + cls.focus = True + + cam.start_acquisition() + + while cls.focus: + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + enter_window_instance.image_window_instance.myImageFigure.plot(image_container) + enter_window_instance.image_window_instance.myImageFigure.draw() + enter_window_instance.image_window_instance.myFocusFigure.plot(image_container[150, :]) + enter_window_instance.image_window_instance.myFocusFigure.draw() + + # 如果点击“白板”按钮,采集并保存白板影像到image_wb + if qt_sender == 'image_mode_wb_bt': + framenumber = 10 + image_container = np.empty((cls.endRow - cls.startRow, framenumber, cls.endColumn - cls.startColumn)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + image_container = image_container.mean(axis=1) + + # 光谱bin和空间bin + if cls.bin_spectral != 1: + image_container_bin_spectral = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), cls.endColumn - cls.startColumn)) + image_container_bin = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), + int((cls.endColumn - cls.startColumn) / cls.bin_spatial))) + + for i in range(image_container_bin_spectral.shape[0]): + for j in range(cls.bin_spectral): + image_container_bin_spectral[i] += image_container[cls.k[i] + j] + # 光谱bin完成后,进行空间bin + for i in range(image_container_bin.shape[1]): + for j in range(cls.bin_spatial): + image_container_bin[:, i] += image_container_bin_spectral[:, cls.l[i] + j] + else: + image_container_bin = image_container + + # 白板扣除暗电流放在暗电流采集中 + cls.image_wb = image_container_bin + + # 如果点击“暗电流”按钮,采集并保存暗电流影像到image_dc + if qt_sender == 'image_mode_dc_bt': + framenumber = 10 + image_container = np.empty((cls.endRow - cls.startRow, framenumber, cls.endColumn - cls.startColumn)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + image_container = image_container.mean(axis=1) + + # 光谱bin和空间bin + if cls.bin_spectral != 1: + image_container_bin_spectral = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), cls.endColumn - cls.startColumn)) + image_container_bin = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), + int((cls.endColumn - cls.startColumn) / cls.bin_spatial))) + + for i in range(image_container_bin_spectral.shape[0]): + for j in range(cls.bin_spectral): + image_container_bin_spectral[i] += image_container[cls.k[i] + j] + # 光谱bin完成后,进行空间bin + for i in range(image_container_bin.shape[1]): + for j in range(cls.bin_spatial): + image_container_bin[:, i] += image_container_bin_spectral[:, cls.l[i] + j] + else: + image_container_bin = image_container + + cls.image_dc = image_container_bin + cls.image_wb = cls.image_wb - cls.image_dc + + # 如果点击“采集”按钮,自动去除暗电流,并且转化成反射率 + if qt_sender == 'image_mode_record_bt': + frameCount = 1 # 统计采集的帧数,用于停止采集使用 + + # 当停止采集后,再次开始采集需要将cls.record的值从False变为True + if not cls.record: + cls.record = True + + # 开始马达 + try: + # D:\py27_program\arcus\ArcusDevice.py + python2_command = r'D:\software\Anaconda3\envs\py27_32\python2.exe ' + os.path.dirname(__file__) + '/ArcusDevice.py' + ' CLR PX=0 EO=1 J+' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + except: + pass + + + # 开始采集数据 并且 将数据写入到硬盘中 + cam.start_acquisition() + with open('corning410_test', 'wb') as f: + + print('Starting data acquisition...') + startTime = datetime.datetime.now() + + while cls.record: + cam.get_image(img) # get data and pass them from camera to img + # image_raw_numpy.dtype -> dtype(' maxout] = maxout + img_out = np.uint8(img_new) + return img_out + else: # 对于彩色照片,需要先单独对每个波段拉伸 + img_new = np.empty(img.shape) + for i in range(img.shape[2]): + low = np.percentile(img[:, :, i], lowPercentile) + up = np.percentile(img[:, :, i], highPercentile) + + img_new[:, :, i] = minout + ((img[:, :, i] - low) / (up - low)) * (maxout - minout) + img_new[:, :, i][img_new[:, :, i] < minout] = minout + img_new[:, :, i][img_new[:, :, i] > maxout] = maxout + img_out = np.uint8(img_new) + return img_out + + @classmethod + def close_camera(cls, cam): + # stop communication + cam.close_device() + + +# 光谱模式类:相关的函数和变量 +class SpectralCameraOperation(object): + # 传感器有效范围 + # startRow = 339 + # endRow = 639 + # startColumn = 285 + # endColumn = 1650 + # 影像中400-560列:685-845 + startRow = 339 + endRow = 639 + startColumn = 285 + endColumn = 1649 + + # 转辐亮度 + rad_or_not = False + img_gain = r'D:\py_program\corning410\corning410_radiance_calibration\jfq_dn_gain' + _, _, gain = Grid.read_img(img_gain) + gain = gain.astype(np.float) + cal_it = 6059 + target_it = None + gain_scale = None + + # 开始采集数据 + fn = 'test' # 随便给个初始值(初始值要和filename_le控件初始值一致),从spectral_window获取的手动输入的帧率 + + framenumber = 10 # 每条光谱为多少帧平均得到 + spectral_container = np.empty((endRow - startRow, framenumber, endColumn - startColumn)).astype(np.float) + # spectral_container = np.empty((300, framenumber, 3)).astype(np.float64) + + align = True # 用于对准光纤 + image_dc = np.empty((endRow - startRow, endColumn - startColumn)).astype(np.float) # 此变量用于存储采集到的暗电流,一帧平均得到 + spectralNumber_wb = 1 # 每次采集的白板的光谱数 + spectral_wb = np.empty((endRow - startRow, endColumn - startColumn)).astype(np.float) # 此变量用于存储采集到的白板,一帧平均得到 + spectral_wb_tmp = np.empty((endRow - startRow, framenumber, endColumn - startColumn)) # 此变量用于存储采集到的白板原始一帧影像,后面白板影像去除了暗电流后值赋给spectral_wb + spectralNumber = 10 # 每次采集目标物的光谱数 + spectral = np.empty((endRow - startRow, spectralNumber)).astype(np.float) # 此ndarray用于存储采集到的目标物光谱,每一列为一个光谱 + + @classmethod + def start_AcquireData(cls, cam, qt_sender): + # 创建img = xiapi.Image()前需要设置一系列img参数,例如:格式、位深度、 + cam.set_imgdataformat('XI_RAW16') + # create instance of Image to store image data and metadata + img = xiapi.Image() + + print('Starting data acquisition...') + starttime = datetime.datetime.now() + + # 如果点击暗“align”按钮 + if qt_sender == 'spectral_mode_align_bt': + + if not cls.align: + cls.align = True + + cam.start_acquisition() + while cls.align: + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + enter_window_instance.spectral_window_instance.alignFigure.plot(image_raw_numpy) + enter_window_instance.spectral_window_instance.alignFigure.draw() + + # 如果点击“曝光/白板”按钮:(1)先自动曝光;(2)然后在采集白板 + if qt_sender == 'spectral_mode_wb_bt': + + # 自动曝光 + cam.set_framerate(15) + cam.set_aeag_roi_offset_x(cls.startColumn) + cam.set_aeag_roi_offset_y(cls.startRow) + cam.set_aeag_roi_height(cls.endRow - cls.startRow) + cam.set_aeag_roi_width(cls.endColumn - cls.startColumn) + # cam.set_exp_priority(1) # Exposure priority (0.8 - exposure 80%, gain 20%).XI_PRM_EXP_PRIORITY + # cam.set_ae_max_limit(24000) # Maximum time (us) used for exposure in AEAG procedureXI_PRM_AE_MAX_LIMIT + # cam.set_ag_max_limit(12) + # cam.set_aeag_level(50) # Average intensity of output signal AEAG should achieve(in %)XI_PRM_AEAG_LEVEL + # 还有两个不知怎么用的参数:XI_PRM_GAIN_SELECTOR or "gain_selector"和XI_PRM_SHUTTER_TYPE or "shutter_type" + cam.enable_aeag() + cam.start_acquisition() + for i in range(10): + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + cam.disable_aeag() + + # 将自动曝光获得的exposure和gain写入到相机 + cam.set_framerate(15) + cam.set_exposure(cam.get_exposure()) + cam.set_gain(cam.get_gain()) + enter_window_instance.spectral_window_instance.statu_tb.append('Exposure: ' + str(cam.get_exposure()) + ' us') + enter_window_instance.spectral_window_instance.statu_tb.append('Framerate: ' + str(cam.get_framerate()) + ' FPS') + + # 计算gain + cls.target_it = cam.get_exposure() + cls.gain_scale = cls.cal_it / cls.target_it + cls.gain = cls.gain * cls.gain_scale + + print('Framerate was set to %i FPS' % cam.get_framerate()) + print('Exposure was set to %i us' % cam.get_exposure()) + print('Gain was set to %i dB' % cam.get_gain()) + + # 开始采集白板数据,去除白板暗电流的操作放在采集暗电流时进行 + cam.start_acquisition() + for i in range(cls.framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + cls.spectral_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, + cls.startColumn:cls.endColumn] + + # 去除白板暗电流的操作放在采集暗电流时进行 + # cls.spectral_container没经过运算,传给cls.spectral_wb_tmp的是cls.spectral_container的内存地址 + cls.spectral_wb_tmp = cls.spectral_container + + # 存储原始白板影像 + filename = system_setting.spectral_dir + '\\' + 'baiban' + with open(filename, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_wb_tmp[:, i, :].flatten().tobytes()) + CameraOperation.write_hdr(filename, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + # 如果点击暗“暗电流”按钮 + if qt_sender == 'spectral_mode_dc_bt': + # 为cls.spectral_container新建立一个内存地址,以免改变cls.spectral_wb_tmp(传址)的值 + cls.spectral_container = np.empty((cls.endRow - cls.startRow, cls.framenumber, cls.endColumn - cls.startColumn)) + cam.start_acquisition() + for i in range(cls.framenumber): # 此循环为啥会改变649行的赋值的结果呢?怎么会执行那里的代码 + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + cls.spectral_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, cls.startColumn:cls.endColumn] + + # 存储暗电流影像 + filename1 = system_setting.spectral_dir + '\\' + 'dark' + with open(filename1, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_container[:, i, :].flatten().tobytes()) + CameraOperation.write_hdr(filename1, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + # cls.spectral_container经过运算,传给cls.image_dc的不是cls.spectral_container的内存地址,是新运算结果的内存地址;相当于传值 + cls.image_dc = cls.spectral_container.mean(axis=1) # 因为平均,cls.image_dc的数据类型为:dtype('float') + + # 去除白板暗电流 + for i in range(cls.framenumber): + cls.spectral_wb_tmp[:, i, :] = cls.spectral_wb_tmp[:, i, :] - cls.image_dc + + # 存储扣除暗电流的白板影像 + filename2 = system_setting.spectral_dir + '\\' + 'baiban_rmdark' + with open(filename2, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_wb_tmp[:, i, :].flatten().tobytes()) + CameraOperation.write_hdr(filename2, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + # 决定是否将白板转化成辐亮度 + if cls.rad_or_not: + cls.spectral_wb = cls.spectral_wb_tmp.mean(axis=1) * cls.gain[:, 0, :] + else: + cls.spectral_wb = cls.spectral_wb_tmp.mean(axis=1) # 因为平均,cls.spectral_wb的数据类型为:dtype('float') + + + # 如果点击“采集”按钮,去除暗电流,转化成反射率, + if qt_sender == 'spectral_mode_record_bt': + cam.start_acquisition() + for j in range(cls.spectralNumber): + for i in range(cls.framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + cls.spectral_container[:, i, :] = image_raw_numpy[cls.startRow:cls.endRow, + cls.startColumn:cls.endColumn] + + # 存储扣除暗电流前的目标物影像 + if j == 1: + filename1 = system_setting.spectral_dir + '\\' + cls.fn + with open(filename1, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_container[:, i, :].flatten().tobytes()) + CameraOperation.write_hdr(filename1, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + for i in range(cls.framenumber): # (1)去除暗电流;(2)转辐亮度;(3)转反射率 + if cls.rad_or_not: + cls.spectral_container[:, i, :] = (cls.spectral_container[:, i, + :] - cls.image_dc) * cls.gain[:, 0, :] / cls.spectral_wb + else: + cls.spectral_container[:, i, :] = (cls.spectral_container[:, i, + :] - cls.image_dc) / cls.spectral_wb + + # 存储目标物反射率影像 + if j == 1: + filename2 = system_setting.spectral_dir + '\\' + cls.fn + '_ref' + with open(filename2, 'wb') as f: + for i in range(cls.framenumber): + f.write(cls.spectral_container[:, i, :].flatten().tobytes()) + CameraOperation.write_hdr(filename2, cls.framenumber, cam.get_exposure(), cam.get_framerate()) + + # spectral_tmp = cls.spectral_container.sum(axis=1).sum(axis=1) + spectral_tmp = cls.spectral_container.mean(axis=1).mean(axis=1) + + cls.spectral[:, j] = spectral_tmp + + # 画出光谱 + def calculate_wavelength(x): + wavelength = x * 1.999564 - 279.893 + return wavelength + wavelength = np.empty(cls.endRow - cls.startRow) + for i in range(cls.startRow, cls.endRow): + wavelength[i - cls.startRow] = calculate_wavelength(i) + enter_window_instance.spectral_window_instance.spectralFigure.plot(wavelength, spectral_tmp) + enter_window_instance.spectral_window_instance.spectralFigure.draw() + + # 计算波长 + def calculate_wavelength(x): + wavelength = x * 1.999564 - 279.893 + return wavelength + wavelength = np.empty(cls.endRow - cls.startRow) + for i in range(cls.startRow, cls.endRow): + wavelength[i - cls.startRow] = calculate_wavelength(i) + + # 保存光谱为txt文件 + cls.spectral = np.insert(cls.spectral, 0, wavelength, axis=1) + for i in range(cls.spectralNumber): + np.savetxt(system_setting.spectral_dir + '\\' + cls.fn + str(i) + '.txt', cls.spectral[:, [0, i + 1]], fmt='%f') + + endtime = datetime.datetime.now() + print('光谱采集用时:%d' % (endtime - starttime).seconds) + + # stop data acquisition + print('Stopping acquisition...') + cam.stop_acquisition() + + @classmethod + def close_camera(cls, cam): + # stop communication + cam.close_device() + + +# 相机参数设置 +class SystemSetting(object): + def __init__(self): + self.file_dir = os.path.split(__file__)[0] + self.corning_config_file = self.file_dir + '//corning_config.ini' + + self.signals = WorkerSignals() + self.signals.image_signal.connect(self.image_record_param_changed) + self.signals.spectral_signal.connect(self.spectral_record_param_changed) + + self.read_config_file() + self.open_camera() + self.set_binning() + self.log() + + # 读取配置文件,如果没有就创建 + def read_config_file(self): + if os.path.exists(self.corning_config_file): + ''' + 如果存在配置文件,就从配置文件中读取软件配置信息 + ''' + print('配置文件存在!') + + config = configparser.ConfigParser() + config.read(self.corning_config_file) + + self.image_dir = config.get('image_record_param', 'image_dir') + self.create_directory(self.image_dir) + self.default_image_name = config.get('image_record_param', 'default_image_name') + self.framerate = int(config.get('image_record_param', 'framerate')) + self.exposure_time = int(config.get('image_record_param', 'exposure_time')) + self.gain = int(float(config.get('image_record_param', 'gain'))) + self.frame_number = int(config.get('image_record_param', 'frame_number')) + + self.spectral_dir = config.get('spectral_record_param', 'spectral_dir') + self.create_directory(self.spectral_dir) + self.default_spectral_name = config.get('spectral_record_param', 'default_spectral_name') + + self.binning = int(config.get('bin', 'binning')) + if self.binning == 1: + self.start_column = int(config.get('bin', 'start_column_binning_1')) + self.end_column = int(config.get('bin', 'end_column_binning_1')) + self.start_row = int(config.get('bin', 'start_row_binning_1')) + self.end_row = int(config.get('bin', 'end_row_binning_1')) + elif self.binning == 2: + self.start_column = int(config.get('bin', 'start_column_binning_2')) + self.end_column = int(config.get('bin', 'end_column_binning_2')) + self.start_row = int(config.get('bin', 'start_row_binning_2')) + self.end_row = int(config.get('bin', 'end_row_binning_2')) + + # print(self.default_dir, self.binning, self.start_column, self.end_column, self.start_row, self.end_row) + + else: + ''' + 1、如果不存在配置文件,就建立配置文件; + 2、并且手动创建配置变量 + ''' + config = configparser.ConfigParser() + + # config.add_section('effective_window') + # startRow = 339 + # endRow = 639 + # startColumn = 285 + # endColumn = 1649 + + + config.add_section('bin') + config.set('bin', 'binning', '1') + + config.set('bin', 'start_column_binning_1', '12') + config.set('bin', 'end_column_binning_1', '1376') + config.set('bin', 'start_row_binning_1', '1') + config.set('bin', 'end_row_binning_1', '300') + + config.set('bin', 'start_column_binning_2', '13') + config.set('bin', 'end_column_binning_2', '695') + config.set('bin', 'start_row_binning_2', '1') + config.set('bin', 'end_row_binning_2', '150') + + config.add_section('image_record_param') + config.set('image_record_param', 'image_dir', self.file_dir + '/image') + config.set('image_record_param', 'default_image_name', 'test_image') + config.set('image_record_param', 'framerate', '20') + config.set('image_record_param', 'exposure_time', '500') + config.set('image_record_param', 'gain', '0') + config.set('image_record_param', 'frame_number', '20') + + config.add_section('spectral_record_param') + config.set('spectral_record_param', 'spectral_dir', self.file_dir + '/spectral') + config.set('spectral_record_param', 'default_spectral_name', 'test_spectral') + # config.set('spectral_record_param', 'start_column_binning_1', '12') + + with open(self.corning_config_file, mode='w') as f: + config.write(f) + print('创建配置文件成功!') + + # 如果没有配置文件,就手动创建配置变量 + self.image_dir = self.file_dir + '/image' + self.create_directory(self.image_dir) + self.default_image_name = 'test_image' + self.framerate = 20 + self.exposure_time = 500 + self.gain = 0 + self.frame_number = 20 + + self.spectral_dir = self.file_dir + '/spectral' + self.create_directory(self.spectral_dir) + self.default_spectral_name = 'test_spectral' + + self.binning = 1 + self.start_column = int(config.get('bin', 'start_column_binning_1')) + self.end_column = int(config.get('bin', 'end_column_binning_1')) + self.start_row = int(config.get('bin', 'start_row_binning_1')) + self.end_row = int(config.get('bin', 'end_row_binning_1')) + + # self.start_column = 12 + # self.end_column = 1376 + # self.start_row = 1 + # self.end_row = 300 + + # 打开相机 + def open_camera(self): + # create instance for first connected camera + self.cam = xiapi.Camera() + + # start communication to open specific device, use: cam.open_device_by_SN('41305651') + print('Opening first camera...') + self.cam.open_device() + + # 打开相机后,显示相机信息 + print('SN: %s' % str(self.cam.get_device_sn(), encoding="utf-8")) + print('Device name: %s' % str(self.cam.get_device_name(), encoding="utf-8")) + print('Device name: %s' % str(self.cam.get_device_type(), encoding="utf-8")) + print('Instance path: %s' % str(self.cam.get_device_inst_path(), encoding="utf-8")) # Returns device instance path in operating system. + print('Location path: %s' % str(self.cam.get_device_loc_path(), encoding="utf-8")) + print('Debug level: %s' % self.cam.get_debug_level()) + + # The number of threads per image processor + print('Default number of threads per image processor: %d' % self.cam.get_proc_num_threads()) + self.cam.set_proc_num_threads(8) + print('Current number of threads per image processor: %d' % self.cam.get_proc_num_threads()) + + # 图像水平翻转 + print('Is horizontal flip enabled?, %s' % str(self.cam.is_horizontal_flip())) + print() + + # This mode is supported by selected camera families: CB, MC, MT, MX + self.cam.set_acq_timing_mode('XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + mode_used = self.cam.get_acq_timing_mode() + if mode_used == 'XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT': + print('Mode is XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + else: + print('Mode is not XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + sys.exit() + + # + def set_binning(self): + self.cam.set_binning_selector('XI_BIN_SELECT_HOST_CPU') # 默认为XI_BIN_SELECT_SENSOR(会报错),不可用:XI_BIN_SELECT_DEVICE_FPGA + self.cam.set_binning_horizontal_mode('XI_BIN_MODE_SUM') + self.cam.set_binning_horizontal(self.binning) + self.cam.set_binning_vertical_mode('XI_BIN_MODE_SUM') + self.cam.set_binning_vertical(self.binning) + + # 返回打开的相机对象 + def get_cam(self): + return self.cam + + # 查看是否存在保存光谱和影像文件的目录,如果没有就创建 + def create_directory(self, dir): + if not os.path.exists(dir): + print('创建文件夹:%s', dir) + os.makedirs(dir) + + def log(self): + # 判断是否存在log文件,如果不存在就创建 + if not os.path.exists(self.file_dir + '//all_operate.log'): + with open(self.file_dir + '//all_operate.log', 'w') as f: + pass + if not os.path.exists(self.file_dir + '//image_operate.log'): + with open(self.file_dir + '//image_operate.log', 'w') as f: + pass + if not os.path.exists(self.file_dir + '//spectral_operate.log'): + with open(self.file_dir + '//spectral_operate.log', 'w') as f: + pass + if not os.path.exists(self.file_dir + '//error.log'): + with open(self.file_dir + '//error.log', 'w') as f: + pass + if not os.path.exists(self.file_dir + '//temperature.log'): + with open(self.file_dir + '//temperature.log', 'w') as f: + pass + + # 初始化log + root_logger = logging.getLogger('root') + root_logger.setLevel(level=logging.DEBUG) # logger级别设置为低级别,代表这个logger可以处理很多级别的日志,更灵活的处理放在logger中的各种handler中 + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + + all_operate_file_handler = logging.FileHandler(self.file_dir + '//all_operate.log') # 输出到文件 + all_operate_file_handler.setLevel(logging.INFO) + all_operate_file_handler.setFormatter(formatter) + + error_file_handler = logging.FileHandler(self.file_dir + '//error.log') # 输出到文件 + error_file_handler.setLevel(logging.ERROR) + error_file_handler.setFormatter(formatter) + + stream_handler = logging.StreamHandler() # 输出到控制台 + stream_handler.setLevel(logging.INFO) + stream_handler.setFormatter(formatter) + + root_logger.addHandler(all_operate_file_handler) + root_logger.addHandler(error_file_handler) + root_logger.addHandler(stream_handler) + + def image_record_param_changed(self, dictionary): + ''' + :param dictionary: {'image_dir':值, 'image_record_param': 值} + :return: + ''' + try: + print(len(dictionary.keys())) + + config = configparser.ConfigParser() + config.read(self.corning_config_file) + + + for key in dictionary.keys(): + if key == 'image_dir': + self.image_dir = dictionary[key] + config.set('image_record_param', key, dictionary[key]) + if key == 'framerate': + self.framerate = dictionary[key] + config.set('image_record_param', key, str(dictionary[key])) + if key == 'exposure_time': + self.exposure_time = dictionary[key] + config.set('image_record_param', key, str(dictionary[key])) + if key == 'gain': + self.gain = dictionary[key] + config.set('image_record_param', key, str(dictionary[key])) + if key == 'frame_number': + self.frame_number = dictionary[key] + config.set('image_record_param', key, str(dictionary[key])) + except: + traceback.print_exc() + + with open(self.corning_config_file, 'w') as f: + config.write(f) + + def spectral_record_param_changed(self, dictionary): + ''' + :param dictionary: {'image_dir':值, 'image_record_param': 值} + :return: + ''' + print(len(dictionary.keys())) + + config = configparser.ConfigParser() + config.read(self.corning_config_file) + + try: + for key in dictionary.keys(): + if key == 'spectral_dir': + self.spectral_dir = dictionary[key] + config.set('spectral_record_param', key, dictionary[key]) + # if key == 'default_spectral_name': + # self.framerate = dictionary[key] + # config.set('spectral_record_param', key, dictionary[key]) + except: + traceback.print_exc() + + with open(self.corning_config_file, 'w') as f: + config.write(f) + + +if __name__ == '__main__': + app = QApplication(sys.argv) + + system_setting = SystemSetting() + camera = system_setting.get_cam() + + serial_port = SerialPort() + + # 实例化窗口 + enter_window_instance = EnterWindow() + enter_window_instance.c.openinfo.emit() + enter_window_instance.show() + + sys.exit(app.exec_()) diff --git a/record_system_v24/ArcusDevice.py b/record_system_v24/ArcusDevice.py new file mode 100644 index 0000000..70ba5a0 --- /dev/null +++ b/record_system_v24/ArcusDevice.py @@ -0,0 +1,75 @@ +""" +Arcus controller python interface. +Only works if one ARCUS device is connected. +Including Arcus Configuration cables. +Open ArcusDevice.py in Python IDE --> Run --> Enter Terminal Commands +""" +import threading +import Arcus +import copy +import sys + +class ArcusDevice(object): + """ + This is interface class to Arcus stepper controller + @author Lukas Zubal + @version 1.0 + """ + def __init__(self): + """ + @brief Constructor + @param self object instance + """ + self.device = Arcus.Arcus() + if self.device.Connect() == 1: + print ' ' + else: + print "Cannot open stepper device on port " + sys.exit() + self.outputBuffer = " " + self.lock = threading.Lock() # thread safety + self.verbose = 0 + + def close(self): + """ + @brief Closes Arcus device connection + @param self object instance + @return bool Returns a 1 if successful + """ + self.lock.acquire() + self.device.Close() + self.lock.release() + del self.device + return 1 + + def write(self, data): + """ + @brief Command-response call to Arcus device + @see Arcus controller manual for complete list of interactive commands + @param self object instance + @param data string containing interactive commands to arcus + @return str Returns string containing response of controller + """ + self.lock.acquire() + self.device.SendAndRecive(data, self.outputBuffer) + resp = copy.deepcopy(self.outputBuffer[:]) + self.lock.release() + resp = resp.split('\x00')[0] + if self.verbose == 1: + print resp + return resp + +arc = ArcusDevice() + +arc.write('DN') # Send Terminal Command to return device name. +# print "Connected to device: " + response # Notify user + +for i in range(len(sys.argv)-1): + response = arc.write(sys.argv[i+1]) # Process Command and save Controller Response + while response != 'OK': + response = arc.write(sys.argv[i+1]) + if sys.argv[i+1] == 'HSPD': + print response + +arc.close() # Close Device. +del arc diff --git a/record_system_v24/corning_config.ini b/record_system_v24/corning_config.ini new file mode 100644 index 0000000..23e9a90 --- /dev/null +++ b/record_system_v24/corning_config.ini @@ -0,0 +1,23 @@ +[bin] +binning = 1 +start_column_binning_1 = 12 +end_column_binning_1 = 1376 +start_row_binning_1 = 1 +end_row_binning_1 = 300 +start_column_binning_2 = 13 +end_column_binning_2 = 695 +start_row_binning_2 = 1 +end_row_binning_2 = 150 + +[image_record_param] +image_dir = D:/07 Itres +default_image_name = test_image +framerate = 60 +exposure_time = 16667 +gain = 0.0 +frame_number = 600 + +[spectral_record_param] +spectral_dir = D:/demo data +default_spectral_name = test_spectral + diff --git a/record_system_v24/delete.py b/record_system_v24/delete.py new file mode 100644 index 0000000..e08a96b --- /dev/null +++ b/record_system_v24/delete.py @@ -0,0 +1,42 @@ +import os, subprocess, time, traceback + +print('开始马达') +try: + # D:\software\Anaconda3\envs\py27_32\ + python2_command = r'python2.exe ' + os.path.dirname(__file__) + '/ArcusDevice.py' + ' CLR PX=0 EO=1 J+' + print(python2_command) + print(python2_command.split()) + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + print('有错1') + process.kill() + output, error = process.communicate() +except: + traceback.print_exc() + print('有错2') + pass + + +print('转动5秒') +time.sleep(5) + + +print('返回马达') +try: + # D:\software\Anaconda3\envs\py27_32\ + # 打包:https://stackoverflow.com/questions/58995937/using-pyinstaller-to-convert-python3-and-python2-to-exe + python2_command = r'python2.exe ' + os.path.dirname(__file__) + '/ArcusDevice.py' + ' CLR STOP X0' + print(python2_command) + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + print('有错3') + process.kill() + output, error = process.communicate() +except: + traceback.print_exc() + print('有错4') + pass diff --git a/record_system_v24/ui/__init__.py b/record_system_v24/ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/record_system_v24/ui/arcus_control_ui.py b/record_system_v24/ui/arcus_control_ui.py new file mode 100644 index 0000000..640777f --- /dev/null +++ b/record_system_v24/ui/arcus_control_ui.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'arcus_control_ui.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_arcus_ui(object): + def setupUi(self, arcus_ui): + arcus_ui.setObjectName("arcus_ui") + arcus_ui.resize(354, 171) + self.centralwidget = QtWidgets.QWidget(arcus_ui) + self.centralwidget.setObjectName("centralwidget") + self.left_btn = QtWidgets.QPushButton(self.centralwidget) + self.left_btn.setGeometry(QtCore.QRect(100, 90, 61, 21)) + self.left_btn.setObjectName("left_btn") + self.right_btn = QtWidgets.QPushButton(self.centralwidget) + self.right_btn.setGeometry(QtCore.QRect(170, 90, 61, 23)) + self.right_btn.setObjectName("right_btn") + self.speed_lineEdit = QtWidgets.QLineEdit(self.centralwidget) + self.speed_lineEdit.setGeometry(QtCore.QRect(101, 10, 131, 20)) + self.speed_lineEdit.setObjectName("speed_lineEdit") + self.speed_ScrollBar = QtWidgets.QScrollBar(self.centralwidget) + self.speed_ScrollBar.setGeometry(QtCore.QRect(100, 40, 131, 20)) + self.speed_ScrollBar.setOrientation(QtCore.Qt.Horizontal) + self.speed_ScrollBar.setObjectName("speed_ScrollBar") + arcus_ui.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(arcus_ui) + self.menubar.setGeometry(QtCore.QRect(0, 0, 354, 23)) + self.menubar.setObjectName("menubar") + arcus_ui.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(arcus_ui) + self.statusbar.setObjectName("statusbar") + arcus_ui.setStatusBar(self.statusbar) + + self.retranslateUi(arcus_ui) + QtCore.QMetaObject.connectSlotsByName(arcus_ui) + + def retranslateUi(self, arcus_ui): + _translate = QtCore.QCoreApplication.translate + arcus_ui.setWindowTitle(_translate("arcus_ui", "MainWindow")) + self.left_btn.setText(_translate("arcus_ui", "左")) + self.right_btn.setText(_translate("arcus_ui", "右")) diff --git a/record_system_v24/ui/arcus_control_ui.ui b/record_system_v24/ui/arcus_control_ui.ui new file mode 100644 index 0000000..b494281 --- /dev/null +++ b/record_system_v24/ui/arcus_control_ui.ui @@ -0,0 +1,81 @@ + + + arcus_ui + + + + 0 + 0 + 354 + 171 + + + + MainWindow + + + + + + 100 + 90 + 61 + 21 + + + + + + + + + + 170 + 90 + 61 + 23 + + + + + + + + + + 101 + 10 + 131 + 20 + + + + + + + 100 + 40 + 131 + 20 + + + + Qt::Horizontal + + + + + + + 0 + 0 + 354 + 23 + + + + + + + + diff --git a/record_system_v24/ui/enter_window.py b/record_system_v24/ui/enter_window.py new file mode 100644 index 0000000..9f5f1cd --- /dev/null +++ b/record_system_v24/ui/enter_window.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'enter_window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_enter_Window(object): + def setupUi(self, enter_Window): + enter_Window.setObjectName("enter_Window") + enter_Window.resize(651, 474) + self.centralwidget = QtWidgets.QWidget(enter_Window) + self.centralwidget.setObjectName("centralwidget") + self.image_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.image_mode_bt.setGeometry(QtCore.QRect(200, 180, 111, 51)) + self.image_mode_bt.setObjectName("image_mode_bt") + self.spectral_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.spectral_mode_bt.setGeometry(QtCore.QRect(360, 180, 111, 51)) + self.spectral_mode_bt.setObjectName("spectral_mode_bt") + self.camstatus_tb = QtWidgets.QTextBrowser(self.centralwidget) + self.camstatus_tb.setGeometry(QtCore.QRect(200, 240, 271, 81)) + self.camstatus_tb.setObjectName("camstatus_tb") + enter_Window.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(enter_Window) + self.menubar.setGeometry(QtCore.QRect(0, 0, 651, 26)) + self.menubar.setObjectName("menubar") + enter_Window.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(enter_Window) + self.statusbar.setObjectName("statusbar") + enter_Window.setStatusBar(self.statusbar) + self.actionwew_e = QtWidgets.QAction(enter_Window) + self.actionwew_e.setObjectName("actionwew_e") + + self.retranslateUi(enter_Window) + QtCore.QMetaObject.connectSlotsByName(enter_Window) + + def retranslateUi(self, enter_Window): + _translate = QtCore.QCoreApplication.translate + enter_Window.setWindowTitle(_translate("enter_Window", "主窗口")) + self.image_mode_bt.setText(_translate("enter_Window", "影像模式")) + self.spectral_mode_bt.setText(_translate("enter_Window", "光谱模式")) + self.actionwew_e.setText(_translate("enter_Window", "wew e")) diff --git a/record_system_v24/ui/enter_window.ui b/record_system_v24/ui/enter_window.ui new file mode 100644 index 0000000..4c39418 --- /dev/null +++ b/record_system_v24/ui/enter_window.ui @@ -0,0 +1,73 @@ + + + enter_Window + + + + 0 + 0 + 651 + 474 + + + + 主窗口 + + + + + + 200 + 180 + 111 + 51 + + + + 影像模式 + + + + + + 360 + 180 + 111 + 51 + + + + 光谱模式 + + + + + + 200 + 240 + 271 + 81 + + + + + + + + 0 + 0 + 651 + 26 + + + + + + + wew e + + + + + + diff --git a/record_system_v24/ui/image_Window.py b/record_system_v24/ui/image_Window.py new file mode 100644 index 0000000..2d176f5 --- /dev/null +++ b/record_system_v24/ui/image_Window.py @@ -0,0 +1,246 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'image_Window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_image_Window(object): + def setupUi(self, image_Window): + image_Window.setObjectName("image_Window") + image_Window.setEnabled(True) + image_Window.resize(1181, 683) + image_Window.setMouseTracking(False) + image_Window.setAutoFillBackground(False) + image_Window.setSizeGripEnabled(False) + image_Window.setModal(False) + self.gridLayout = QtWidgets.QGridLayout(image_Window) + self.gridLayout.setObjectName("gridLayout") + self.groupBox_5 = QtWidgets.QGroupBox(image_Window) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth()) + self.groupBox_5.setSizePolicy(sizePolicy) + self.groupBox_5.setObjectName("groupBox_5") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox_5) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + spacerItem = QtWidgets.QSpacerItem(374, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem) + self.splitter_2 = QtWidgets.QSplitter(self.groupBox_5) + self.splitter_2.setOrientation(QtCore.Qt.Horizontal) + self.splitter_2.setObjectName("splitter_2") + self.layoutWidget = QtWidgets.QWidget(self.splitter_2) + self.layoutWidget.setObjectName("layoutWidget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.label = QtWidgets.QLabel(self.layoutWidget) + self.label.setObjectName("label") + self.verticalLayout.addWidget(self.label) + self.label_4 = QtWidgets.QLabel(self.layoutWidget) + self.label_4.setObjectName("label_4") + self.verticalLayout.addWidget(self.label_4) + self.layoutWidget1 = QtWidgets.QWidget(self.splitter_2) + self.layoutWidget1.setObjectName("layoutWidget1") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.layoutWidget1) + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.filepath_le = QtWidgets.QLineEdit(self.layoutWidget1) + self.filepath_le.setObjectName("filepath_le") + self.verticalLayout_2.addWidget(self.filepath_le) + self.filename_le = QtWidgets.QLineEdit(self.layoutWidget1) + self.filename_le.setObjectName("filename_le") + self.verticalLayout_2.addWidget(self.filename_le) + self.layoutWidget2 = QtWidgets.QWidget(self.splitter_2) + self.layoutWidget2.setObjectName("layoutWidget2") + self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.layoutWidget2) + self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.filepath_bt = QtWidgets.QPushButton(self.layoutWidget2) + self.filepath_bt.setObjectName("filepath_bt") + self.verticalLayout_3.addWidget(self.filepath_bt) + self.save_bt = QtWidgets.QPushButton(self.layoutWidget2) + self.save_bt.setObjectName("save_bt") + self.verticalLayout_3.addWidget(self.save_bt) + self.layoutWidget3 = QtWidgets.QWidget(self.splitter_2) + self.layoutWidget3.setObjectName("layoutWidget3") + self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.layoutWidget3) + self.verticalLayout_7.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_7.setObjectName("verticalLayout_7") + self.t_label = QtWidgets.QLabel(self.layoutWidget3) + self.t_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.t_label.setObjectName("t_label") + self.verticalLayout_7.addWidget(self.t_label) + self.hum_label = QtWidgets.QLabel(self.layoutWidget3) + self.hum_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.hum_label.setObjectName("hum_label") + self.verticalLayout_7.addWidget(self.hum_label) + self.horizontalLayout_4.addWidget(self.splitter_2) + spacerItem1 = QtWidgets.QSpacerItem(374, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem1) + self.gridLayout.addWidget(self.groupBox_5, 0, 0, 1, 1) + self.splitter = QtWidgets.QSplitter(image_Window) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName("splitter") + self.groupBox_3 = QtWidgets.QGroupBox(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth()) + self.groupBox_3.setSizePolicy(sizePolicy) + self.groupBox_3.setMinimumSize(QtCore.QSize(0, 0)) + self.groupBox_3.setMaximumSize(QtCore.QSize(2000, 16777215)) + self.groupBox_3.setObjectName("groupBox_3") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_3) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.groupBox = QtWidgets.QGroupBox(self.groupBox_3) + self.groupBox.setObjectName("groupBox") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox) + self.horizontalLayout.setObjectName("horizontalLayout") + self.image_glo = QtWidgets.QGridLayout() + self.image_glo.setObjectName("image_glo") + self.horizontalLayout.addLayout(self.image_glo) + self.verticalLayout_4.addWidget(self.groupBox) + self.statu_tb = QtWidgets.QTextBrowser(self.groupBox_3) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.statu_tb.sizePolicy().hasHeightForWidth()) + self.statu_tb.setSizePolicy(sizePolicy) + self.statu_tb.setMaximumSize(QtCore.QSize(8777215, 100)) + self.statu_tb.setReadOnly(True) + self.statu_tb.setObjectName("statu_tb") + self.verticalLayout_4.addWidget(self.statu_tb) + self.groupBox_4 = QtWidgets.QGroupBox(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_4.sizePolicy().hasHeightForWidth()) + self.groupBox_4.setSizePolicy(sizePolicy) + self.groupBox_4.setObjectName("groupBox_4") + self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.groupBox_4) + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.groupBox_2 = QtWidgets.QGroupBox(self.groupBox_4) + self.groupBox_2.setObjectName("groupBox_2") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox_2) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.focus_glo = QtWidgets.QGridLayout() + self.focus_glo.setObjectName("focus_glo") + self.horizontalLayout_2.addLayout(self.focus_glo) + self.verticalLayout_5.addWidget(self.groupBox_2) + self.groupBox_6 = QtWidgets.QGroupBox(self.groupBox_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_6.sizePolicy().hasHeightForWidth()) + self.groupBox_6.setSizePolicy(sizePolicy) + self.groupBox_6.setObjectName("groupBox_6") + self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_6) + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.groupBox_7 = QtWidgets.QGroupBox(self.groupBox_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_7.sizePolicy().hasHeightForWidth()) + self.groupBox_7.setSizePolicy(sizePolicy) + self.groupBox_7.setMaximumSize(QtCore.QSize(500, 500)) + self.groupBox_7.setObjectName("groupBox_7") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_7) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.label_3 = QtWidgets.QLabel(self.groupBox_7) + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.verticalLayout_6.addWidget(self.label_3) + self.image_mode_focus_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_focus_bt.setObjectName("image_mode_focus_bt") + self.verticalLayout_6.addWidget(self.image_mode_focus_bt) + self.image_mode_exposureTime_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_exposureTime_bt.setObjectName("image_mode_exposureTime_bt") + self.verticalLayout_6.addWidget(self.image_mode_exposureTime_bt) + self.label_5 = QtWidgets.QLabel(self.groupBox_7) + self.label_5.setAlignment(QtCore.Qt.AlignCenter) + self.label_5.setObjectName("label_5") + self.verticalLayout_6.addWidget(self.label_5) + self.image_mode_wb_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_wb_bt.setObjectName("image_mode_wb_bt") + self.verticalLayout_6.addWidget(self.image_mode_wb_bt) + self.label_2 = QtWidgets.QLabel(self.groupBox_7) + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.verticalLayout_6.addWidget(self.label_2) + self.image_mode_record_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_record_bt.setObjectName("image_mode_record_bt") + self.verticalLayout_6.addWidget(self.image_mode_record_bt) + self.horizontalLayout_3.addLayout(self.verticalLayout_6) + self.verticalLayout_8 = QtWidgets.QVBoxLayout() + self.verticalLayout_8.setObjectName("verticalLayout_8") + self.framerate_le = QtWidgets.QLineEdit(self.groupBox_7) + self.framerate_le.setReadOnly(False) + self.framerate_le.setObjectName("framerate_le") + self.verticalLayout_8.addWidget(self.framerate_le) + self.image_mode_stop_focus_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_stop_focus_bt.setObjectName("image_mode_stop_focus_bt") + self.verticalLayout_8.addWidget(self.image_mode_stop_focus_bt) + self.exposureTime_le = QtWidgets.QLineEdit(self.groupBox_7) + self.exposureTime_le.setObjectName("exposureTime_le") + self.verticalLayout_8.addWidget(self.exposureTime_le) + self.gain_le = QtWidgets.QLineEdit(self.groupBox_7) + self.gain_le.setObjectName("gain_le") + self.verticalLayout_8.addWidget(self.gain_le) + self.image_mode_dc_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_dc_bt.setObjectName("image_mode_dc_bt") + self.verticalLayout_8.addWidget(self.image_mode_dc_bt) + self.framenumber_le = QtWidgets.QLineEdit(self.groupBox_7) + self.framenumber_le.setObjectName("framenumber_le") + self.verticalLayout_8.addWidget(self.framenumber_le) + self.image_mode_motor_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_motor_bt.setObjectName("image_mode_motor_bt") + self.verticalLayout_8.addWidget(self.image_mode_motor_bt) + self.image_mode_stop_record_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_stop_record_bt.setObjectName("image_mode_stop_record_bt") + self.verticalLayout_8.addWidget(self.image_mode_stop_record_bt) + self.horizontalLayout_3.addLayout(self.verticalLayout_8) + self.horizontalLayout_5.addWidget(self.groupBox_7) + spacerItem2 = QtWidgets.QSpacerItem(261, 17, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_5.addItem(spacerItem2) + self.verticalLayout_5.addWidget(self.groupBox_6) + self.gridLayout.addWidget(self.splitter, 1, 0, 1, 1) + + self.retranslateUi(image_Window) + QtCore.QMetaObject.connectSlotsByName(image_Window) + + def retranslateUi(self, image_Window): + _translate = QtCore.QCoreApplication.translate + image_Window.setWindowTitle(_translate("image_Window", "影像窗口")) + self.groupBox_5.setTitle(_translate("image_Window", "GroupBox")) + self.label.setText(_translate("image_Window", "保存路径")) + self.label_4.setText(_translate("image_Window", "文件名")) + self.filepath_bt.setText(_translate("image_Window", "浏览")) + self.save_bt.setText(_translate("image_Window", "保存")) + self.t_label.setText(_translate("image_Window", "温度:无数据")) + self.hum_label.setText(_translate("image_Window", "湿度:无数据")) + self.groupBox_3.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox.setTitle(_translate("image_Window", "图像")) + self.groupBox_4.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox_2.setTitle(_translate("image_Window", "光谱")) + self.groupBox_6.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox_7.setTitle(_translate("image_Window", "GroupBox")) + self.label_3.setText(_translate("image_Window", "帧率")) + self.image_mode_focus_bt.setText(_translate("image_Window", "调焦")) + self.image_mode_exposureTime_bt.setText(_translate("image_Window", "曝光")) + self.label_5.setText(_translate("image_Window", "gain")) + self.image_mode_wb_bt.setText(_translate("image_Window", "白板")) + self.label_2.setText(_translate("image_Window", "帧数")) + self.image_mode_record_bt.setText(_translate("image_Window", "采集")) + self.image_mode_stop_focus_bt.setText(_translate("image_Window", "停止调焦")) + self.image_mode_dc_bt.setText(_translate("image_Window", "暗电流")) + self.image_mode_motor_bt.setText(_translate("image_Window", "马达")) + self.image_mode_stop_record_bt.setText(_translate("image_Window", "停止采集")) diff --git a/record_system_v24/ui/image_Window.ui b/record_system_v24/ui/image_Window.ui new file mode 100644 index 0000000..588fe4c --- /dev/null +++ b/record_system_v24/ui/image_Window.ui @@ -0,0 +1,405 @@ + + + image_Window + + + true + + + + 0 + 0 + 1179 + 683 + + + + false + + + 影像窗口 + + + false + + + false + + + false + + + + + + + 0 + 0 + + + + GroupBox + + + + + + 湿度:无数据 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 374 + 20 + + + + + + + + Qt::Horizontal + + + + + + + 保存路径 + + + + + + + 文件名 + + + + + + + + + + + true + + + + + + + + + + + + + + 浏览 + + + + + + + 保存 + + + + + + + + + + + 温度:无数据 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + + + + Qt::Horizontal + + + + 374 + 20 + + + + + + + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 2000 + 16777215 + + + + GroupBox + + + + + + 图像 + + + + + + + + + + + + + 0 + 0 + + + + + 8777215 + 100 + + + + true + + + + + + + + + 0 + 0 + + + + GroupBox + + + + + + 光谱 + + + + + + + + + + + + + 0 + 0 + + + + GroupBox + + + + + + + 0 + 0 + + + + + 500 + 500 + + + + GroupBox + + + + + + + + 帧率 + + + Qt::AlignCenter + + + + + + + 调焦 + + + + + + + 曝光 + + + + + + + gain + + + Qt::AlignCenter + + + + + + + 白板 + + + + + + + 帧数 + + + Qt::AlignCenter + + + + + + + 采集 + + + + + + + + + + + false + + + + + + + 停止调焦 + + + + + + + + + + + + + 暗电流 + + + + + + + + + + 马达 + + + + + + + 停止采集 + + + + + + + + + + + + Qt::Horizontal + + + + 261 + 17 + + + + + + + + + + + + + + + + diff --git a/record_system_v24/ui/spectral_Window.py b/record_system_v24/ui/spectral_Window.py new file mode 100644 index 0000000..6e89899 --- /dev/null +++ b/record_system_v24/ui/spectral_Window.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'spectral_Window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_spectral_Window(object): + def setupUi(self, spectral_Window): + spectral_Window.setObjectName("spectral_Window") + spectral_Window.resize(820, 545) + self.label = QtWidgets.QLabel(spectral_Window) + self.label.setGeometry(QtCore.QRect(54, 10, 51, 20)) + self.label.setObjectName("label") + self.filepath_le = QtWidgets.QLineEdit(spectral_Window) + self.filepath_le.setGeometry(QtCore.QRect(131, 10, 261, 21)) + self.filepath_le.setObjectName("filepath_le") + self.label_2 = QtWidgets.QLabel(spectral_Window) + self.label_2.setGeometry(QtCore.QRect(54, 40, 41, 20)) + self.label_2.setObjectName("label_2") + self.filename_le = QtWidgets.QLineEdit(spectral_Window) + self.filename_le.setGeometry(QtCore.QRect(131, 40, 261, 21)) + self.filename_le.setObjectName("filename_le") + self.filepath_bt = QtWidgets.QPushButton(spectral_Window) + self.filepath_bt.setGeometry(QtCore.QRect(401, 10, 71, 21)) + self.filepath_bt.setObjectName("filepath_bt") + self.statu_tb = QtWidgets.QTextBrowser(spectral_Window) + self.statu_tb.setGeometry(QtCore.QRect(620, 240, 161, 301)) + self.statu_tb.setObjectName("statu_tb") + self.tabWidget = QtWidgets.QTabWidget(spectral_Window) + self.tabWidget.setGeometry(QtCore.QRect(10, 70, 591, 441)) + self.tabWidget.setObjectName("tabWidget") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.gridLayoutWidget = QtWidgets.QWidget(self.tab) + self.gridLayoutWidget.setGeometry(QtCore.QRect(0, 0, 581, 411)) + self.gridLayoutWidget.setObjectName("gridLayoutWidget") + self.spe_glo = QtWidgets.QGridLayout(self.gridLayoutWidget) + self.spe_glo.setContentsMargins(0, 0, 0, 0) + self.spe_glo.setObjectName("spe_glo") + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QtWidgets.QWidget() + self.tab_2.setObjectName("tab_2") + self.gridLayoutWidget_2 = QtWidgets.QWidget(self.tab_2) + self.gridLayoutWidget_2.setGeometry(QtCore.QRect(-1, -1, 581, 411)) + self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2") + self.align_glo = QtWidgets.QGridLayout(self.gridLayoutWidget_2) + self.align_glo.setContentsMargins(0, 0, 0, 0) + self.align_glo.setObjectName("align_glo") + self.tabWidget.addTab(self.tab_2, "") + self.layoutWidget = QtWidgets.QWidget(spectral_Window) + self.layoutWidget.setGeometry(QtCore.QRect(610, 90, 195, 135)) + self.layoutWidget.setObjectName("layoutWidget") + self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.spectral_mode_align_bt = QtWidgets.QPushButton(self.layoutWidget) + self.spectral_mode_align_bt.setObjectName("spectral_mode_align_bt") + self.gridLayout.addWidget(self.spectral_mode_align_bt, 0, 0, 1, 1) + self.spectral_mode_stop_align_bt = QtWidgets.QPushButton(self.layoutWidget) + self.spectral_mode_stop_align_bt.setObjectName("spectral_mode_stop_align_bt") + self.gridLayout.addWidget(self.spectral_mode_stop_align_bt, 0, 1, 1, 1) + self.spectral_mode_wb_bt = QtWidgets.QPushButton(self.layoutWidget) + self.spectral_mode_wb_bt.setObjectName("spectral_mode_wb_bt") + self.gridLayout.addWidget(self.spectral_mode_wb_bt, 1, 0, 1, 2) + self.spectral_mode_dc_bt = QtWidgets.QPushButton(self.layoutWidget) + self.spectral_mode_dc_bt.setObjectName("spectral_mode_dc_bt") + self.gridLayout.addWidget(self.spectral_mode_dc_bt, 2, 0, 1, 2) + self.spectral_mode_record_bt = QtWidgets.QPushButton(self.layoutWidget) + self.spectral_mode_record_bt.setObjectName("spectral_mode_record_bt") + self.gridLayout.addWidget(self.spectral_mode_record_bt, 3, 0, 1, 2) + self.t_label = QtWidgets.QLabel(spectral_Window) + self.t_label.setGeometry(QtCore.QRect(490, 11, 78, 23)) + self.t_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.t_label.setObjectName("t_label") + self.hum_label = QtWidgets.QLabel(spectral_Window) + self.hum_label.setGeometry(QtCore.QRect(490, 40, 78, 23)) + self.hum_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.hum_label.setObjectName("hum_label") + + self.retranslateUi(spectral_Window) + self.tabWidget.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(spectral_Window) + + def retranslateUi(self, spectral_Window): + _translate = QtCore.QCoreApplication.translate + spectral_Window.setWindowTitle(_translate("spectral_Window", "光谱窗口")) + self.label.setText(_translate("spectral_Window", "保存路径")) + self.label_2.setText(_translate("spectral_Window", "文件名")) + self.filepath_bt.setText(_translate("spectral_Window", "浏览")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("spectral_Window", "spe")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("spectral_Window", "align")) + self.spectral_mode_align_bt.setText(_translate("spectral_Window", "align")) + self.spectral_mode_stop_align_bt.setText(_translate("spectral_Window", "stop align")) + self.spectral_mode_wb_bt.setText(_translate("spectral_Window", "曝光/白板")) + self.spectral_mode_dc_bt.setText(_translate("spectral_Window", "暗电流")) + self.spectral_mode_record_bt.setText(_translate("spectral_Window", "采集")) + self.t_label.setText(_translate("spectral_Window", "温度:无数据")) + self.hum_label.setText(_translate("spectral_Window", "湿度:无数据")) diff --git a/record_system_v24/ui/spectral_Window.ui b/record_system_v24/ui/spectral_Window.ui new file mode 100644 index 0000000..4d1c99d --- /dev/null +++ b/record_system_v24/ui/spectral_Window.ui @@ -0,0 +1,212 @@ + + + spectral_Window + + + + 0 + 0 + 820 + 545 + + + + 光谱窗口 + + + + + 54 + 10 + 51 + 20 + + + + 保存路径 + + + + + + 131 + 10 + 261 + 21 + + + + + + + 54 + 40 + 41 + 20 + + + + 文件名 + + + + + + 131 + 40 + 261 + 21 + + + + + + + 401 + 10 + 71 + 21 + + + + 浏览 + + + + + + 620 + 240 + 161 + 301 + + + + + + + 10 + 70 + 591 + 441 + + + + 0 + + + + spe + + + + + 0 + 0 + 581 + 411 + + + + + + + + align + + + + + -1 + -1 + 581 + 411 + + + + + + + + + + 610 + 90 + 195 + 135 + + + + + + + align + + + + + + + stop align + + + + + + + 曝光/白板 + + + + + + + 暗电流 + + + + + + + 采集 + + + + + + + + + 490 + 11 + 78 + 23 + + + + 温度:无数据 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + 490 + 40 + 78 + 23 + + + + 湿度:无数据 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + diff --git a/record_system_v25/2record_system_v25.py b/record_system_v25/2record_system_v25.py new file mode 100644 index 0000000..1808790 --- /dev/null +++ b/record_system_v25/2record_system_v25.py @@ -0,0 +1,1801 @@ +# -*- coding:utf-8 -*- + +''' +在2record system_v2.2的基础上更新: +1、优化了图像显示和光谱显示:使用QGraphicsView显示图像 +2、通过包组织代码,降低主程序的复杂度 +3、 +4、 +5、 +6、 +7、 +''' + +# 内置包 +import os, sys, functools, re, shutil, traceback, time +import subprocess +import datetime # 几种Python执行时间的计算方法:https://blog.csdn.net/wangshuang1631/article/details/54286551 +import logging + +# 三方包 +import numpy as np +from osgeo import gdal +from ximea import xiapi +import configparser +import serial +import serial.tools.list_ports +from serial.serialutil import SerialBase, SerialException + +# 界面包 +import qimage2ndarray +from PyQt5.QtCore import Qt, QObject, QThreadPool, QTimer, QRegExp +# from PyQt5.QtCore import QRectF, pyqtSignal, QRunnable, pyqtSlot, QT_VERSION_STR +from PyQt5.QtGui import QIntValidator, QRegExpValidator, QPixmap, QImage, QPainterPath +from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, qApp, QDialog, QFileDialog, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem + +from QtImageViewer import QtImageViewer +from QtSpectralViewer import QtSpectralViewer +from library.multithread import Worker, WorkerSignals +from library.image_reader_writer import ImageReaderWriter +from library.functions import get_path, get_resource_path, return_file_path + +from record_system_v25.ui.enter_window import * +from record_system_v25.ui.image_Window import * +from record_system_v25.ui.spectral_Window import * +from record_system_v25.ui.arcus_control_ui import * + +import matplotlib +matplotlib.use("Qt5Agg") # 声明使用QT5 +from library.matplotlib_display_image_spectral import MatplotlibSpectralViewer, MatplotlibImageViewer + + +class ArcusWindow(QMainWindow, Ui_arcus_ui): + def __init__(self, parent=None): + super(ArcusWindow, self).__init__(parent) + self.setupUi(self) + + self.left_btn.pressed.connect(self.leftMove) + self.left_btn.released.connect(self.stop) + self.right_btn.pressed.connect(self.rightMove) + self.right_btn.released.connect(self.stop) + + # self.speed_lineEdit.setText(self.arc.write('HSPD')) + self.speed_lineEdit.textEdited.connect(self.change_speed) + + self.time = time.time() # 控制两次点击后,发送命令的间隔 + + def leftMove(self): + time_now = time.time() + if time_now - self.time > 0: + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J-' + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' CLR EO=1 J-' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('左移ok!') + + def rightMove(self): + time_now = time.time() + if time_now - self.time > 0.5: + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J+' + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' CLR EO=1 J+' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + print(output) + # print(error) + print('右移ok!') + + def change_speed(self): + time_now = time.time() + if time_now - self.time > 0.5: + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py HSPD=' + str(self.speed_lineEdit.text()) + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' HSPD=' + str(self.speed_lineEdit.text()) + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('改变速度ok!') + + def stop(self): + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py STOP' + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' STOP' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('停止ok!') + + +# 主窗口 +class EnterWindow(QMainWindow, Ui_enter_Window): + def __init__(self, parent=None): + super(EnterWindow, self).__init__(parent) + self.setupUi(self) + + # 在刚打开软件在本窗口显示相机状态(是否打开) + self.c = WorkerSignals() + self.c.openinfo.connect(self.printCamInfo) + self.c.openinfo.emit(2) + + # self.spectral_mode_bt.clicked.connect(self.spectral_window) + self.image_window_instance = ImageWindow() + self.image_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + self.image_mode_bt.clicked.connect(self.image_window_instance.show) + + self.spectral_window_instance = SpectralWindow() + self.spectral_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + self.spectral_mode_bt.clicked.connect(self.spectral_window_instance.show) + + def printCamInfo(self, cam_status): + ''' + :param cam_status: 0代表相机打开出错;1代表相机打开成功;2代表正在打开相机 + :return: + ''' + if cam_status == 1: + self.camstatus_tb.append('相机打开成功!') + + self.image_mode_bt.setDisabled(False) + self.spectral_mode_bt.setDisabled(False) + elif cam_status == 0: + self.camstatus_tb.append('相机打开失败!') + + self.image_mode_bt.setDisabled(True) + self.spectral_mode_bt.setDisabled(True) + elif cam_status == 2: + self.camstatus_tb.append('正在打开相机...') + + self.image_mode_bt.setDisabled(True) + self.spectral_mode_bt.setDisabled(True) + + +class SerialPort(QObject): + def __init__(self): + super(SerialPort, self).__init__() + + self.logger = logging.getLogger('root.serial') + + formatter1 = logging.Formatter('%(asctime)s %(message)s') + temperature_file_handler = logging.FileHandler(system_setting.log_dir + '//temperature.log') # 输出到文件 + temperature_file_handler.setLevel(logging.DEBUG) + temperature_file_handler.setFormatter(formatter1) + + self.logger.addHandler(temperature_file_handler) + + + + # self.signals = pyqtSignal(tuple) # 为啥这就不行呢? + self.signals = WorkerSignals() + + self.connect_number = 0 # 记录打开串口的次数 + self.serial_port = self.open_serial_port() + + self.timer = QTimer() + self.timer.timeout.connect(self.receiver_data_from_port) + self.timer.start(1000) + + def open_serial_port(self): + self.connect_number += 1 + port_list = list(serial.tools.list_ports.comports()) # 列出所有可用串口 + # print(port_list) + + if len(port_list) > 0: # 如果可用串口 >0 个 + # 打印出所有串口的信息 + for i in range(0, len(port_list)): + print(port_list[i]) + + # 打开第一个串口 + ser = serial.Serial(port_list[0].device) + # print('温湿度传感器打开成功!') + return ser + elif len(port_list) == 0: # 如果可用串口为0个 + if self.connect_number == 1: + self.logger.info('无可用串口,温湿度传感器不可用!') + else: + self.logger.error('串口连接上之后,断开连接!') + return 1 # 如果返回1,则代表没有可用串口;通过1来判断不执行定时器触发:self.timer.start(1000) + else: # 其他没有考虑到的情况 + return 1 + + def receiver_data_from_port(self): + ''' + 定时器QTimer没隔1s调用此函数一次 → 让串口buffer有足够的数据等待读取 + :return: 无返回值 + + 本函数功能:1、串口中接收字节数据,有两种帧 → 代表两种数据 + 2、判断帧头位置和本帧数据类型 + 3、判断帧尾 → 等效判断本帧数据是否完全 + 4、如果数据帧完整 → 解析数据,将温度湿度显示到界面上和写入到文件中 + ''' + try: + if self.serial_port.in_waiting: # 如果串口buffer有数据等待读取 + bytes_receive = self.serial_port.read(self.serial_port.inWaiting()) # 读取串口buffer的数据 + # print(len(bytes_receive)) + + # 判断帧头位置,通过正则表达式 + hex_receive = bytes_receive.hex() # 一个字节需要一个两位16进制数表示,所以:len(hex_receive) = len(bytes_receive) * 2 + p = re.compile('5a5a*') + index_head = [i.start() / 2 for i in re.finditer(p, hex_receive)] # re.finditer() + # print(hex_receive) + # print(index_head) + except SerialException: # 程序打开时,温湿度传感器的串口工作正常;如果程序运行中拔掉串口就会出现此异常 + self.logger.error('在程序运行中温湿度传感器的串口出现问题!') + + # 再次尝试打开串口 + self.serial_port = self.open_serial_port() + if not isinstance(self.serial_port, int): + self.logger.info('再次尝试连接温湿度传感器成功!') + else: + self.logger.info('再次尝试连接温湿度传感器失败!') + except AttributeError: # int object has no attribute: in_waiting + self.timer.stop() + self.logger.info('停止定时触发器!') + except Exception as e: # 未出现过的异常。当第一次出现时,需要编写代码处理,先写入日志文件(log) + self.logger.critical('未知错误!') + else: # 当没有捕获到异常时,代表串口数据获取成功 → 执行数据解析 + # 解析数据 + try: + if len(index_head) != 0: + Lux = 1.0 + T = 1.0 + P = 1.0 + Hum = 1.0 + H = 1.0 + Lux_full = 0 # 判断光照帧的数据是否完整。0:不完整;1:完整; + T_full = 0 # 判断温度帧的数据是否完整。0:不完整;1:完整; + try: + for i in index_head: # 循环遍历每个帧头 + if bytes_receive[int(i) + 2] == 21: # 0x15=21,判断帧头类型 + if sum(bytes_receive[int(i):int(i) + 8]) & 0xff == bytes_receive[int(i) + 8]: # 判断帧尾是否正确 + # print('光照帧的帧尾正确!') + + Lux_full = 1 # 如果帧尾,此帧数据数完整的 + Lux = ((bytes_receive[int(i) + 4] << 24) | (bytes_receive[int(i) + 5] << 16) | ( + bytes_receive[int(i) + 6] << 8) | bytes_receive[int(i) + 7]) / 100 + if bytes_receive[int(i) + 2] == 69: # 0x45=69,判断帧头类型 + if sum(bytes_receive[int(i):int(i) + 14]) & 0xff == bytes_receive[int(i) + 14]: # 判断帧尾是否正确 + # print('温度帧的帧尾正确!') + + T_full = 1 # 当执行这段代码时,代表帧头帧尾都正常,此帧数据数完整的 + T = ((bytes_receive[int(i) + 4] << 8) | bytes_receive[int(i) + 5]) / 100 + P = ((bytes_receive[int(i) + 6] << 24) | (bytes_receive[int(i) + 7] << 16) | ( + bytes_receive[int(i) + 8] << 8) | bytes_receive[ + int(i) + 9]) / 100 + Hum = ((bytes_receive[int(i) + 10] << 8) | bytes_receive[int(i) + 11]) / 100 + H = ((bytes_receive[int(i) + 12] << 8) | bytes_receive[int(i) + 13]) / 100 + except IndexError as e: # 当出现帧头,但是帧头到帧尾的数据不全 → 在判断帧尾是否正确时就会出现索引越界 + # print('----------------------索引越界!') + pass + except Exception: # 当出现前面没有解决的异常时,前面的异常捕捉就失效。最后通过异常基类来捕捉 → 代表需要修改代码进行处理的新异常 + # print('---------------------------------没遇见过的异常') + pass + + # 将数据显示和写入文件 + if Lux_full + T_full == 2: # x + y == 2代表温度帧和光照帧都完整 + # self.t_label.setVisible(True) + # self.hum_label.setVisible(True) + # self.t_label.setText('温度:' + str(T)) + # self.hum_label.setText('湿度:' + str(Hum)) + + # print('发送数据') + + self.signals.serial.emit((str(T), str(Hum))) + self.logger.debug('%s %s', str(T), str(Hum)) + + # print('光照强度:%f' % Lux) + # print('温度:%f' % T) + # print('气压:%f' % P) + # print('湿度:%f' % Hum) + # print('海拔:%f' % H) + # print() + elif Lux_full + T_full == 1: + # print('只有一个数据帧是完整的。(光照帧或者温度帧)') + # print() + pass + except UnboundLocalError: + # print(2222222222222222222222222222222) + # traceback.print_exc() + pass + except Exception: + self.logger.critical('未知错误!') + finally: # 不管有没有捕获到异常都会执行,一般用作资源回收 + pass + + +# 图像窗口 +class ImageWindow(QDialog, Ui_image_Window): + def __init__(self, parent=None): + ''' + The super().__init__() method invokes the base class constructor from the MyForm class, + that is, the constructor of the QDialog class is invoked from MyForm class to indicate that + QDialog is displayed through this class iss a top-level window. + ''' + super(ImageWindow, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + + self.arcus_window_instance = ArcusWindow() + self.image_mode_motor_bt.clicked.connect(self.arcus_window_instance.show) + + # log + self.logger = logging.getLogger('root.image') + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + image_operate_file_handler = logging.FileHandler(system_setting.log_dir + "//image_operate.log") # 输出到文件 + image_operate_file_handler.setLevel(logging.INFO) + image_operate_file_handler.setFormatter(formatter) + self.logger.addHandler(image_operate_file_handler) + + # 在窗口中显示串口接收的温度/湿度 + serial_port.signals.serial.connect(self.temperature) + + # 采集影像时,边采集边刷新显示 + # self.plotsignal = pyqtSignal() # 直接这样建立信号执行时会报错 + self.plotsignal = WorkerSignals() + self.plotsignal.plotsignal.connect(self.plotimg) + + #建立进程池 + # https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + #初始化窗口中的值 + self.framenumber_le.setText(str(system_setting.frame_number)) + CameraOperation.framenumber_input = system_setting.frame_number + CameraOperation.rgb = np.ones((3, int(system_setting.frame_number), int( + (CameraOperation.endColumn - CameraOperation.startColumn) / CameraOperation.bin_spatial))) + self.framerate_le.setText(str(system_setting.framerate)) + self.exposure_time_le.setText(str(system_setting.exposure_time)) + self.gain_le.setText(str(system_setting.gain)) + self.filename_le.setText(system_setting.default_image_name) + self.filepath_le.setText(system_setting.image_dir) + + # self.framenumber_le.setText(str(CameraOperation.framenumber_input)) + # self.framerate_le.setText(str(CameraOperation.framerate_input)) + # self.exposure_time_le.setText(str(CameraOperation.exposureTime_input)) + # self.gain_le.setText(str(CameraOperation.gain_input)) + # self.filename_le.setText(system_setting.default_image_name) + # self.filepath_le.setText(system_setting.image_dir) + + # #手动改变窗口中的值,然后将值写入camera_operation类对应的变量中 + # self.exposure_time_le.textEdited.connect(self.onchange2) + # self.exposure_time_le.textChanged.connect(self.onchange)# 将 自动曝光返回到QLineEdit中的值 写入到camera_operation.exposureTime_input + # self.gain_le.textEdited.connect(self.onchange2) + # self.gain_le.textChanged.connect(self.onchange)# 将 自动曝光返回到QLineEdit中的值 写入到camera_operation.gain_input + # self.framerate_le.textEdited.connect(self.onchange2) + # self.framenumber_le.textEdited.connect(self.onchange) + # self.filename_le.textEdited.connect(self.onchange) + # self.filepath_bt.clicked.connect(self.directory_select) + # self.filepath_le.textEdited.connect(self.onchange) + + # 显示影像和调焦 + # self.myImageFigure = MatplotlibImageViewer() + self.myImageFigure = QtImageViewer() + self.myImageFigure.leftMouseButtonPressed.connect(self.handleLeftClick) + self.image_glo.addWidget(self.myImageFigure) + + self.myFocusFigure = MatplotlibSpectralViewer(xlabel='Wavelength (nm)') + # self.myFocusFigure = QtSpectralViewer(xlabel='Wavelength (nm)') + self.focus_glo.addWidget(self.myFocusFigure) + + #操作光谱仪 + ## 注释的代码没有使用多线程,所以会造成一采集数据界面就卡死的情况 + # self.focus_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.dc_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.save_bt.clicked.connect(camera_operation.savedata) + self.image_mode_exposureTime_bt.clicked.connect(self.run) + self.image_mode_focus_bt.clicked.connect(self.run) + # 停止调焦和采集操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.image_mode_stop_focus_bt.clicked.connect(self.stop_focus) + self.image_mode_stop_record_bt.clicked.connect(self.stop_record) + self.image_mode_dc_bt.clicked.connect(self.run) + self.image_mode_wb_bt.clicked.connect(self.run) + self.image_mode_record_bt.clicked.connect(self.run) + self.save_bt.clicked.connect(self.save_image) + + # 手动改变窗口中的值,然后将值写入camera_operation类对应的变量中 + self.exposure_time_le.setValidator(QIntValidator()) # QIntValidator是一个类 + self.gain_le.setValidator(QIntValidator()) + self.framerate_le.setValidator(QIntValidator()) + self.framenumber_le.setValidator(QIntValidator()) + + my_regex = QRegExp("[a-zA-Z0-9]*") + my_validator = QRegExpValidator(my_regex, self.filename_le) + self.filename_le.setValidator(my_validator) + + self.exposure_time_le.editingFinished.connect(self.text_edited) + # self.exposure_time_le.setPlaceholderText('曝光时间') + self.gain_le.editingFinished.connect(self.text_edited) + self.framerate_le.editingFinished.connect(self.text_edited) + self.framenumber_le.editingFinished.connect(self.text_edited) + self.filename_le.editingFinished.connect(self.text_edited) + self.filepath_le.editingFinished.connect(self.text_edited) + + self.filepath_bt.clicked.connect(self.directory_select) + + self.cwd = system_setting.image_dir + + def handleLeftClick(self, x, y): + # 画出光谱 + try: + # 计算波长 + def calculate_wavelength(x): + wavelength = x * 1.999564 - 279.893 + return wavelength + + wavelength = np.empty(639 - 339) + for i in range(339, 639): + wavelength[i - 339] = calculate_wavelength(i) + + row = int(y) + column = int(x) + # print("Pixel (row=" + str(row) + ", column=" + str(column) + ")") + + _, _, img = ImageReaderWriter.read_img('corning410_test', column, row, 1, 1) + + if isinstance(img, np.ndarray): # 如果点击到图像之外,img就是NoneType,就不重画光谱 + # print('点击有效') + + self.myFocusFigure.plot_wrap(wavelength, img[:, 0, 0]) + except TypeError: + pass + # print('有错') + # self.logger.critical('TypeError:', exc_info=True) + except Exception: + self.logger.critical('点击显示光谱时出现未知错误:', exc_info=True) + traceback.print_exc() + + # 手动修改界面中的值后,为相机重新设置如下参数:exposure, gain, framerate + def text_edited(self): + try: + system_setting.exposure_time = int(self.exposure_time_le.text()) + system_setting.gain = int(float(self.gain_le.text())) + system_setting.framerate = int(self.framerate_le.text()) + system_setting.frame_number = int(self.framenumber_le.text()) + system_setting.default_image_name = self.filename_le.text() + + system_setting.signals.image_signal.emit( + {'exposure_time': int(self.exposure_time_le.text()), 'gain': int(float(self.gain_le.text())), + 'framerate': int(self.framerate_le.text()), 'frame_number': int(self.framenumber_le.text()), + 'default_image_name': self.filename_le.text()}) + except ValueError: + QMessageBox.information(self, '提示', '请输入正确的值!', QMessageBox.Yes) + except Exception: + self.logger.critical('设置曝光/gain/帧率/帧数时出现未知错误!', exe_info=True) + + CameraOperation.set_exposure_gain_framerate(camera) + + CameraOperation.fn = system_setting.default_image_name + + CameraOperation.framenumber_input = system_setting.frame_number + CameraOperation.rgb = np.ones((3, int(system_setting.frame_number), int( + (CameraOperation.endColumn - CameraOperation.startColumn) / CameraOperation.bin_spatial))) + + # 将自动曝光返回值写入到界面中的QLineEdit和system_setting对象中 + def post_auto_expose(self, result): + ''' + :param result: return cam.get_exposure(), cam.get_gain(), cls.autoexposure_feedback + :return: + ''' + + # 将自动曝光得到的结果显示到界面(QLineEdit) + print(result) + self.exposure_time_le.setText(str(result[0])) + self.gain_le.setText(str(result[1])) + + # 为了防止后面的信号执行延迟;如果延迟,设置曝光时间就会设置为system_setting.exposure_time的旧值 + system_setting.exposure_time = result[0] + system_setting.gain = result[1] + + try: + system_setting.signals.image_signal.emit({'exposure_time': result[0], 'gain': result[1]}) + except: + traceback.print_exc() + + CameraOperation.set_exposure_gain_framerate(camera) + + if result[2] == 1: + QMessageBox.information(self, '曝光提示', '光线不足,曝光时间已设置为最大!', QMessageBox.Yes) + CameraOperation.autoexposure_feedback = 0 + + def temperature(self, data): + try: + self.t_label.setText('温度:' + data[0]) + self.hum_label.setText('湿度:' + data[1]) + except: + print('有问题') + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + self.t_label.setText('温度:无数据') + self.hum_label.setText('湿度:无数据') + + def timer_start(self): + ''' + 本函数目的是在self.timer.start(1000)外包裹一层(有点装饰器的感觉),加入判断: + 1、如果self.serial_port为串口类型,就触发定时器self.timer.start(1000) + 2、如果self.serial_port == 1(为int类型),则代表硬件中没有温湿度传感器,就没必要触发定时器self.timer.start(1000) + :return: 无返回值 + ''' + + if isinstance(self.serial_port, serial.serialwin32.Serial): + self.timer.start(1000) + elif isinstance(self.serial_port, int): + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + else: + pass + + def plotimg(self): + worker = Worker(CameraOperation.plotimg) + self.threadpool.start(worker) + + def stop_focus(self): + CameraOperation.focus = False + + def stop_record(self): + CameraOperation.record = False + + # 调焦、采集暗电流、采集白板、采集影像 都通过此函数 + def run(self): + try: + self.qt_sender = self.sender().objectName() + + # 操作状态显示 + if self.qt_sender == 'image_mode_exposureTime_bt': + self.statu_tb.append('自动曝光...') + elif self.qt_sender == 'image_mode_focus_bt': + self.statu_tb.append('调焦...') + elif self.qt_sender == 'image_mode_dc_bt': + self.statu_tb.append('采集暗电流...') + elif self.qt_sender == 'image_mode_wb_bt': + self.statu_tb.append('采集白板...') + elif self.qt_sender == 'image_mode_record_bt': + self.statu_tb.append('采集影像...') + + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(CameraOperation.start_AcquireData, camera, self.qt_sender) + + worker.signals.error.connect(self.operate_failed) + worker.signals.finished.connect(self.operate_success) + if self.qt_sender == 'image_mode_exposureTime_bt': + ''' + 曝光参数的设置过程: + (1)曝光参数返回到界面中的QLineEdit; + (2)通过QLineEdit的textChanged事件将值写入到camera_operation对应的变量; + (3)为相机设置参数:1)通过worker的finished信号【本程序使用】2)也可以通过QLineEdit的textChanged事件调用self.set_exposure函数,为相机设置参数 + 这种过程的好处是界面显示的曝光参数和实际设置的是同步的 + ''' + worker.signals.result.connect(self.post_auto_expose) + + self.threadpool.start(worker) + + self.save_bt.setDisabled(True) + self.image_mode_exposureTime_bt.setDisabled(True) + self.image_mode_focus_bt.setDisabled(True) + self.image_mode_dc_bt.setDisabled(True) + self.image_mode_wb_bt.setDisabled(True) + self.image_mode_record_bt.setDisabled(True) + self.save_bt.setDisabled(True) + except Exception: + traceback.print_exc() + + def operate_failed(self, traceback_info): + if traceback_info[0] == xiapi.Xi_error: + if self.qt_sender == 'image_mode_exposureTime_bt': + self.statu_tb.append('自动曝光失败!') + self.logger.error('自动曝光失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_focus_bt': + self.statu_tb.append('调焦失败!') + self.logger.error('调焦失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_dc_bt': + self.statu_tb.append('采集暗电流失败!') + self.logger.error('采集暗电流失败:光谱仪正在工作中,请稍等\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_wb_bt': + self.statu_tb.append('采集白板失败!') + self.logger.error('采集白板失败:光谱仪正在工作中,请稍等\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_record_bt': + self.statu_tb.append('采集影像失败!') + self.logger.error('采集影像失败:光谱仪正在工作中,请稍等\n%s', traceback_info[2]) + elif traceback_info[0] == ValueError: + if self.qt_sender == 'save_bt': + self.statu_tb.append('保存影像失败!') + self.logger.error('保存影像失败!\n%s', traceback_info[2]) + QMessageBox.information(self, '提示', '请输入正确的影像名!', QMessageBox.Yes) + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + + def operate_success(self): + if self.qt_sender == 'image_mode_exposureTime_bt': + self.statu_tb.append('自动曝光成功!') + self.logger.info('自动曝光成功!') + elif self.qt_sender == 'image_mode_focus_bt': + self.statu_tb.append('调焦成功!') + self.logger.info('调焦成功!') + elif self.qt_sender == 'image_mode_dc_bt': + self.statu_tb.append('采集暗电流成功!') + self.logger.info('采集暗电流成功!') + elif self.qt_sender == 'image_mode_wb_bt': + self.statu_tb.append('采集白板成功!') + self.logger.info('采集白板成功!') + elif self.qt_sender == 'image_mode_record_bt': + self.statu_tb.append('采集影像成功!') + self.logger.info('采集影像成功!') + elif self.qt_sender == 'save_bt': + self.statu_tb.append('保存影像成功!') + self.logger.info('保存影像成功!') + + self.save_bt.setDisabled(False) + self.image_mode_exposureTime_bt.setDisabled(False) + self.image_mode_focus_bt.setDisabled(False) + self.image_mode_dc_bt.setDisabled(False) + self.image_mode_wb_bt.setDisabled(False) + self.image_mode_record_bt.setDisabled(False) + self.save_bt.setDisabled(False) + + def save_image(self): + # 操作状态显示 + self.qt_sender = self.sender().objectName() + self.statu_tb.append('保存影像...') + + worker = Worker(CameraOperation.savedata) + + worker.signals.error.connect(self.operate_failed) + worker.signals.finished.connect(self.operate_success) + + self.threadpool.start(worker) + + def directory_select(self): + dirpath = QFileDialog.getExistingDirectory(self, '选择存储路径文件夹', self.cwd) + + # 当在文件夹选择窗口中点击取消时,不重设路径 + if dirpath != '': + self.cwd = dirpath + + self.filepath_le.setText(dirpath) + system_setting.signals.image_signal.emit({'image_dir': dirpath}) + + self.logger.info('选择影像保存路径!') + + +# 光谱窗口 +class SpectralWindow(QDialog, Ui_spectral_Window): + def __init__(self, parent=None): + super(SpectralWindow, self).__init__(parent) + self.setupUi(self) + + # log + self.logger = logging.getLogger('root.spectral') + + # 在窗口中显示串口接收的温度/湿度 + serial_port.signals.serial.connect(self.temperature) + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + spectral_operate_file_handler = logging.FileHandler(system_setting.log_dir + "//spectral_operate.log") # 输出到文件 + spectral_operate_file_handler.setLevel(logging.INFO) + spectral_operate_file_handler.setFormatter(formatter) + self.logger.addHandler(spectral_operate_file_handler) + + # 建立进程池 + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 初始化值 + self.filename_le.setText(system_setting.default_spectral_name) + self.filepath_le.setText(system_setting.spectral_dir) + + # 显示光谱和align + self.spectralFigure = MatplotlibSpectralViewer(xlabel='Wavelength (nm)', ylabel='reflectance') + # self.spectralFigure = QtSpectralViewer(xlabel='Wavelength (nm)', ylabel='reflectance') + self.spe_glo.addWidget(self.spectralFigure) + + self.alignFigure = MatplotlibImageViewer() + # self.alignFigure = QtImageViewer() + self.align_glo.addWidget(self.alignFigure) + + #操作光谱仪 + # self.dc_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + self.spectral_mode_wb_bt.clicked.connect(self.run) # 曝光 + 采集白板 + self.spectral_mode_align_bt.clicked.connect(self.run) + self.spectral_mode_stop_align_bt.clicked.connect(self.stop_align) # 这个操作非常简单,耗时非常短,瞬间可回到event loop;所以不需要多线程 + self.spectral_mode_dc_bt.clicked.connect(self.run) + self.spectral_mode_record_bt.clicked.connect(self.run) + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + self.filepath_bt.clicked.connect(self.directory_select) + self.filename_le.editingFinished.connect(self.onchange) + # self.filepath_le.textEdited.connect(self.onchange) + + self.cwd = system_setting.spectral_dir + + def temperature(self, data): + try: + self.t_label.setText('温度:' + data[0]) + self.hum_label.setText('湿度:' + data[1]) + except: + traceback.print_exc() + print('有问题') + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + self.t_label.setText('温度:无数据') + self.hum_label.setText('湿度:无数据') + + def stop_align(self): + SpectralCameraOperation.align = False + + def run(self): + self.qt_sender = self.sender().objectName() + + # 操作状态显示 + if self.qt_sender == 'spectral_mode_wb_bt': + self.statu_tb.append('曝光/白板...') + self.logger.info('曝光/白板...') + elif self.qt_sender == 'spectral_mode_align_bt': + self.statu_tb.append('align...') + self.logger.info('align...') + elif self.qt_sender == 'spectral_mode_dc_bt': + self.statu_tb.append('采集暗电流...') + self.logger.info('采集暗电流...') + elif self.qt_sender == 'spectral_mode_record_bt': + self.statu_tb.append('采集光谱...') + self.logger.info('采集光谱...') + + worker = Worker(SpectralCameraOperation.start_AcquireData, camera, self.qt_sender) + worker.signals.finished.connect(self.operate_success) + worker.signals.error.connect(self.operate_failed) + # worker.signals.result.connect() + + self.threadpool.start(worker) + + def operate_failed(self, traceback_info): + if traceback_info[0] == xiapi.Xi_error: + if self.qt_sender == 'spectral_mode_wb_bt': + self.statu_tb.append('曝光/白板失败!') + self.logger.error('曝光/白板失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_align_bt': + self.statu_tb.append('align 失败!') + self.logger.error('align 失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_dc_bt': + self.statu_tb.append('采集暗电流失败!') + self.logger.error('采集暗电流失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_record_bt': + self.statu_tb.append('采集光谱失败!') + self.logger.error('采集光谱失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif traceback_info[0] == ValueError: + if self.qt_sender == 'spectral_mode_record_bt': + self.statu_tb.append('保存光谱失败!') + self.logger.error('保存光谱失败!\n%s', traceback_info[2]) + QMessageBox.information(self, '提示', '请输入正确的光谱名!', QMessageBox.Yes) + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + + def operate_success(self): + # 操作状态显示 + if self.qt_sender == 'spectral_mode_wb_bt': + self.statu_tb.append('曝光/白板成功!') + self.logger.info('曝光/白板成功!') + elif self.qt_sender == 'spectral_mode_align_bt': + self.statu_tb.append('align successfully!') + self.logger.info('align successfully!') + elif self.qt_sender == 'spectral_mode_dc_bt': + self.statu_tb.append('采集暗电流成功!') + self.logger.info('采集暗电流成功!') + elif self.qt_sender == 'spectral_mode_record_bt': + self.statu_tb.append('采集光谱成功!') + self.logger.info('采集光谱成功!') + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + def onchange(self): + filename = self.filename_le.text() + system_setting.default_spectral_name = filename + if filename != '': + system_setting.signals.spectral_signal.emit({'default_spectral_name': filename}) + self.logger.info('选择光谱保存路径!') + + def directory_select(self): + dirpath = QFileDialog.getExistingDirectory(self, '选择存储路径文件夹', self.cwd) + + # 当在文件夹选择窗口中点击取消时,不重设路径 + if dirpath != '': + self.cwd = dirpath + + self.filepath_le.setText(dirpath) + system_setting.signals.spectral_signal.emit({'spectral_dir': dirpath}) + self.logger.info('选择光谱保存路径!') + + +# 影像模式类:相关的函数和变量 +class CameraOperation(object): + + # 传感器有效范围 + # startRow = 339 + # endRow = 639 + # startColumn = 285 + # endColumn = 1650 + # 影像中400-560列:685-845 + startRow = 339 + endRow = 639 + startColumn = 285 + endColumn = 1649 + + # 转辐亮度 + rad_or_not = False + # img_gain = r'D:\py_program\corning410\corning410_radiance_calibration\jfq_dn_gain' + img_gain = get_resource_path('./data/jfq_dn_gain') + print(img_gain) + _, _, gain = ImageReaderWriter.read_img(img_gain) + gain = gain.astype(np.float) + cal_it = 6059 + target_it = None + gain_scale = None + + @classmethod + # 手动改变界面上的曝光值和gain值后,设置相机的曝光值和gain值所用 + def set_exposure_gain_framerate(cls, cam): + # settings,cam.set_param("exposure",10000) + cam.set_framerate(int(system_setting.framerate)) + cam.set_exposure(int(system_setting.exposure_time)) # 曝光时间单位为微秒,1s共有1000000微秒 + cam.set_gain(int(float(system_setting.gain))) #int('0.0')会报错,int(float('0.0'))不会报错 + + print('Exposure was set to %i us' % cam.get_exposure()) + print('Framerate was set to %i FPS' % cam.get_framerate()) + # ('Framerate: ' + str(cam.get_framerate()) + ' FPS')这样连接字符串会浪费内存 + enter_window_instance.image_window_instance.statu_tb.append("%s%s%s" % ('Framerate: ', str(cam.get_framerate()), ' FPS')) + enter_window_instance.image_window_instance.statu_tb.append("%s%s%s" % ('Exposure: ', str(cam.get_exposure()), ' us')) + enter_window_instance.image_window_instance.statu_tb.append("%s%s%s" % ('Gain: ', str(cam.get_gain()), ' dB')) + + # 开始采集数据 + framenumber_input = 100 # 随便给个初始值(初始值要和framenumber_le控件初始值一致),从image_window获取的手动输入的帧数 + image_dc = 1 # 随便给个初始值,此变量用于存储采集到的暗电流影像 + image_wb = 1 # 随便给个初始值,此变量用于存储采集到的白板影像 + focus = True # 用于停止调焦 + record = True # 用于停止采集 + img_datatype = 12 # 在头文件中确定影像数据类型 + # bin相关设置 + bin_spectral = 1 # 光谱bin + bin_spatial = 1 # 空间bin + k = np.arange(endRow - startRow)[0::bin_spectral] + l = np.arange(endColumn - startColumn)[0::bin_spatial] + + rgb = np.zeros((3, int(framenumber_input), int((endColumn - startColumn) / bin_spatial))) + + autoexposure_feedback = 0 # 指示:自动曝光所得到的shutter值是否为最大;如果为最大→值设置为1 + @classmethod + def start_AcquireData(cls, cam, qt_sender): # qt_sender是指qt窗口中事件的发生者 + # 创建img = xiapi.Image()前需要设置一系列img参数,例如:格式、位深度、 + # 如果格式设置为XI_RAW8,image_raw_numpy.dtype -> dtype('uint8'), uint8 + # 如果格式设置为XI_RAW16,image_raw_numpy.dtype -> dtype(' int(1 / int(system_setting.framerate) * 10**6): + cam.set_exposure(int(1 / int(system_setting.framerate) * 10**6)) + cls.autoexposure_feedback = 1 + + else: + cam.set_exposure(cam.get_exposure()) + + + print('Framerate was set to %i FPS' % cam.get_framerate()) + print('Exposure was set to %i us' % cam.get_exposure()) + print('Gain was set to %i dB' % cam.get_gain()) + + # 如果点击“调焦”按钮 + if qt_sender == 'image_mode_focus_bt': + # cls.set_exposureTime(cam) + + # 当关闭调焦后,再次打开调焦功能需要将cls.focus的值从False变为True + if not cls.focus: + cls.focus = True + + cam.start_acquisition() + + while cls.focus: + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container = image_raw_numpy[system_setting.start_row:system_setting.end_row, system_setting.start_column:system_setting.end_column] + + try: + # enter_window_instance.image_window_instance.myImageFigure.plot(image_container) + # enter_window_instance.image_window_instance.myImageFigure.draw() + + enter_window_instance.image_window_instance.myImageFigure.setImage(image_container) + + enter_window_instance.image_window_instance.myFocusFigure.plot_wrap(image_container[150, :]) + except Exception: + traceback.print_exc() + + # 如果点击“白板”按钮,采集并保存白板影像到image_wb + if qt_sender == 'image_mode_wb_bt': + framenumber = 10 + image_container = np.empty((cls.endRow - cls.startRow, framenumber, cls.endColumn - cls.startColumn)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[system_setting.start_row:system_setting.end_row, system_setting.start_column:system_setting.end_column] + + image_container = image_container.mean(axis=1) + + # 光谱bin和空间bin + if cls.bin_spectral != 1: + image_container_bin_spectral = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), cls.endColumn - cls.startColumn)) + image_container_bin = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), + int((cls.endColumn - cls.startColumn) / cls.bin_spatial))) + + for i in range(image_container_bin_spectral.shape[0]): + for j in range(cls.bin_spectral): + image_container_bin_spectral[i] += image_container[cls.k[i] + j] + # 光谱bin完成后,进行空间bin + for i in range(image_container_bin.shape[1]): + for j in range(cls.bin_spatial): + image_container_bin[:, i] += image_container_bin_spectral[:, cls.l[i] + j] + else: + image_container_bin = image_container + + # 白板扣除暗电流放在暗电流采集中 + cls.image_wb = image_container_bin + + # 如果点击“暗电流”按钮,采集并保存暗电流影像到image_dc + if qt_sender == 'image_mode_dc_bt': + framenumber = 10 + image_container = np.empty((cls.endRow - cls.startRow, framenumber, cls.endColumn - cls.startColumn)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[system_setting.start_row:system_setting.end_row, system_setting.start_column:system_setting.end_column] + + image_container = image_container.mean(axis=1) + + # 光谱bin和空间bin + if cls.bin_spectral != 1: + image_container_bin_spectral = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), cls.endColumn - cls.startColumn)) + image_container_bin = np.zeros( + (int((cls.endRow - cls.startRow) / cls.bin_spectral), + int((cls.endColumn - cls.startColumn) / cls.bin_spatial))) + + for i in range(image_container_bin_spectral.shape[0]): + for j in range(cls.bin_spectral): + image_container_bin_spectral[i] += image_container[cls.k[i] + j] + # 光谱bin完成后,进行空间bin + for i in range(image_container_bin.shape[1]): + for j in range(cls.bin_spatial): + image_container_bin[:, i] += image_container_bin_spectral[:, cls.l[i] + j] + else: + image_container_bin = image_container + + cls.image_dc = image_container_bin + cls.image_wb = cls.image_wb - cls.image_dc + + # 如果点击“采集”按钮,自动去除暗电流,并且转化成反射率 + if qt_sender == 'image_mode_record_bt': + frameCount = 1 # 统计采集的帧数,用于停止采集使用 + + # 当停止采集后,再次开始采集需要将cls.record的值从False变为True + if not cls.record: + cls.record = True + + # 开始马达 + try: + # D:\py27_program\arcus\ArcusDevice.py + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python2.exe ' + get_resource_path('./data/ArcusDevice.py') + ' CLR PX=0 EO=1 J+' + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' CLR PX=0 EO=1 J+' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + except: + pass + + # 开始采集数据 并且 将数据写入到硬盘中 + cam.start_acquisition() + with open('corning410_test', 'wb') as f: + + print('Starting data acquisition...') + startTime = datetime.datetime.now() + + while cls.record: + cam.get_image(img) # get data and pass them from camera to img + # image_raw_numpy.dtype -> dtype(' + + arcus_ui + + + + 0 + 0 + 354 + 171 + + + + MainWindow + + + + + + 100 + 90 + 61 + 21 + + + + + + + + + + 170 + 90 + 61 + 23 + + + + + + + + + + 101 + 10 + 131 + 20 + + + + + + + 100 + 40 + 131 + 20 + + + + Qt::Horizontal + + + + + + + 0 + 0 + 354 + 23 + + + + + + + + diff --git a/record_system_v25/ui/enter_window.py b/record_system_v25/ui/enter_window.py new file mode 100644 index 0000000..9f5f1cd --- /dev/null +++ b/record_system_v25/ui/enter_window.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'enter_window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_enter_Window(object): + def setupUi(self, enter_Window): + enter_Window.setObjectName("enter_Window") + enter_Window.resize(651, 474) + self.centralwidget = QtWidgets.QWidget(enter_Window) + self.centralwidget.setObjectName("centralwidget") + self.image_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.image_mode_bt.setGeometry(QtCore.QRect(200, 180, 111, 51)) + self.image_mode_bt.setObjectName("image_mode_bt") + self.spectral_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.spectral_mode_bt.setGeometry(QtCore.QRect(360, 180, 111, 51)) + self.spectral_mode_bt.setObjectName("spectral_mode_bt") + self.camstatus_tb = QtWidgets.QTextBrowser(self.centralwidget) + self.camstatus_tb.setGeometry(QtCore.QRect(200, 240, 271, 81)) + self.camstatus_tb.setObjectName("camstatus_tb") + enter_Window.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(enter_Window) + self.menubar.setGeometry(QtCore.QRect(0, 0, 651, 26)) + self.menubar.setObjectName("menubar") + enter_Window.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(enter_Window) + self.statusbar.setObjectName("statusbar") + enter_Window.setStatusBar(self.statusbar) + self.actionwew_e = QtWidgets.QAction(enter_Window) + self.actionwew_e.setObjectName("actionwew_e") + + self.retranslateUi(enter_Window) + QtCore.QMetaObject.connectSlotsByName(enter_Window) + + def retranslateUi(self, enter_Window): + _translate = QtCore.QCoreApplication.translate + enter_Window.setWindowTitle(_translate("enter_Window", "主窗口")) + self.image_mode_bt.setText(_translate("enter_Window", "影像模式")) + self.spectral_mode_bt.setText(_translate("enter_Window", "光谱模式")) + self.actionwew_e.setText(_translate("enter_Window", "wew e")) diff --git a/record_system_v25/ui/enter_window.ui b/record_system_v25/ui/enter_window.ui new file mode 100644 index 0000000..4c39418 --- /dev/null +++ b/record_system_v25/ui/enter_window.ui @@ -0,0 +1,73 @@ + + + enter_Window + + + + 0 + 0 + 651 + 474 + + + + 主窗口 + + + + + + 200 + 180 + 111 + 51 + + + + 影像模式 + + + + + + 360 + 180 + 111 + 51 + + + + 光谱模式 + + + + + + 200 + 240 + 271 + 81 + + + + + + + + 0 + 0 + 651 + 26 + + + + + + + wew e + + + + + + diff --git a/record_system_v25/ui/image_Window.py b/record_system_v25/ui/image_Window.py new file mode 100644 index 0000000..f877b4e --- /dev/null +++ b/record_system_v25/ui/image_Window.py @@ -0,0 +1,268 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'image_Window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_image_Window(object): + def setupUi(self, image_Window): + image_Window.setObjectName("image_Window") + image_Window.setEnabled(True) + image_Window.resize(1179, 683) + image_Window.setMouseTracking(False) + image_Window.setFocusPolicy(QtCore.Qt.NoFocus) + image_Window.setAutoFillBackground(False) + image_Window.setSizeGripEnabled(False) + image_Window.setModal(False) + self.gridLayout = QtWidgets.QGridLayout(image_Window) + self.gridLayout.setObjectName("gridLayout") + self.groupBox_5 = QtWidgets.QGroupBox(image_Window) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth()) + self.groupBox_5.setSizePolicy(sizePolicy) + self.groupBox_5.setObjectName("groupBox_5") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox_5) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.hum_label = QtWidgets.QLabel(self.groupBox_5) + self.hum_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.hum_label.setObjectName("hum_label") + self.horizontalLayout_4.addWidget(self.hum_label) + spacerItem = QtWidgets.QSpacerItem(374, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem) + self.splitter_2 = QtWidgets.QSplitter(self.groupBox_5) + self.splitter_2.setOrientation(QtCore.Qt.Horizontal) + self.splitter_2.setObjectName("splitter_2") + self.layoutWidget = QtWidgets.QWidget(self.splitter_2) + self.layoutWidget.setObjectName("layoutWidget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.label = QtWidgets.QLabel(self.layoutWidget) + self.label.setObjectName("label") + self.verticalLayout.addWidget(self.label) + self.label_4 = QtWidgets.QLabel(self.layoutWidget) + self.label_4.setObjectName("label_4") + self.verticalLayout.addWidget(self.label_4) + self.layoutWidget1 = QtWidgets.QWidget(self.splitter_2) + self.layoutWidget1.setObjectName("layoutWidget1") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.layoutWidget1) + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.filepath_le = QtWidgets.QLineEdit(self.layoutWidget1) + self.filepath_le.setReadOnly(True) + self.filepath_le.setObjectName("filepath_le") + self.verticalLayout_2.addWidget(self.filepath_le) + self.filename_le = QtWidgets.QLineEdit(self.layoutWidget1) + self.filename_le.setObjectName("filename_le") + self.verticalLayout_2.addWidget(self.filename_le) + self.layoutWidget2 = QtWidgets.QWidget(self.splitter_2) + self.layoutWidget2.setObjectName("layoutWidget2") + self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.layoutWidget2) + self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.filepath_bt = QtWidgets.QPushButton(self.layoutWidget2) + self.filepath_bt.setFocusPolicy(QtCore.Qt.ClickFocus) + self.filepath_bt.setAutoDefault(False) + self.filepath_bt.setObjectName("filepath_bt") + self.verticalLayout_3.addWidget(self.filepath_bt) + self.save_bt = QtWidgets.QPushButton(self.layoutWidget2) + self.save_bt.setFocusPolicy(QtCore.Qt.ClickFocus) + self.save_bt.setAutoDefault(False) + self.save_bt.setObjectName("save_bt") + self.verticalLayout_3.addWidget(self.save_bt) + self.layoutWidget3 = QtWidgets.QWidget(self.splitter_2) + self.layoutWidget3.setObjectName("layoutWidget3") + self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.layoutWidget3) + self.verticalLayout_7.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_7.setObjectName("verticalLayout_7") + self.t_label = QtWidgets.QLabel(self.layoutWidget3) + self.t_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.t_label.setObjectName("t_label") + self.verticalLayout_7.addWidget(self.t_label) + self.horizontalLayout_4.addWidget(self.splitter_2) + spacerItem1 = QtWidgets.QSpacerItem(374, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem1) + self.gridLayout.addWidget(self.groupBox_5, 0, 0, 1, 1) + self.splitter = QtWidgets.QSplitter(image_Window) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName("splitter") + self.groupBox_3 = QtWidgets.QGroupBox(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth()) + self.groupBox_3.setSizePolicy(sizePolicy) + self.groupBox_3.setMinimumSize(QtCore.QSize(0, 0)) + self.groupBox_3.setMaximumSize(QtCore.QSize(2000, 16777215)) + self.groupBox_3.setObjectName("groupBox_3") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_3) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.groupBox = QtWidgets.QGroupBox(self.groupBox_3) + self.groupBox.setObjectName("groupBox") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox) + self.horizontalLayout.setObjectName("horizontalLayout") + self.image_glo = QtWidgets.QGridLayout() + self.image_glo.setObjectName("image_glo") + self.horizontalLayout.addLayout(self.image_glo) + self.verticalLayout_4.addWidget(self.groupBox) + self.statu_tb = QtWidgets.QTextBrowser(self.groupBox_3) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.statu_tb.sizePolicy().hasHeightForWidth()) + self.statu_tb.setSizePolicy(sizePolicy) + self.statu_tb.setMaximumSize(QtCore.QSize(8777215, 100)) + self.statu_tb.setReadOnly(True) + self.statu_tb.setObjectName("statu_tb") + self.verticalLayout_4.addWidget(self.statu_tb) + self.groupBox_4 = QtWidgets.QGroupBox(self.splitter) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_4.sizePolicy().hasHeightForWidth()) + self.groupBox_4.setSizePolicy(sizePolicy) + self.groupBox_4.setObjectName("groupBox_4") + self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.groupBox_4) + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.groupBox_2 = QtWidgets.QGroupBox(self.groupBox_4) + self.groupBox_2.setObjectName("groupBox_2") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox_2) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.focus_glo = QtWidgets.QGridLayout() + self.focus_glo.setObjectName("focus_glo") + self.horizontalLayout_2.addLayout(self.focus_glo) + self.verticalLayout_5.addWidget(self.groupBox_2) + self.groupBox_6 = QtWidgets.QGroupBox(self.groupBox_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_6.sizePolicy().hasHeightForWidth()) + self.groupBox_6.setSizePolicy(sizePolicy) + self.groupBox_6.setObjectName("groupBox_6") + self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_6) + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.groupBox_7 = QtWidgets.QGroupBox(self.groupBox_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_7.sizePolicy().hasHeightForWidth()) + self.groupBox_7.setSizePolicy(sizePolicy) + self.groupBox_7.setMaximumSize(QtCore.QSize(500, 500)) + self.groupBox_7.setObjectName("groupBox_7") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_7) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.label_3 = QtWidgets.QLabel(self.groupBox_7) + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.verticalLayout_6.addWidget(self.label_3) + self.image_mode_focus_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_focus_bt.setFocusPolicy(QtCore.Qt.ClickFocus) + self.image_mode_focus_bt.setAutoDefault(False) + self.image_mode_focus_bt.setObjectName("image_mode_focus_bt") + self.verticalLayout_6.addWidget(self.image_mode_focus_bt) + self.image_mode_exposureTime_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_exposureTime_bt.setFocusPolicy(QtCore.Qt.ClickFocus) + self.image_mode_exposureTime_bt.setAutoDefault(False) + self.image_mode_exposureTime_bt.setObjectName("image_mode_exposureTime_bt") + self.verticalLayout_6.addWidget(self.image_mode_exposureTime_bt) + self.label_5 = QtWidgets.QLabel(self.groupBox_7) + self.label_5.setAlignment(QtCore.Qt.AlignCenter) + self.label_5.setObjectName("label_5") + self.verticalLayout_6.addWidget(self.label_5) + self.image_mode_wb_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_wb_bt.setFocusPolicy(QtCore.Qt.ClickFocus) + self.image_mode_wb_bt.setAutoDefault(False) + self.image_mode_wb_bt.setObjectName("image_mode_wb_bt") + self.verticalLayout_6.addWidget(self.image_mode_wb_bt) + self.label_2 = QtWidgets.QLabel(self.groupBox_7) + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.verticalLayout_6.addWidget(self.label_2) + self.image_mode_record_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_record_bt.setFocusPolicy(QtCore.Qt.ClickFocus) + self.image_mode_record_bt.setAutoDefault(False) + self.image_mode_record_bt.setObjectName("image_mode_record_bt") + self.verticalLayout_6.addWidget(self.image_mode_record_bt) + self.horizontalLayout_3.addLayout(self.verticalLayout_6) + self.verticalLayout_8 = QtWidgets.QVBoxLayout() + self.verticalLayout_8.setObjectName("verticalLayout_8") + self.framerate_le = QtWidgets.QLineEdit(self.groupBox_7) + self.framerate_le.setReadOnly(False) + self.framerate_le.setObjectName("framerate_le") + self.verticalLayout_8.addWidget(self.framerate_le) + self.image_mode_stop_focus_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_stop_focus_bt.setFocusPolicy(QtCore.Qt.ClickFocus) + self.image_mode_stop_focus_bt.setAutoDefault(False) + self.image_mode_stop_focus_bt.setObjectName("image_mode_stop_focus_bt") + self.verticalLayout_8.addWidget(self.image_mode_stop_focus_bt) + self.exposure_time_le = QtWidgets.QLineEdit(self.groupBox_7) + self.exposure_time_le.setObjectName("exposure_time_le") + self.verticalLayout_8.addWidget(self.exposure_time_le) + self.gain_le = QtWidgets.QLineEdit(self.groupBox_7) + self.gain_le.setObjectName("gain_le") + self.verticalLayout_8.addWidget(self.gain_le) + self.image_mode_dc_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_dc_bt.setFocusPolicy(QtCore.Qt.ClickFocus) + self.image_mode_dc_bt.setAutoDefault(False) + self.image_mode_dc_bt.setObjectName("image_mode_dc_bt") + self.verticalLayout_8.addWidget(self.image_mode_dc_bt) + self.framenumber_le = QtWidgets.QLineEdit(self.groupBox_7) + self.framenumber_le.setObjectName("framenumber_le") + self.verticalLayout_8.addWidget(self.framenumber_le) + self.image_mode_motor_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_motor_bt.setFocusPolicy(QtCore.Qt.ClickFocus) + self.image_mode_motor_bt.setAutoDefault(False) + self.image_mode_motor_bt.setObjectName("image_mode_motor_bt") + self.verticalLayout_8.addWidget(self.image_mode_motor_bt) + self.image_mode_stop_record_bt = QtWidgets.QPushButton(self.groupBox_7) + self.image_mode_stop_record_bt.setFocusPolicy(QtCore.Qt.ClickFocus) + self.image_mode_stop_record_bt.setAutoDefault(False) + self.image_mode_stop_record_bt.setObjectName("image_mode_stop_record_bt") + self.verticalLayout_8.addWidget(self.image_mode_stop_record_bt) + self.horizontalLayout_3.addLayout(self.verticalLayout_8) + self.horizontalLayout_5.addWidget(self.groupBox_7) + spacerItem2 = QtWidgets.QSpacerItem(261, 17, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_5.addItem(spacerItem2) + self.verticalLayout_5.addWidget(self.groupBox_6) + self.gridLayout.addWidget(self.splitter, 1, 0, 1, 1) + + self.retranslateUi(image_Window) + QtCore.QMetaObject.connectSlotsByName(image_Window) + + def retranslateUi(self, image_Window): + _translate = QtCore.QCoreApplication.translate + image_Window.setWindowTitle(_translate("image_Window", "影像窗口")) + self.groupBox_5.setTitle(_translate("image_Window", "GroupBox")) + self.hum_label.setText(_translate("image_Window", "湿度:无数据")) + self.label.setText(_translate("image_Window", "保存路径")) + self.label_4.setText(_translate("image_Window", "文件名")) + self.filepath_bt.setText(_translate("image_Window", "浏览")) + self.save_bt.setText(_translate("image_Window", "保存")) + self.t_label.setText(_translate("image_Window", "温度:无数据")) + self.groupBox_3.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox.setTitle(_translate("image_Window", "图像")) + self.groupBox_4.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox_2.setTitle(_translate("image_Window", "光谱")) + self.groupBox_6.setTitle(_translate("image_Window", "GroupBox")) + self.groupBox_7.setTitle(_translate("image_Window", "GroupBox")) + self.label_3.setText(_translate("image_Window", "帧率")) + self.image_mode_focus_bt.setText(_translate("image_Window", "调焦")) + self.image_mode_exposureTime_bt.setText(_translate("image_Window", "曝光")) + self.label_5.setText(_translate("image_Window", "gain")) + self.image_mode_wb_bt.setText(_translate("image_Window", "白板")) + self.label_2.setText(_translate("image_Window", "帧数")) + self.image_mode_record_bt.setText(_translate("image_Window", "采集")) + self.image_mode_stop_focus_bt.setText(_translate("image_Window", "停止调焦")) + self.image_mode_dc_bt.setText(_translate("image_Window", "暗电流")) + self.image_mode_motor_bt.setText(_translate("image_Window", "马达")) + self.image_mode_stop_record_bt.setText(_translate("image_Window", "停止采集")) diff --git a/record_system_v25/ui/image_Window.ui b/record_system_v25/ui/image_Window.ui new file mode 100644 index 0000000..0b93dd3 --- /dev/null +++ b/record_system_v25/ui/image_Window.ui @@ -0,0 +1,468 @@ + + + image_Window + + + true + + + + 0 + 0 + 1179 + 683 + + + + false + + + Qt::NoFocus + + + 影像窗口 + + + false + + + false + + + false + + + + + + + 0 + 0 + + + + GroupBox + + + + + + 湿度:无数据 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 374 + 20 + + + + + + + + Qt::Horizontal + + + + + + + 保存路径 + + + + + + + 文件名 + + + + + + + + + + + true + + + + + + + + + + + + + + Qt::ClickFocus + + + 浏览 + + + false + + + + + + + Qt::ClickFocus + + + 保存 + + + false + + + + + + + + + + + 温度:无数据 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + + + + Qt::Horizontal + + + + 374 + 20 + + + + + + + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 2000 + 16777215 + + + + GroupBox + + + + + + 图像 + + + + + + + + + + + + + 0 + 0 + + + + + 8777215 + 100 + + + + true + + + + + + + + + 0 + 0 + + + + GroupBox + + + + + + 光谱 + + + + + + + + + + + + + 0 + 0 + + + + GroupBox + + + + + + + 0 + 0 + + + + + 500 + 500 + + + + GroupBox + + + + + + + + 帧率 + + + Qt::AlignCenter + + + + + + + Qt::ClickFocus + + + 调焦 + + + false + + + + + + + Qt::ClickFocus + + + 曝光 + + + false + + + + + + + gain + + + Qt::AlignCenter + + + + + + + Qt::ClickFocus + + + 白板 + + + false + + + + + + + 帧数 + + + Qt::AlignCenter + + + + + + + Qt::ClickFocus + + + 采集 + + + false + + + + + + + + + + + false + + + + + + + Qt::ClickFocus + + + 停止调焦 + + + false + + + + + + + + + + + + + Qt::ClickFocus + + + 暗电流 + + + false + + + + + + + + + + Qt::ClickFocus + + + 马达 + + + false + + + + + + + Qt::ClickFocus + + + 停止采集 + + + false + + + + + + + + + + + + Qt::Horizontal + + + + 261 + 17 + + + + + + + + + + + + + + + + diff --git a/record_system_v25/ui/image_Window_phone.ui b/record_system_v25/ui/image_Window_phone.ui new file mode 100644 index 0000000..3b5ed09 --- /dev/null +++ b/record_system_v25/ui/image_Window_phone.ui @@ -0,0 +1,1083 @@ + + + image_Window_phone + + + true + + + + 0 + 0 + 525 + 1174 + + + + false + + + 影像窗口 + + + false + + + false + + + false + + + + + + Qt::Vertical + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 16777215 + 600 + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 600 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 曝 光 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 调 焦 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 暗 电 流 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 白 板 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 采 集 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 保 存 + + + false + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 积分时间 + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 率 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + false + + + + + + + + + + 0 + 0 + + + + + 160 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + < + + + false + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + > + + + false + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + 0 + + + + + + + + 0 + 0 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 233 + 12 + + + + + + + + + 0 + 0 + + + + 温度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + 湿度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + 光谱仪 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + 马达 + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/record_system_v25/ui/spectral_Window.py b/record_system_v25/ui/spectral_Window.py new file mode 100644 index 0000000..6e89899 --- /dev/null +++ b/record_system_v25/ui/spectral_Window.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'spectral_Window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_spectral_Window(object): + def setupUi(self, spectral_Window): + spectral_Window.setObjectName("spectral_Window") + spectral_Window.resize(820, 545) + self.label = QtWidgets.QLabel(spectral_Window) + self.label.setGeometry(QtCore.QRect(54, 10, 51, 20)) + self.label.setObjectName("label") + self.filepath_le = QtWidgets.QLineEdit(spectral_Window) + self.filepath_le.setGeometry(QtCore.QRect(131, 10, 261, 21)) + self.filepath_le.setObjectName("filepath_le") + self.label_2 = QtWidgets.QLabel(spectral_Window) + self.label_2.setGeometry(QtCore.QRect(54, 40, 41, 20)) + self.label_2.setObjectName("label_2") + self.filename_le = QtWidgets.QLineEdit(spectral_Window) + self.filename_le.setGeometry(QtCore.QRect(131, 40, 261, 21)) + self.filename_le.setObjectName("filename_le") + self.filepath_bt = QtWidgets.QPushButton(spectral_Window) + self.filepath_bt.setGeometry(QtCore.QRect(401, 10, 71, 21)) + self.filepath_bt.setObjectName("filepath_bt") + self.statu_tb = QtWidgets.QTextBrowser(spectral_Window) + self.statu_tb.setGeometry(QtCore.QRect(620, 240, 161, 301)) + self.statu_tb.setObjectName("statu_tb") + self.tabWidget = QtWidgets.QTabWidget(spectral_Window) + self.tabWidget.setGeometry(QtCore.QRect(10, 70, 591, 441)) + self.tabWidget.setObjectName("tabWidget") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.gridLayoutWidget = QtWidgets.QWidget(self.tab) + self.gridLayoutWidget.setGeometry(QtCore.QRect(0, 0, 581, 411)) + self.gridLayoutWidget.setObjectName("gridLayoutWidget") + self.spe_glo = QtWidgets.QGridLayout(self.gridLayoutWidget) + self.spe_glo.setContentsMargins(0, 0, 0, 0) + self.spe_glo.setObjectName("spe_glo") + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QtWidgets.QWidget() + self.tab_2.setObjectName("tab_2") + self.gridLayoutWidget_2 = QtWidgets.QWidget(self.tab_2) + self.gridLayoutWidget_2.setGeometry(QtCore.QRect(-1, -1, 581, 411)) + self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2") + self.align_glo = QtWidgets.QGridLayout(self.gridLayoutWidget_2) + self.align_glo.setContentsMargins(0, 0, 0, 0) + self.align_glo.setObjectName("align_glo") + self.tabWidget.addTab(self.tab_2, "") + self.layoutWidget = QtWidgets.QWidget(spectral_Window) + self.layoutWidget.setGeometry(QtCore.QRect(610, 90, 195, 135)) + self.layoutWidget.setObjectName("layoutWidget") + self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.spectral_mode_align_bt = QtWidgets.QPushButton(self.layoutWidget) + self.spectral_mode_align_bt.setObjectName("spectral_mode_align_bt") + self.gridLayout.addWidget(self.spectral_mode_align_bt, 0, 0, 1, 1) + self.spectral_mode_stop_align_bt = QtWidgets.QPushButton(self.layoutWidget) + self.spectral_mode_stop_align_bt.setObjectName("spectral_mode_stop_align_bt") + self.gridLayout.addWidget(self.spectral_mode_stop_align_bt, 0, 1, 1, 1) + self.spectral_mode_wb_bt = QtWidgets.QPushButton(self.layoutWidget) + self.spectral_mode_wb_bt.setObjectName("spectral_mode_wb_bt") + self.gridLayout.addWidget(self.spectral_mode_wb_bt, 1, 0, 1, 2) + self.spectral_mode_dc_bt = QtWidgets.QPushButton(self.layoutWidget) + self.spectral_mode_dc_bt.setObjectName("spectral_mode_dc_bt") + self.gridLayout.addWidget(self.spectral_mode_dc_bt, 2, 0, 1, 2) + self.spectral_mode_record_bt = QtWidgets.QPushButton(self.layoutWidget) + self.spectral_mode_record_bt.setObjectName("spectral_mode_record_bt") + self.gridLayout.addWidget(self.spectral_mode_record_bt, 3, 0, 1, 2) + self.t_label = QtWidgets.QLabel(spectral_Window) + self.t_label.setGeometry(QtCore.QRect(490, 11, 78, 23)) + self.t_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.t_label.setObjectName("t_label") + self.hum_label = QtWidgets.QLabel(spectral_Window) + self.hum_label.setGeometry(QtCore.QRect(490, 40, 78, 23)) + self.hum_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.hum_label.setObjectName("hum_label") + + self.retranslateUi(spectral_Window) + self.tabWidget.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(spectral_Window) + + def retranslateUi(self, spectral_Window): + _translate = QtCore.QCoreApplication.translate + spectral_Window.setWindowTitle(_translate("spectral_Window", "光谱窗口")) + self.label.setText(_translate("spectral_Window", "保存路径")) + self.label_2.setText(_translate("spectral_Window", "文件名")) + self.filepath_bt.setText(_translate("spectral_Window", "浏览")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("spectral_Window", "spe")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("spectral_Window", "align")) + self.spectral_mode_align_bt.setText(_translate("spectral_Window", "align")) + self.spectral_mode_stop_align_bt.setText(_translate("spectral_Window", "stop align")) + self.spectral_mode_wb_bt.setText(_translate("spectral_Window", "曝光/白板")) + self.spectral_mode_dc_bt.setText(_translate("spectral_Window", "暗电流")) + self.spectral_mode_record_bt.setText(_translate("spectral_Window", "采集")) + self.t_label.setText(_translate("spectral_Window", "温度:无数据")) + self.hum_label.setText(_translate("spectral_Window", "湿度:无数据")) diff --git a/record_system_v25/ui/spectral_Window.ui b/record_system_v25/ui/spectral_Window.ui new file mode 100644 index 0000000..378d713 --- /dev/null +++ b/record_system_v25/ui/spectral_Window.ui @@ -0,0 +1,215 @@ + + + spectral_Window + + + + 0 + 0 + 820 + 545 + + + + 光谱窗口 + + + + + 54 + 10 + 51 + 20 + + + + 保存路径 + + + + + + 131 + 10 + 261 + 21 + + + + true + + + + + + 54 + 40 + 41 + 20 + + + + 文件名 + + + + + + 131 + 40 + 261 + 21 + + + + + + + 401 + 10 + 71 + 21 + + + + 浏览 + + + + + + 620 + 240 + 161 + 301 + + + + + + + 10 + 70 + 591 + 441 + + + + 0 + + + + spe + + + + + 0 + 0 + 581 + 411 + + + + + + + + align + + + + + -1 + -1 + 581 + 411 + + + + + + + + + + 610 + 90 + 195 + 135 + + + + + + + align + + + + + + + stop align + + + + + + + 曝光/白板 + + + + + + + 暗电流 + + + + + + + 采集 + + + + + + + + + 490 + 11 + 78 + 23 + + + + 温度:无数据 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + 490 + 40 + 78 + 23 + + + + 湿度:无数据 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + diff --git a/record_system_v25/ui/spectral_Window_phone.ui b/record_system_v25/ui/spectral_Window_phone.ui new file mode 100644 index 0000000..402fd57 --- /dev/null +++ b/record_system_v25/ui/spectral_Window_phone.ui @@ -0,0 +1,377 @@ + + + spectral_Window_phone + + + + 0 + 0 + 568 + 1144 + + + + 光谱窗口 + + + + + + + 0 + 0 + + + + + 0 + 600 + + + + + 16777215 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 600 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 曝光/白板 + + + false + + + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 暗电流 + + + false + + + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + /*background-color:rgb(14 , 135 , 228);*/ + background-color:red; + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 采集 + + + false + + + + + + + + + + + 16777215 + 150 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + + 25 + + + + 文件名 + + + + + + + + 0 + 0 + + + + + 61 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 温度:无数据 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 湿度:无数据 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + + + + + + diff --git a/record_system_v26/2record_system_v26.py b/record_system_v26/2record_system_v26.py new file mode 100644 index 0000000..37f1246 --- /dev/null +++ b/record_system_v26/2record_system_v26.py @@ -0,0 +1,2215 @@ +# -*- coding:utf-8 -*- + +''' +在2record system_v2.2的基础上更新: +1、优化界面美观 +2、极大的优化了代码结构:充分利用了类的封装特性,降低了耦合性;解决了界面显示图像和光谱的问题; +3、设置ximea的有效输出窗口,以提高帧率 +4、设置芯片中bin,以减轻电脑的运算量 +5、 +6、 +7、 +''' + +# 内置包 +import os, sys, functools, re, shutil, traceback, time +import subprocess +import datetime # 几种Python执行时间的计算方法:https://blog.csdn.net/wangshuang1631/article/details/54286551 +import logging + +# 三方包 +import numpy as np +from osgeo import gdal +from ximea import xiapi +import configparser +import serial +import serial.tools.list_ports +from serial.serialutil import SerialBase, SerialException + +# 界面包 +import qimage2ndarray +from PyQt5.QtCore import Qt, QObject, QThreadPool, QTimer, QRegExp, pyqtSignal +# from PyQt5.QtCore import QRectF, pyqtSignal, QRunnable, pyqtSlot, QT_VERSION_STR +from PyQt5.QtGui import QIntValidator, QRegExpValidator, QPixmap, QImage, QPainterPath +from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, qApp, QDialog, QFileDialog, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem + +import matplotlib +matplotlib.use("Qt5Agg") # 声明使用QT5 +from library.matplotlib_display_image_spectral import MatplotlibSpectralViewer, MatplotlibImageViewer + + +# 自己写的包 +from QtImageViewer import QtImageViewer +from QtSpectralViewer import QtSpectralViewer +from library.multithread import Worker +from library.image_reader_writer import ImageReaderWriter +from library.functions import get_path, get_resource_path, return_file_path +from library.message_box import MessageBox +from library.config import ConfigFile +from library.log import Log + + +from record_system_v26.ui.enter_window import * + +# from record_system_v26.ui.image_Window import * +from record_system_v26.ui.image_Window_phone import * + +# from record_system_v26.ui.spectral_Window import * +from record_system_v26.ui.spectral_Window_phone import * + + +# 主窗口 +class EnterWindow(QMainWindow, Ui_enter_Window): + def __init__(self, parent=None): + super(EnterWindow, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + + self.image_mode_phone_bt.clicked.connect(self.image_window) + + self.spectral_mode_bt.clicked.connect(self.spectral_window) + + self.setEnabled(False) # 先设置本窗口不可用,当打开相机成功后,才设置为可用 + + system_setting.camera_status_signal.connect(self.test_imager_status) + + def image_window(self): + self.image_window_phone_instance = ImageWindowPhone() + self.image_window_phone_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + self.image_window_phone_instance.show() + + def spectral_window(self): + self.spectral_window_instance = SpectralWindow() + print(id(self.spectral_window_instance)) + self.spectral_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + self.spectral_window_instance.show() + + def test_imager_status(self, imager_status): + if imager_status == 1000: # 相机打开成功 + self.camstatus_label.setText('相机打开成功!') + + # 如果相机打开成功,界面中label颜色设置为绿色 + self.change_lable_background_color('green') + + self.setEnabled(True) # 如果相机打开成功,则窗口可用 + elif imager_status == 1001: + self.camstatus_label.setText('相机打开时出现不是ximea错误的未知错误!') + + # 如果相机打开成功,界面中label颜色设置为绿色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 1: + self.camstatus_label.setText('相机已经断开连接!请重新打开软件尝试连接相机!') + + # 如果相机打开失败,界面中label颜色设置为红色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 12: + pass + elif imager_status == 41: + pass + elif imager_status == 56: + self.camstatus_label.setText('没有检测到光谱仪!') + + # 如果相机打开失败,界面中label颜色设置为红色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 103: + pass + + def change_lable_background_color(self, color): + pattern = re.compile('background-color:rgb[(](.*)[)]') + old_style_sheet = self.camstatus_label.styleSheet() + + if color == 'red': # 如果相机打开失败,界面中label颜色设置为红色 + new_style_sheet = re.sub(pattern, r'background-color:rgb(255 , 0 , 0)', old_style_sheet) + self.camstatus_label.setStyleSheet(new_style_sheet) + elif color == 'green': # 如果相机打开成功,界面中label颜色设置为绿色 + new_style_sheet = re.sub(pattern, r'background-color:rgb(0 , 255 , 0)', old_style_sheet) + self.camstatus_label.setStyleSheet(new_style_sheet) + + +class SerialPort(QObject): + # 信号必须定义为类属性,不能放在__init__方法里 + serial_signal = pyqtSignal(object) # 建立信号,用于发射获取的温湿度 + + def __init__(self): + super(SerialPort, self).__init__() + + # 获取log温度日志的文件夹 + self.config_file_object = ConfigFile() + + # log + self.logger = logging.getLogger('root.serial') + + if not os.path.exists(self.config_file_object.log_dir + '//temperature.log'): + with open(self.config_file_object.log_dir + '//temperature.log', 'w') as f: + pass + + formatter1 = logging.Formatter('%(asctime)s %(message)s') + temperature_file_handler = logging.FileHandler(self.config_file_object.log_dir + '//temperature.log') # 输出到文件 + temperature_file_handler.setLevel(logging.DEBUG) + temperature_file_handler.setFormatter(formatter1) + + self.logger.addHandler(temperature_file_handler) + + self.connect_number = 0 # 记录打开串口的次数 + self.serial_port = self.open_serial_port() + + self.timer = QTimer() + self.timer.timeout.connect(self.receiver_data_from_port) + self.timer.start(1000) + + def open_serial_port(self): + self.connect_number += 1 + port_list = list(serial.tools.list_ports.comports()) # 列出所有可用串口 + # print(port_list) + + if len(port_list) > 0: # 如果可用串口 >0 个 + # 打印出所有串口的信息 + for i in range(0, len(port_list)): + print(port_list[i]) + + # 打开第一个串口 + ser = serial.Serial(port_list[0].device) + # print('温湿度传感器打开成功!') + return ser + elif len(port_list) == 0: # 如果可用串口为0个 + if self.connect_number == 1: + self.logger.info('无可用串口,温湿度传感器不可用!') + else: + self.logger.error('串口连接上之后,断开连接!') + return 1 # 如果返回1,则代表没有可用串口;通过1来判断不执行定时器触发:self.timer.start(1000) + else: # 其他没有考虑到的情况 + return 1 + + def receiver_data_from_port(self): + ''' + 定时器QTimer没隔1s调用此函数一次 → 让串口buffer有足够的数据等待读取 + :return: 无返回值 + + 本函数功能:1、串口中接收字节数据,有两种帧 → 代表两种数据 + 2、判断帧头位置和本帧数据类型 + 3、判断帧尾 → 等效判断本帧数据是否完全 + 4、如果数据帧完整 → 解析数据,将温度湿度显示到界面上和写入到文件中 + ''' + try: + if self.serial_port.in_waiting: # 如果串口buffer有数据等待读取 + bytes_receive = self.serial_port.read(self.serial_port.inWaiting()) # 读取串口buffer的数据 + # print(len(bytes_receive)) + + # 判断帧头位置,通过正则表达式 + hex_receive = bytes_receive.hex() # 一个字节需要一个两位16进制数表示,所以:len(hex_receive) = len(bytes_receive) * 2 + p = re.compile('5a5a*') + index_head = [i.start() / 2 for i in re.finditer(p, hex_receive)] # re.finditer() + # print(hex_receive) + # print(index_head) + except SerialException: # 程序打开时,温湿度传感器的串口工作正常;如果程序运行中拔掉串口就会出现此异常 + self.logger.error('在程序运行中温湿度传感器的串口出现问题!') + + # 再次尝试打开串口 + self.serial_port = self.open_serial_port() + if not isinstance(self.serial_port, int): + self.logger.info('再次尝试连接温湿度传感器成功!') + else: + self.logger.info('再次尝试连接温湿度传感器失败!') + except AttributeError: # int object has no attribute: in_waiting + self.timer.stop() + self.logger.info('停止定时触发器!') + except Exception as e: # 未出现过的异常。当第一次出现时,需要编写代码处理,先写入日志文件(log) + self.logger.critical('未知错误!') + else: # 当没有捕获到异常时,代表串口数据获取成功 → 执行数据解析 + # 解析数据 + try: + if len(index_head) != 0: + Lux = 1.0 + T = 1.0 + P = 1.0 + Hum = 1.0 + H = 1.0 + Lux_full = 0 # 判断光照帧的数据是否完整。0:不完整;1:完整; + T_full = 0 # 判断温度帧的数据是否完整。0:不完整;1:完整; + try: + for i in index_head: # 循环遍历每个帧头 + if bytes_receive[int(i) + 2] == 21: # 0x15=21,判断帧头类型 + if sum(bytes_receive[int(i):int(i) + 8]) & 0xff == bytes_receive[int(i) + 8]: # 判断帧尾是否正确 + # print('光照帧的帧尾正确!') + + Lux_full = 1 # 如果帧尾,此帧数据数完整的 + Lux = ((bytes_receive[int(i) + 4] << 24) | (bytes_receive[int(i) + 5] << 16) | ( + bytes_receive[int(i) + 6] << 8) | bytes_receive[int(i) + 7]) / 100 + if bytes_receive[int(i) + 2] == 69: # 0x45=69,判断帧头类型 + if sum(bytes_receive[int(i):int(i) + 14]) & 0xff == bytes_receive[int(i) + 14]: # 判断帧尾是否正确 + # print('温度帧的帧尾正确!') + + T_full = 1 # 当执行这段代码时,代表帧头帧尾都正常,此帧数据数完整的 + T = ((bytes_receive[int(i) + 4] << 8) | bytes_receive[int(i) + 5]) / 100 + P = ((bytes_receive[int(i) + 6] << 24) | (bytes_receive[int(i) + 7] << 16) | ( + bytes_receive[int(i) + 8] << 8) | bytes_receive[ + int(i) + 9]) / 100 + Hum = ((bytes_receive[int(i) + 10] << 8) | bytes_receive[int(i) + 11]) / 100 + H = ((bytes_receive[int(i) + 12] << 8) | bytes_receive[int(i) + 13]) / 100 + except IndexError as e: # 当出现帧头,但是帧头到帧尾的数据不全 → 在判断帧尾是否正确时就会出现索引越界 + # print('----------------------索引越界!') + pass + except Exception: # 当出现前面没有解决的异常时,前面的异常捕捉就失效。最后通过异常基类来捕捉 → 代表需要修改代码进行处理的新异常 + # print('---------------------------------没遇见过的异常') + pass + + # 将数据显示和写入文件 + if Lux_full + T_full == 2: # x + y == 2代表温度帧和光照帧都完整 + # self.t_label.setVisible(True) + # self.hum_label.setVisible(True) + # self.t_label.setText('温度:' + str(T)) + # self.hum_label.setText('湿度:' + str(Hum)) + + # print('发送数据') + + self.serial_signal.emit((str(T), str(Hum))) + self.logger.debug('%s %s', str(T), str(Hum)) # 将温湿度记录进log文件中 + + # print('光照强度:%f' % Lux) + # print('温度:%f' % T) + # print('气压:%f' % P) + # print('湿度:%f' % Hum) + # print('海拔:%f' % H) + # print() + elif Lux_full + T_full == 1: + # print('只有一个数据帧是完整的。(光照帧或者温度帧)') + # print() + pass + except UnboundLocalError: + # print(2222222222222222222222222222222) + # traceback.print_exc() + pass + except Exception: + self.logger.critical('未知错误!') + finally: # 不管有没有捕获到异常都会执行,一般用作资源回收 + pass + + +# 图像窗口 +class ImageWindowPhone(QDialog, Ui_image_Window_phone): + # 信号必须定义为类属性,不能放在__init__方法里 + arcus_status_signal = pyqtSignal(int) # arcus信号:0→马达未连接;1→马达连接成功; + plot_signal = pyqtSignal() # 采集影像时,边采集边刷新显示 + + def __init__(self, parent=None): + ''' + The super().__init__() method invokes the base class constructor from the MyForm class, + that is, the constructor of the QDialog class is invoked from MyForm class to indicate that + QDialog is displayed through this class iss a top-level window. + ''' + super(ImageWindowPhone, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + self.setWindowModality(Qt.ApplicationModal) # 阻塞此窗口:此行代码必须放在show()函数之前 + + # 配置文件读取和写入类,配置文件读写和界面分离 + # 1、采集数据需要的帧率、曝光、帧数、文件名等等都由此类从文件中读取 + # 2、并保存在此类中 + self.config_file_object = ConfigFile() + + # 数据采集保存类,采集数据并将数据保存在此类中,数据采集和界面分离 + self.image_camera_operation = CameraOperation(self.config_file_object) + + # 当配置文件读取完成后,就第一时间根据读取的配置文件设置相机曝光、帧率和gain + self.image_camera_operation.set_exposure_gain_framerate(camera) + self.initiate_arcus_speed() # 初始化arcus速度 + + # log + self.logger = logging.getLogger('root.image_phone') + + if not os.path.exists(self.config_file_object.log_dir + '//image_operate.log'): + with open(self.config_file_object.log_dir + '//image_operate.log', 'w') as f: + pass + + image_operate_file_handler = logging.FileHandler(self.config_file_object.log_dir + "//image_operate.log") # 输出到文件 + image_operate_file_handler.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + image_operate_file_handler.setFormatter(formatter) + + stream_handler = logging.StreamHandler() # 输出到控制台 + stream_handler.setLevel(logging.DEBUG) + stream_handler.setFormatter(formatter) + self.logger.addHandler(image_operate_file_handler) + self.logger.addHandler(stream_handler) + + # 在窗口中显示串口接收的温度/湿度 + serial_port.serial_signal.connect(self.temperature) + + # 采集影像时,边采集边刷新显示 + self.plot_signal.connect(self.plotimg) + + #建立进程池 + # https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 初始化窗口中的值 + self.framenumber_le.setText(str(self.config_file_object.frame_number)) + self.framerate_le.setText(str(self.config_file_object.framerate)) + self.exposure_time_le.setText(str(self.config_file_object.exposure_time)) + self.arcus_speed_le.setText(str(self.config_file_object.arcus_speed)) + self.filename_le.setText(self.config_file_object.default_image_name) + + # 显示影像和调焦 + # self.myImageFigure = MatplotlibImageViewer() + self.myImageFigure = QtImageViewer() + self.myImageFigure.leftMouseButtonPressed.connect(self.handle_left_click) + self.image_glo.addWidget(self.myImageFigure) + + # self.myFocusFigure = MatplotlibSpectralViewer(xlabel='Wavelength (nm)') + self.myFocusFigure = QtSpectralViewer() + self.focus_glo.addWidget(self.myFocusFigure) + + #操作光谱仪 + ## 注释的代码没有使用多线程,所以会造成一采集数据界面就卡死的情况 + # self.focus_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.dc_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(camera_operation.start_AcquireData, camera)) + # self.save_bt.clicked.connect(camera_operation.savedata) + self.image_mode_exposureTime_bt.clicked.connect(self.run) + self.image_mode_focus_bt.clicked.connect(self.run) + # 停止调焦和采集操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.image_mode_dc_bt.clicked.connect(self.run) + self.image_mode_wb_bt.clicked.connect(self.run) + self.image_mode_record_bt.clicked.connect(self.run) + self.save_bt.clicked.connect(self.run) + + # 手动改变窗口中的值,然后将值写入camera_operation类对应的变量中 + self.exposure_time_le.setValidator(QIntValidator()) # QIntValidator是一个类 + self.framerate_le.setValidator(QIntValidator()) + self.framenumber_le.setValidator(QIntValidator()) + + my_regex = QRegExp("[a-zA-Z0-9]*") + my_validator = QRegExpValidator(my_regex, self.filename_le) + self.filename_le.setValidator(my_validator) + + self.exposure_time_le.editingFinished.connect(self.text_edited) + # self.exposure_time_le.setPlaceholderText('曝光时间') + self.framerate_le.editingFinished.connect(self.text_edited) + self.framenumber_le.editingFinished.connect(self.text_edited) + self.filename_le.editingFinished.connect(self.text_edited) + + self.state = 0 # 光谱仪操作状态:曝光=1;暗电流=3;白板=5 → 所以只有state==9时才能开始采集影像 + self.focus_count = 1 # 用于调焦按钮点击计数,取2的余数;当余数为1是执行调焦,当余数为0时停止调焦 + self.record_count = 1 # 用于采集按钮点击计数,取2的余数;当余数为1是执行采集,当余数为0时停止采集;这是为了使用通过一个按钮控制开始采集和停止采集 + + # 马达相关操作 + self.arcus_left_bt.pressed.connect(self.leftMove) + self.arcus_left_bt.released.connect(self.stop) + self.arcus_right_bt.pressed.connect(self.rightMove) + self.arcus_right_bt.released.connect(self.stop) + + # self.arcus_speed_le.setText(self.arc.write('HSPD')) + self.arcus_speed_le.editingFinished.connect(self.text_edited) + self.arcus_speed_le.setValidator(QIntValidator()) + + # 控制两次点击后,发送命令的间隔 + self.time = time.time() + self.time_interval = 1 + + self.plot_frame_count_multiple = 1 # 用于边采集边在页面中刷新,用于确定该显示多少帧了;如何确定该显示多少帧:self.plot_frame_count_multiple * 帧率 + + system_setting.camera_status_signal.connect(self.test_imager_status) + + # 检测arcus马达的连接情况 + self.timer = QTimer() + self.timer.timeout.connect(self.test_arcus_status) + self.timer.start(3000) + self.arcus_status_signal.connect(self.response_to_arcus_status) + + def test_arcus_status(self): + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' DN' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=2) + if 'Arcus device connected' in output.decode('utf-8'): + self.arcus_status_signal.emit(1) + elif 'No arcus devices' in output.decode('utf-8'): + self.arcus_status_signal.emit(0) + except subprocess.TimeoutExpired: + process.kill() + output2, error2 = process.communicate() + if 'Arcus device connected' in output2.decode('utf-8'): + self.arcus_status_signal.emit(1) + elif 'No arcus devices' in output2.decode('utf-8'): + self.arcus_status_signal.emit(0) + + def response_to_arcus_status(self, arcus_status): + if arcus_status == 0: + self.arcus_status_label.setText('马达:连接失败!') + self.change_widget_background_color(self.arcus_status_label, 'red') + elif arcus_status == 1: + self.arcus_status_label.setText('马达:连接正常!') + self.change_widget_background_color(self.arcus_status_label, 'green') + + def test_imager_status(self, imager_status): + if imager_status == 1000: # 相机打开成功 + # print('相机打开成功!') + + self.camera_status_label.setText('光谱仪:正常') + self.change_widget_background_color(self.camera_status_label, 'green') + elif imager_status == 1001: + print('相机打开时出现不是ximea错误的未知错误!') + elif imager_status == 1: + # print('相机已经断开连接!请重新打开软件尝试连接相机!') + + self.camera_status_label.setText('光谱仪:断开连接') + self.change_widget_background_color(self.camera_status_label, 'red') + + self.setEnabled(False) + self.close() + elif imager_status == 12: + pass + elif imager_status == 41: + pass + elif imager_status == 56: + print('没有检测到光谱仪!') + elif imager_status == 103: + pass + + def leftMove(self): + time_now = time.time() + if time_now - self.time > self.time_interval: + print(time_now - self.time) + + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J-' + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' CLR EO=1 J-' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=2) + + print('左移output', output) + print('左移error', error) # 如果没有输出内容就输出None + except subprocess.TimeoutExpired: + process.kill() + output2, error2 = process.communicate() + + print('---------------------------------------------------------') + print('左移出错output', output2) + print('左移出错error', error2) + + def rightMove(self): + time_now = time.time() + if time_now - self.time > self.time_interval: + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J+' + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' CLR EO=1 J+' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=2) + + print('右移output;', type(output), output) + print('右移error', error) + except subprocess.TimeoutExpired: + process.kill() + output2, error2 = process.communicate() + + print('---------------------------------------------------------') + print('右移出错output', output2) + print('右移出错error', error2) + + def stop(self): + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py STOP' + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' STOP' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=2) + + print('停止output', output) + print('停止error', error) + except subprocess.TimeoutExpired: + process.kill() + output2, error2 = process.communicate() + + print('---------------------------------------------------------') + print('停止出错output', output2) + print('停止出错error', error2) + + def handle_left_click(self, x, y): + # 画出光谱 + try: + row = int(y) + column = int(x) + # print("Pixel (row=" + str(row) + ", column=" + str(column) + ")") + + _, _, img = ImageReaderWriter.read_img('corning410_test', column, row, 1, 1) + + if isinstance(img, np.ndarray): # 如果点击到图像之外,img就是NoneType,就不重画光谱 + # print('点击有效') + + self.myFocusFigure.plot_wrap(self.image_camera_operation.wave(model='array'), img[:, 0, 0]) + except TypeError: + pass + # print('有错') + # self.logger.critical('TypeError:', exc_info=True) + except Exception: + self.logger.critical('点击显示光谱时出现未知错误:', exc_info=True) + traceback.print_exc() + + # 手动修改界面中的值后,为相机重新设置如下参数:exposure, gain, framerate + def text_edited(self): + try: + # 将改变值1)保存到配置文件对象,供程序运行使用2)写入到配置文件,供程序下次打开读取 + self.config_file_object.image_signal.emit( + {'exposure_time': int(self.exposure_time_le.text()), + 'framerate': int(self.framerate_le.text()), 'frame_number': int(self.framenumber_le.text()), + 'default_image_name': self.filename_le.text(), 'arcus_speed': self.arcus_speed_le.text()}) + except ValueError: + # QMessageBox.information(self, '提示', '请输入正确的值!', QMessageBox.Yes) + self.x = MessageBox('请输入正确的值!') + except Exception: + self.logger.critical('设置曝光/gain/帧率/帧数时出现未知错误!', exe_info=True) + + if self.sender().objectName() == 'exposure_time_le': + self.state = 1 # 手动改变曝光时间后,强制让用户重新采集暗电流+白板 + + print('exposure_time_le改变') + self.image_camera_operation.set_exposure_gain_framerate(camera) + + if self.sender().objectName() == 'framerate_le': + self.state = 0 # 改变帧率后,需要重新曝光 + + print('framerate_le改变') + self.image_camera_operation.set_exposure_gain_framerate(camera) + + if self.sender().objectName() == 'framenumber_le': + self.image_camera_operation.create_rgb() + + if self.sender().objectName() == 'arcus_speed_le': + time_now = time.time() + if time_now - self.time > self.time_interval: + self.time = time.time() + + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' HSPD=' + str(self.arcus_speed_le.text()) + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('改变速度ok!') + + def initiate_arcus_speed(self): + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' HSPD=' + str(self.config_file_object.arcus_speed) + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('初始化速度ok!') + + def temperature(self, data): + try: + self.t_label.setText('温度:' + data[0]) + self.hum_label.setText('湿度:' + data[1]) + + self.change_widget_background_color(self.t_label, 'green') + self.change_widget_background_color(self.hum_label, 'green') + except: + print('有问题') + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + self.t_label.setText('温度:无数据') + self.hum_label.setText('湿度:无数据') + + def timer_start(self): + ''' + 本函数目的是在self.timer.start(1000)外包裹一层(有点装饰器的感觉),加入判断: + 1、如果self.serial_port为串口类型,就触发定时器self.timer.start(1000) + 2、如果self.serial_port == 1(为int类型),则代表硬件中没有温湿度传感器,就没必要触发定时器self.timer.start(1000) + :return: 无返回值 + ''' + + if isinstance(self.serial_port, serial.serialwin32.Serial): + self.timer.start(1000) + elif isinstance(self.serial_port, int): + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + else: + pass + + def plotimg(self): + try: + if self.qt_sender == 'image_mode_record_bt': + plot = self.plot_frame_count_multiple * self.config_file_object.framerate + + img = np.dstack((self.image_camera_operation.rgb[2, 0:plot, :], self.image_camera_operation.rgb[1, 0:plot, :], + self.image_camera_operation.rgb[0, 0:plot, :])) + + self.myImageFigure.setImage(img) + + self.plot_frame_count_multiple += 1 + elif self.qt_sender == 'image_mode_focus_bt': + self.myImageFigure.setImage(self.image_camera_operation.image_container) + + n = int(self.image_camera_operation.image_container.shape[0] / 2) + self.myFocusFigure.plot_wrap(self.image_camera_operation.image_container[n, :]) + + # worker = Worker(self.myImageFigure.setImage, self.image_camera_operation.image_container) + # self.threadpool.start(worker) + except: + self.logger.critical('未知错误--界面中绘制影像和光谱时!\n%s', exc_info=True) + + # 调焦、采集暗电流、采集白板、采集影像 都通过此函数 + def run(self): + try: + self.qt_sender = self.sender().objectName() + + if self.qt_sender == 'image_mode_focus_bt': + if camera.get_framerate() <= 10: # 调焦时控制帧率在20以内,以防帧率过高,界面卡死 + if self.focus_count % 2 == 1: + self.image_mode_focus_bt.setText('停止调焦') + self.core_operation() + self.focus_count += 1 + + self.change_widget_background_color(self.image_mode_focus_bt, 'red') + elif self.focus_count % 2 == 0: + self.image_camera_operation.focus = False + self.image_mode_focus_bt.setText('调焦') + self.focus_count += 1 + else: + self.x = MessageBox('调焦时帧率最大为10!') + elif self.qt_sender == 'image_mode_exposureTime_bt': + self.state = 1 + + self.core_operation() + + self.change_widget_background_color(self.image_mode_exposureTime_bt, 'red') + elif self.qt_sender == 'image_mode_dc_bt': + if self.state == 0: + + self.x = MessageBox('请先曝光!') + elif self.state == 1: # 正常采集暗电流 + self.state = 4 + + self.core_operation() + + self.change_widget_background_color(self.image_mode_dc_bt, 'red') + elif self.state == 4 or self.state == 9: + self.x = MessageBox('已经执行过暗电流!') + elif self.qt_sender == 'image_mode_wb_bt': + if self.state == 0: + self.x = MessageBox('请先曝光 + 暗电流!') + elif self.state == 1: + self.x = MessageBox('请先暗电流!') + elif self.state == 4: # 正常采集白板 + self.state = 9 + + self.core_operation() + + self.change_widget_background_color(self.image_mode_wb_bt, 'red') + elif self.state == 9: # 重新采集白板 + self.state = 9 + + self.core_operation() + + self.change_widget_background_color(self.image_mode_wb_bt, 'red') + elif self.qt_sender == 'image_mode_record_bt': + if self.record_count % 2 == 1: + if self.state == 0: + self.x = MessageBox('请先曝光!') + elif self.state == 1: # 正常采集DN值影像 + if type(self.image_camera_operation.image_dc) is np.ndarray and type( + self.image_camera_operation.image_wb) is np.ndarray: # 这个判断是为了在手动改变曝光时间的情况下,强制让用于重新采集暗电流和白板 + self.x = MessageBox('请重新暗电流+白板!') + else: + self.record_count += 1 + self.plot_frame_count_multiple = 1 # 每次点击采集按钮都将此变量设置为1,用于正常边采集影像边在界面中显示影像 + + self.image_mode_record_bt.setText('停止采集') + + self.core_operation() + + self.change_widget_background_color(self.image_mode_record_bt, 'red') + elif self.state == 4: + self.x = MessageBox('请先白板!') + elif self.state == 9: # 正常采集反射率影像 + self.record_count += 1 + self.plot_frame_count_multiple = 1 # 每次点击采集按钮都将此变量设置为1,用于正常边采集影像边在界面中显示影像 + + self.image_mode_record_bt.setText('停止采集') + + self.core_operation() + + self.change_widget_background_color(self.image_mode_record_bt, 'red') + elif self.record_count % 2 == 0: + self.image_camera_operation.record = False + self.image_mode_record_bt.setText('采集') + self.record_count += 1 + elif self.qt_sender == 'save_bt': + worker = Worker(self.savedata) + + worker.signals.error.connect(self.operate_failed) + worker.signals.finished.connect(self.operate_success) + + self.threadpool.start(worker) + + self.change_widget_background_color(self.save_bt, 'red') + except Exception: + traceback.print_exc() + + # 改变按钮三态中普通态的背景颜色 + def change_widget_background_color(self, qt_widget, color): + pattern = re.compile('background-color(.*)(normal\*/)') + old_style_sheet = qt_widget.styleSheet() + + if color == 'red': + new_style_sheet = re.sub(pattern, r'background-color:rgb(255 , 0 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'green': + new_style_sheet = re.sub(pattern, r'background-color:rgb(0 , 255 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'gray': + new_style_sheet = re.sub(pattern, r'background-color:rgb(225 , 225 , 225);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + + def core_operation(self): + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(self.image_camera_operation.start_AcquireData, camera, self.qt_sender, self.plot_signal) + + worker.signals.error.connect(self.operate_failed) + worker.signals.finished.connect(self.operate_success) + if self.qt_sender == 'image_mode_exposureTime_bt': + ''' + 曝光参数的设置过程: + (1)曝光参数返回到界面中的QLineEdit; + (2)通过QLineEdit的textChanged事件将值写入到camera_operation对应的变量; + (3)为相机设置参数:1)通过worker的finished信号【本程序使用】2)也可以通过QLineEdit的textChanged事件调用self.set_exposure函数,为相机设置参数 + 这种过程的好处是界面显示的曝光参数和实际设置的是同步的 + ''' + worker.signals.result.connect(self.post_auto_expose) + + self.threadpool.start(worker) + + self.disable_bt(True) + + def disable_bt(self, bool): + # 两个if判断存在的原因:调焦/停止调焦(采集/停止采集)使用同一个按钮,所以不能将其设置为不可用 + if self.qt_sender !='image_mode_focus_bt': + self.image_mode_focus_bt.setDisabled(bool) + if self.qt_sender != 'image_mode_record_bt': + self.image_mode_record_bt.setDisabled(bool) + + self.image_mode_exposureTime_bt.setDisabled(bool) + self.image_mode_dc_bt.setDisabled(bool) + self.image_mode_wb_bt.setDisabled(bool) + self.save_bt.setDisabled(bool) + self.arcus_left_bt.setDisabled(bool) + self.arcus_right_bt.setDisabled(bool) + + self.exposure_time_le.setDisabled(bool) + self.framerate_le.setDisabled(bool) + self.arcus_speed_le.setDisabled(bool) + self.framenumber_le.setDisabled(bool) + self.filename_le.setDisabled(bool) + + def operate_failed(self, traceback_info): + if traceback_info[0] == xiapi.Xi_error: + if traceback_info[1].status == 1: # 在ximea的API中代表"Invalid handle":相机断开连接 + if self.qt_sender == 'image_mode_exposureTime_bt': + self.logger.error('自动曝光失败:相机断开连接!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_focus_bt': + self.logger.error('调焦失败:相机断开连接!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_dc_bt': + self.logger.error('采集暗电流失败:相机断开连接!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_wb_bt': + self.logger.error('采集白板失败:相机断开连接!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_record_bt': + self.logger.error('采集影像失败:相机断开连接!\n%s', traceback_info[2]) + elif traceback_info[1].status == 56: # 在ximea的API中代表"No Devices Found":在执行cam.open_device()时,无相机打开 + if self.qt_sender == 'image_mode_exposureTime_bt': + self.logger.error('自动曝光失败:无相机可供打开!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_focus_bt': + self.logger.error('调焦失败:无相机可供打开!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_dc_bt': + self.logger.error('采集暗电流失败:无相机可供打开\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_wb_bt': + self.logger.error('采集白板失败:无相机可供打开\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_record_bt': + self.logger.error('采集影像失败:无相机可供打开\n%s', traceback_info[2]) + elif traceback_info[1].status == 12: # 在ximea的API中代表"Not supported":当相机正在采集数据时,执行代码cam.set_imgdataformat('XI_RAW16') + pass + elif traceback_info[1].status == 41: # 在ximea的API中代表"Acquisition already started":相机已经开始采集数据 + pass + elif traceback_info[0] == ValueError: + if self.qt_sender == 'save_bt': + self.logger.error('保存影像失败--影像名不正确!\n%s', traceback_info[2]) + # QMessageBox.information(self, '提示', '请输入正确的影像名!', QMessageBox.Yes) + + self.x = MessageBox('请输入正确的影像名!') + elif traceback_info[0] == FileNotFoundError: + if self.qt_sender == 'save_bt': + self.logger.error('保存影像失败--没有采集影像!\n%s', traceback_info[2]) + # QMessageBox.information(self, '提示', '请输入正确的影像名!', QMessageBox.Yes) + + self.x = MessageBox('请先采集影像!') + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + + print('operate_failed函数运行成功!') + + def operate_success(self): + if self.qt_sender == 'image_mode_exposureTime_bt': + self.logger.info('自动曝光成功----------------!') + elif self.qt_sender == 'image_mode_focus_bt': + self.logger.info('调焦成功!') + elif self.qt_sender == 'image_mode_dc_bt': + self.image_mode_dc_bt.setText('暗 电 流✔') + + self.logger.info('采集暗电流成功!') + elif self.qt_sender == 'image_mode_wb_bt': + self.image_mode_wb_bt.setText('白 板✔') + + self.logger.info('采集白板成功!') + elif self.qt_sender == 'image_mode_record_bt': + self.logger.info('采集影像成功!') + + self.image_mode_record_bt.setText('采集') + self.record_count += 1 + elif self.qt_sender == 'save_bt': + self.logger.info('保存影像成功!') + + self.disable_bt(False) + + # 当操作成功后,所有按钮都变为初始颜色:灰色 + self.change_widget_background_color(self.image_mode_exposureTime_bt, 'gray') + self.change_widget_background_color(self.image_mode_focus_bt, 'gray') + self.change_widget_background_color(self.image_mode_dc_bt, 'gray') + self.change_widget_background_color(self.image_mode_wb_bt, 'gray') + self.change_widget_background_color(self.image_mode_record_bt, 'gray') + self.change_widget_background_color(self.save_bt, 'gray') + + # 保存影像数据 + def savedata(self): + self.disable_bt(True) # 因为保存影像所需时间较多,所以需要将此行代码放在最前面 + + # 保存路径 + # filename = "%s%s%s" % (re.sub('/', '\\\\', self.config_file_object.image_dir), '\\', self.config_file_object.default_image_name) + filename, file_number = return_file_path([], self.config_file_object.image_dir, + self.config_file_object.default_image_name) + + # 保存影像和头文件 + imagefile = "%s%s%s" % (os.getcwd(), '\\', 'corning410_test') + shutil.copyfile(imagefile, filename) + shutil.copyfile("%s%s" % (imagefile, '.hdr'), "%s%s" % (filename, '.hdr')) + + self.file_number_label.setText(str(file_number)) + + # 将自动曝光返回值写入到界面中的QLineEdit和self.config对象中 + def post_auto_expose(self, result): + ''' + :param result: return cam.get_exposure(), cam.get_gain(), cls.autoexposure_feedback + :return: + ''' + try: + # 将自动曝光得到的结果显示到界面(QLineEdit) + self.exposure_time_le.setText(str(result[0])) + + # 为了防止后面的信号执行延迟;如果延迟,设置曝光时间就会设置为self.config.exposure_time的旧值 + self.config_file_object.exposure_time = result[0] + self.config_file_object.gain = result[1] + + try: + # 将自动曝光值保存到配置文件中 + self.config_file_object.image_signal.emit({'exposure_time': result[0], 'gain': result[1]}) + except: + traceback.print_exc() + + + self.image_camera_operation.set_exposure_gain_framerate(camera) + + if result[2] == 1: + # QMessageBox.information(self, '曝光提示', '光线不足,曝光时间已设置为最大!', QMessageBox.Yes) + + self.x = MessageBox('光线不足,曝光时间已设置为最大!') + self.image_camera_operation.autoexposure_feedback = 0 + except: + traceback.print_exc() + + def closeEvent(self, a0: QtGui.QCloseEvent): + camera.stop_acquisition() + + +# 光谱窗口 +class SpectralWindow(QDialog, Ui_spectral_Window_phone): + # 信号必须定义为类属性,不能放在__init__方法里 + progress_bar_and_plot_spectral_signal = pyqtSignal(int) + + def __init__(self, parent=None): + super(SpectralWindow, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + self.setWindowModality(Qt.ApplicationModal) # 阻塞此窗口:此行代码必须放在show()函数之前 + + # 数据采集保存类,采集数据并将数据保存在此类中,数据采集和界面分离 + + # 配置文件读取和写入类,配置文件读写和界面分离 + # 1、采集数据需要的帧率、曝光、帧数、文件名等等都由此类从文件中读取 + # 2、并保存在此类中 + self.config_file_object = ConfigFile() + + self.spectral_camera_operation = SpectralCameraOperation(self.config_file_object) + + self.progress_bar_and_plot_spectral_signal.connect(self.plot_save_spectral) + + self.state = 0 # 光谱仪操作状态:曝光=1;暗电流=3;白板=5 → 所以只有state==9时才能开始采集光谱 + self.dc_time = time.time() # 用于暗电流计时(从采集成功后那一刻开始) + self.dc_timer = QTimer() + self.dc_timer.timeout.connect(self.dc_timer_slot) + + self.wb_time = time.time() # 用于暗电流计时(从采集成功后那一刻开始) + self.wb_timer = QTimer() + self.wb_timer.timeout.connect(self.wb_timer_slot) + + self.progressBar.setMaximum(self.config_file_object.spectral_number) + self.progressBar.setValue(0) + + # log + self.logger = logging.getLogger('root.spectral') + + if not os.path.exists(self.config_file_object.log_dir + '//spectral_operate.log'): + with open(self.config_file_object.log_dir + '//spectral_operate.log', 'w') as f: + pass + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + spectral_operate_file_handler = logging.FileHandler(self.config_file_object.log_dir + "//spectral_operate.log") # 输出到文件 + spectral_operate_file_handler.setLevel(logging.INFO) + spectral_operate_file_handler.setFormatter(formatter) + self.logger.addHandler(spectral_operate_file_handler) + + # 在窗口中显示串口接收的温度/湿度 + serial_port.serial_signal.connect(self.temperature) + + # 建立进程池 + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 初始化值 + self.filename_le.setText(self.config_file_object.default_spectral_name) + self.spectral_number_le.setText(str(self.config_file_object.spectral_number)) + self.framenumber_average_le.setText(str(self.config_file_object.framenumber_average)) + self.autoexposure_le.setText(str(self.config_file_object.exposure_time_spectral)) + + # 显示光谱和align + # self.spectralFigure = MatplotlibSpectralViewer(xlabel='Wavelength (nm)', ylabel='reflectance') + self.spectralFigure = QtSpectralViewer(ylabel_and_range='reflectance') + self.spe_glo.addWidget(self.spectralFigure) + + #操作光谱仪 + # self.dc_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + self.spectral_mode_autoexposure_bt.clicked.connect(self.run) + self.spectral_mode_wb_bt.clicked.connect(self.run) # 曝光 + 采集白板 + self.spectral_mode_dc_bt.clicked.connect(self.run) + self.spectral_mode_record_bt.clicked.connect(self.run) + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + self.filename_le.editingFinished.connect(self.onchange) + my_regex1 = QRegExp("[a-zA-Z0-9]*") + my_validator1 = QRegExpValidator(my_regex1, self.filename_le) + self.filename_le.setValidator(my_validator1) + + self.autoexposure_le.editingFinished.connect(self.onchange) + my_regex2 = QRegExp("[0-9]*") + my_validator2 = QRegExpValidator(my_regex2, self.autoexposure_le) + self.autoexposure_le.setValidator(my_validator2) + + self.spectral_number_le.editingFinished.connect(self.onchange) + self.framenumber_average_le.editingFinished.connect(self.onchange) + my_regex3 = QRegExp("[0-9]*") + my_validator3 = QRegExpValidator(my_regex2, self.autoexposure_le) + self.spectral_number_le.setValidator(my_validator2) + self.framenumber_average_le.setValidator(my_validator2) + + system_setting.camera_status_signal.connect(self.test_imager_status) + + def test_imager_status(self, imager_status): + if imager_status == 1000: # 相机打开成功 + # print('相机打开成功!') + + self.camera_status_label.setText('光谱仪:正常') + self.change_widget_background_color(self.camera_status_label, 'green') + elif imager_status == 1001: + print('相机打开时出现不是ximea错误的未知错误!') + elif imager_status == 1: + # print('相机已经断开连接!请重新打开软件尝试连接相机!') + + self.camera_status_label.setText('光谱仪:断开连接') + self.change_widget_background_color(self.camera_status_label, 'red') + + self.setEnabled(False) + self.close() + elif imager_status == 12: + pass + elif imager_status == 41: + pass + elif imager_status == 56: + print('没有检测到光谱仪!') + elif imager_status == 103: + pass + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + def onchange(self): + try: + if self.sender().objectName() == 'autoexposure_le': + self.state = 1 # 手动改变曝光时间后,需要强制让用户重新采集暗电流和白板 + + exposure_time_tmp = int(self.autoexposure_le.text()) + + self.config_file_object.spectral_signal.emit({'exposure_time_spectral': exposure_time_tmp}) + + camera.set_exposure(exposure_time_tmp) # 曝光时间单位为微秒,1s共有1000000微秒 + # camera.set_gain(int(float(self.config_file_object.gain))) # int('0.0')会报错,int(float('0.0'))不会报错 + + self.logger.info('手动改变曝光时间!') + elif self.sender().objectName() == 'framenumber_average_le': + framenumber_average_tmp = int(self.framenumber_average_le.text()) + + self.config_file_object.spectral_signal.emit({'framenumber_average': framenumber_average_tmp}) + + self.spectral_camera_operation.create_image_container(framenumber_average_tmp) + + self.logger.info('手动改变每条光谱的平均帧数!') + elif self.sender().objectName() == 'spectral_number_le': + spectral_number_tmp = int(self.spectral_number_le.text()) + + self.config_file_object.spectral_signal.emit({'spectral_number': spectral_number_tmp}) + + self.progressBar.setMaximum(spectral_number_tmp) + self.progressBar.setValue(0) + + self.spectral_camera_operation.create_spectral_container(spectral_number_tmp) + + self.logger.info('手动改变保存的光谱数!') + elif self.sender().objectName() == 'filename_le': + filename = self.filename_le.text() + + if filename != '': + self.config_file_object.spectral_signal.emit({'default_spectral_name': filename}) + + self.logger.info('改变光谱文件名!') + except: + traceback.print_exc() + + def plot_save_spectral(self, x): + try: + self.progressBar.setValue(x) + + # 画出光谱 + if self.data_type_comboBox.currentText() == 'DN': + self.spectralFigure.plot_wrap(self.spectral_camera_operation.spectral_dn[:, 0], self.spectral_camera_operation.spectral_dn[:, x]) + if self.data_type_comboBox.currentText() == 'Rad': + self.spectralFigure.plot_wrap(self.spectral_camera_operation.spectral_dn[:, 0], self.spectral_camera_operation.spectral_rad[:, x]) + if self.data_type_comboBox.currentText() == 'Ref': + self.spectralFigure.plot_wrap(self.spectral_camera_operation.spectral_dn[:, 0], self.spectral_camera_operation.spectral_ref[:, x]) + + # 保存光谱 + filename_dn, file_number_dn = return_file_path([], self.config_file_object.spectral_dir, + self.config_file_object.default_spectral_name + '_dn', model='spectral') + filename_rad, file_number_rad = return_file_path([], self.config_file_object.spectral_dir, + self.config_file_object.default_spectral_name + '_rad', model='spectral') + filename_ref, file_number_ref = return_file_path([], self.config_file_object.spectral_dir, + self.config_file_object.default_spectral_name + '_ref', model='spectral') + # print(filename_ref) + + header_dn = self.get_spectral_metadata('DN') + header_rad = self.get_spectral_metadata('RAD') + header_ref = self.get_spectral_metadata('REF') + + np.savetxt(filename_dn, self.spectral_camera_operation.spectral_dn[:, [0, x]], fmt='%f', header=header_dn) + np.savetxt(filename_rad, self.spectral_camera_operation.spectral_rad[:, [0, x]], fmt='%f', header=header_rad) + np.savetxt(filename_ref, self.spectral_camera_operation.spectral_ref[:, [0, x]], fmt='%f', header=header_ref) + + self.file_number_label.setText(str(file_number_dn)) + except: + traceback.print_exc() + + def get_spectral_metadata(self, data_type_str): + + record_time = "%s%s" % ('RecordTime = ', str(datetime.datetime.now())) + SN = 'SN = 0001' + exposure_time = "%s%s" % ('ExposureTime = ', str(camera.get_exposure())) + data_type = "%s%s" % ('DataType = ', data_type_str) + + header = '%s%s%s%s%s%s%s' % (record_time, '\n', SN, '\n', exposure_time, '\n', data_type) + return header + + def temperature(self, data): + try: + self.t_label.setText('温度:' + data[0]) + self.hum_label.setText('湿度:' + data[1]) + except: + traceback.print_exc() + print('有问题') + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + self.t_label.setText('温度:无数据') + self.hum_label.setText('湿度:无数据') + + def dc_timer_slot(self): + now = time.time() + x = now - self.dc_time + self.dc_timer_label.setText(str(int(x)) + 's') + + def wb_timer_slot(self): + now = time.time() + x = now - self.wb_time + self.wb_timer_label.setText(str(int(x)) + 's') + + def run(self): + self.qt_sender = self.sender().objectName() + + # 操作状态显示 + if self.qt_sender == 'spectral_mode_autoexposure_bt': + print('SpectralWindow采集曝光') + + self.logger.info('曝光...') + + self.state = 1 + + self.core_operation() + + self.change_widget_background_color(self.spectral_mode_autoexposure_bt, 'red') + elif self.qt_sender == 'spectral_mode_dc_bt': + try: + if self.state == 0: + # QMessageBox.information(self, '提示', '请先曝光!', QMessageBox.Yes) + self.x = MessageBox('请先曝光!') + elif self.state == 1 or self.state == 4 or self.state == 9: + self.logger.info('采集暗电流...') + self.state = 4 + + # 暗电流计时 + self.dc_time = time.time() + self.dc_timer.start(2000) + + self.core_operation() + + self.change_widget_background_color(self.spectral_mode_dc_bt, 'red') + except: + traceback.print_exc() + elif self.qt_sender == 'spectral_mode_wb_bt': + if self.state == 0: + self.x = MessageBox('请先曝光+暗电流!') + elif self.state == 1: + self.x = MessageBox('请先采集暗电流!') + elif self.state == 4 or self.state == 9: + self.logger.info('采集白板...') + self.state = 9 + + # 白板计时 + self.wb_time = time.time() + self.wb_timer.start(2000) + + self.core_operation() + + self.change_widget_background_color(self.spectral_mode_wb_bt, 'red') + elif self.qt_sender == 'spectral_mode_record_bt': + if self.state == 0: + self.x = MessageBox('请先曝光+暗电流+白板') + elif self.state == 1: + # QMessageBox.information(self, '提示', '请先采集暗电流!', QMessageBox.Yes) + self.x = MessageBox('请先暗电流+白板') + elif self.state == 4: + # QMessageBox.information(self, '提示', '请先采集暗电流!', QMessageBox.Yes) + self.x = MessageBox('请先白板') + elif self.state == 9: + self.logger.info('采集光谱...') + + self.core_operation() + + self.change_widget_background_color(self.spectral_mode_record_bt, 'red') + + # 改变按钮三态中普通态的背景颜色 + def change_widget_background_color(self, qt_widget, color): + pattern = re.compile('background-color(.*)(normal\*/)') + old_style_sheet = qt_widget.styleSheet() + + if color == 'red': + new_style_sheet = re.sub(pattern, r'background-color:rgb(255 , 0 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'green': + new_style_sheet = re.sub(pattern, r'background-color:rgb(0 , 255 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'gray': + new_style_sheet = re.sub(pattern, r'background-color:rgb(225 , 225 , 225);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + + # 将自动曝光返回值写入到界面中的QLineEdit和self.config_file_object对象中 + def post_auto_expose(self, result): + ''' + :param result: return cam.get_exposure(), cam.get_gain(), cls.autoexposure_feedback + :return: + ''' + + # 将自动曝光得到的结果显示到界面(QLineEdit) + self.autoexposure_le.setText(str(result[0])) + + # # 为了防止后面的信号执行延迟;如果延迟,设置曝光时间就会设置为self.config_file_object.exposure_time的旧值 + # self.config_file_object.exposure_time = result[0] + # self.config_file_object.gain = result[1] + + def core_operation(self): + worker = Worker(self.spectral_camera_operation.start_AcquireData, camera, self.qt_sender, + self.progress_bar_and_plot_spectral_signal) + worker.signals.finished.connect(self.operate_success) + worker.signals.error.connect(self.operate_failed) + + if self.qt_sender == 'spectral_mode_autoexposure_bt': + ''' + 曝光参数的设置过程: + (1)曝光参数返回到界面中的QLineEdit; + (2)通过QLineEdit的textChanged事件将值写入到camera_operation对应的变量; + (3)为相机设置参数:1)通过worker的finished信号【本程序使用】2)也可以通过QLineEdit的textChanged事件调用self.set_exposure函数,为相机设置参数 + 这种过程的好处是界面显示的曝光参数和实际设置的是同步的 + ''' + worker.signals.result.connect(self.post_auto_expose) + + self.threadpool.start(worker) + + self.disable_bt_le(True) + + def operate_failed(self, traceback_info): + if traceback_info[0] == xiapi.Xi_error: + if self.qt_sender == 'spectral_mode_wb_bt': + self.logger.error('曝光/白板失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_align_bt': + self.logger.error('align 失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_dc_bt': + self.logger.error('采集暗电流失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_record_bt': + self.logger.error('采集光谱失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif traceback_info[0] == ValueError: + if self.qt_sender == 'spectral_mode_record_bt': + self.logger.error('保存光谱失败!\n%s', traceback_info[2]) + # QMessageBox.information(self, '提示', '请输入正确的光谱名!', QMessageBox.Yes) + + self.x = MessageBox('请输入正确的光谱名!') + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + + def operate_success(self): + # 操作状态显示 + if self.qt_sender == 'spectral_mode_autoexposure_bt': + self.logger.info('曝光成功!') + elif self.qt_sender == 'spectral_mode_dc_bt': + self.logger.info('采集暗电流成功!') + elif self.qt_sender == 'spectral_mode_wb_bt': + self.logger.info('采集白板成功!') + elif self.qt_sender == 'spectral_mode_align_bt': + self.logger.info('align successfully!') + elif self.qt_sender == 'spectral_mode_record_bt': + self.logger.info('采集光谱成功!') + + self.disable_bt_le(False) + + # 当操作成功后,所有按钮都变为初始颜色:灰色 + self.change_widget_background_color(self.spectral_mode_autoexposure_bt, 'gray') + self.change_widget_background_color(self.spectral_mode_dc_bt, 'gray') + self.change_widget_background_color(self.spectral_mode_wb_bt, 'gray') + self.change_widget_background_color(self.spectral_mode_record_bt, 'gray') + + def disable_bt_le(self, bool): + self.spectral_mode_autoexposure_bt.setDisabled(bool) + self.spectral_mode_dc_bt.setDisabled(bool) + self.spectral_mode_wb_bt.setDisabled(bool) + self.spectral_mode_record_bt.setDisabled(bool) + + self.spectral_number_le.setDisabled(bool) + self.framenumber_average_le.setDisabled(bool) + self.autoexposure_le.setDisabled(bool) + self.filename_le.setDisabled(bool) + + def closeEvent(self, a0: QtGui.QCloseEvent): + camera.stop_acquisition() + + +# 影像模式类:相关的函数和变量 +class CameraOperation(object): + def __init__(self, config_file_object): + self.config_file_object = config_file_object + + # self.startRow = 339 + # self.endRow = 639 + # self.startColumn = 285 + # self.endColumn = 1649 + + # 转辐亮度 + self.rad_or_not = False + if self.config_file_object.binning == 1: + self.img_gain = get_resource_path('./data/lens_bin1_gain_SN0073') + self.cal_it = 7266 + elif self.config_file_object.binning == 2: + self.img_gain = get_resource_path('./data/lens_bin2_gain_SN0073') + self.cal_it = 1621 + _, _, self.gain = ImageReaderWriter.read_img(self.img_gain) + + self.gain = self.gain.astype(np.float32) + self.target_it = None + self.gain_scale = None + + # + self.arcus_reverse_while_record = False + self.record_DN = False + + # 开始采集数据 + self.image_dc = None # 随便给个初始值,此变量用于存储采集到的暗电流影像 + self.image_wb = None # 随便给个初始值,此变量用于存储采集到的白板影像 + self.focus = True # 用于停止调焦 + self.record = True # 用于停止采集 + self.img_datatype = 12 # 在头文件中确定影像数据类型 + + self.autoexposure_feedback = 0 # 指示:自动曝光所得到的shutter值是否为最大;如果为最大→值设置为1 + + # 创建rgb数据,用于在界面中显示 + self.create_rgb() + + def create_rgb(self): + self.rgb = np.ones((3, int(self.config_file_object.frame_number), self.config_file_object.end_column - self.config_file_object.start_column)) + + # 手动改变界面上的曝光值和gain值后,设置相机的曝光值和gain值所用 + def set_exposure_gain_framerate(self, cam): + # settings,cam.set_param("exposure",10000) + cam.set_framerate(self.config_file_object.framerate) + cam.set_exposure(self.config_file_object.exposure_time) # 曝光时间单位为微秒,1s共有1000000微秒 + cam.set_gain(self.config_file_object.gain) #int('0.0')会报错,int(float('0.0'))不会报错 + + print('set_exposure_gain_framerate运行成功') + + def start_AcquireData(self, cam, qt_sender, plot_signal=None): # qt_sender是指qt窗口中事件的发生者 + ''' + :param cam: 实例化的相机句柄 + :param qt_sender: 调用本方法时,点击的界面上的按钮名; + :param plot_signal: + :return: + ''' + # 创建img = xiapi.Image()前需要设置一系列img参数,例如:格式、位深度、 + # 如果格式设置为XI_RAW8,image_raw_numpy.dtype -> dtype('uint8'), uint8 + # 如果格式设置为XI_RAW16,image_raw_numpy.dtype -> dtype('= 4090: + cam.set_exposure(int(0.9 * cam.get_exposure())) + + cam.start_acquisition() + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + image_raw_numpy = img.get_image_data_numpy() + + # 如果因为光线不足曝光值达到了最大,就将曝光反馈变量设置为1 + if cam.get_exposure() > int(1 / self.config_file_object.framerate * 10**6): + cam.set_exposure(int(1 / self.config_file_object.framerate * 10**6)) + self.autoexposure_feedback = 1 + else: + cam.set_exposure(cam.get_exposure()) + + # 计算gain + self.target_it = cam.get_exposure() + self.gain_scale = self.cal_it / self.target_it + self.gain = self.gain * self.gain_scale + + print('start_AcquireData--自动曝光运行结束') + + # 如果点击“调焦”按钮 + if qt_sender == 'image_mode_focus_bt': + # cls.set_exposureTime(cam) + + # 当关闭调焦后,再次打开调焦功能需要将cls.focus的值从False变为True + if not self.focus: + self.focus = True + + cam.start_acquisition() + + while self.focus: + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + self.image_container = image_raw_numpy[self.config_file_object.start_row:self.config_file_object.end_row, + self.config_file_object.start_column:self.config_file_object.end_column] + + if plot_signal is not None: + plot_signal.emit() + + # 如果点击“暗电流”按钮,采集并保存暗电流影像到image_dc + if qt_sender == 'image_mode_dc_bt': + framenumber = 10 + image_container = np.empty(( + self.config_file_object.end_row - self.config_file_object.start_row, framenumber, + self.config_file_object.end_column - self.config_file_object.start_column)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[self.config_file_object.start_row:self.config_file_object.end_row, self.config_file_object.start_column:self.config_file_object.end_column] + + image_container = image_container.mean(axis=1) + + self.image_dc = image_container + + # 如果点击“白板”按钮,采集并保存白板影像到image_wb + if qt_sender == 'image_mode_wb_bt': + framenumber = 10 + image_container = np.empty(( + self.config_file_object.end_row - self.config_file_object.start_row, framenumber, + self.config_file_object.end_column - self.config_file_object.start_column)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[ + self.config_file_object.start_row:self.config_file_object.end_row, + self.config_file_object.start_column:self.config_file_object.end_column] + + image_container = image_container.mean(axis=1) + + # 扣除暗电流的白板 + self.image_wb = image_container - self.image_dc + + # 如果点击“采集”按钮,自动去除暗电流,并且转化成反射率 + if qt_sender == 'image_mode_record_bt': + frameCount = 1 # 统计采集的帧数,用于停止采集使用 + + # 当停止采集后,再次开始采集需要将cls.record的值从False变为True + if not self.record: + self.record = True + + # 启动马达 + self.arcus_start() + + # 开始采集数据 并且 将数据写入到硬盘中 + cam.start_acquisition() + with open('corning410_test', 'wb') as f: + + print('Starting data acquisition...') + startTime = datetime.datetime.now() + + while self.record: + cam.get_image(img) # get data and pass them from camera to img + # image_raw_numpy.dtype -> dtype(' + + enter_Window + + + true + + + + 0 + 0 + 651 + 474 + + + + 主窗口 + + + + + + + true + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:30pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + + + 正在打开相机... + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0); + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 光谱模式 + + + + + + + true + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0); + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 影像模式 + + + + + + + + + 0 + 0 + 651 + 23 + + + + + + + wew e + + + + + + diff --git a/record_system_v26/ui/image_Window_phone.py b/record_system_v26/ui/image_Window_phone.py new file mode 100644 index 0000000..727ee3e --- /dev/null +++ b/record_system_v26/ui/image_Window_phone.py @@ -0,0 +1,830 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'image_Window_phone.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_image_Window_phone(object): + def setupUi(self, image_Window_phone): + image_Window_phone.setObjectName("image_Window_phone") + image_Window_phone.setEnabled(True) + image_Window_phone.resize(518, 1174) + image_Window_phone.setMouseTracking(False) + image_Window_phone.setAutoFillBackground(False) + image_Window_phone.setSizeGripEnabled(False) + image_Window_phone.setModal(False) + self.gridLayout_6 = QtWidgets.QGridLayout(image_Window_phone) + self.gridLayout_6.setObjectName("gridLayout_6") + self.splitter = QtWidgets.QSplitter(image_Window_phone) + self.splitter.setOrientation(QtCore.Qt.Vertical) + self.splitter.setObjectName("splitter") + self.frame_2 = QtWidgets.QFrame(self.splitter) + self.frame_2.setFrameShape(QtWidgets.QFrame.Box) + self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_2.setObjectName("frame_2") + self.gridLayout_2 = QtWidgets.QGridLayout(self.frame_2) + self.gridLayout_2.setContentsMargins(0, 0, 0, 0) + self.gridLayout_2.setObjectName("gridLayout_2") + self.image_glo = QtWidgets.QGridLayout() + self.image_glo.setObjectName("image_glo") + self.gridLayout_2.addLayout(self.image_glo, 0, 0, 1, 1) + self.frame = QtWidgets.QFrame(self.splitter) + self.frame.setMaximumSize(QtCore.QSize(16777215, 600)) + self.frame.setFrameShape(QtWidgets.QFrame.Box) + self.frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame.setObjectName("frame") + self.gridLayout = QtWidgets.QGridLayout(self.frame) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.focus_glo = QtWidgets.QGridLayout() + self.focus_glo.setObjectName("focus_glo") + self.gridLayout.addLayout(self.focus_glo, 0, 0, 1, 1) + self.gridLayout_6.addWidget(self.splitter, 0, 0, 1, 1) + self.frame_3 = QtWidgets.QFrame(image_Window_phone) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_3.sizePolicy().hasHeightForWidth()) + self.frame_3.setSizePolicy(sizePolicy) + self.frame_3.setMaximumSize(QtCore.QSize(16777215, 600)) + self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_3.setObjectName("frame_3") + self.gridLayout_5 = QtWidgets.QGridLayout(self.frame_3) + self.gridLayout_5.setContentsMargins(0, 0, 0, 0) + self.gridLayout_5.setObjectName("gridLayout_5") + self.frame_7 = QtWidgets.QFrame(self.frame_3) + self.frame_7.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_7.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_7.setObjectName("frame_7") + self.gridLayout_4 = QtWidgets.QGridLayout(self.frame_7) + self.gridLayout_4.setContentsMargins(0, 0, 0, 0) + self.gridLayout_4.setObjectName("gridLayout_4") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.image_mode_exposureTime_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_exposureTime_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_exposureTime_bt.setSizePolicy(sizePolicy) + self.image_mode_exposureTime_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_exposureTime_bt.setFont(font) + self.image_mode_exposureTime_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_exposureTime_bt.setAutoDefault(False) + self.image_mode_exposureTime_bt.setObjectName("image_mode_exposureTime_bt") + self.verticalLayout.addWidget(self.image_mode_exposureTime_bt) + self.image_mode_focus_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_focus_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_focus_bt.setSizePolicy(sizePolicy) + self.image_mode_focus_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_focus_bt.setFont(font) + self.image_mode_focus_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_focus_bt.setAutoDefault(False) + self.image_mode_focus_bt.setObjectName("image_mode_focus_bt") + self.verticalLayout.addWidget(self.image_mode_focus_bt) + self.image_mode_dc_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_dc_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_dc_bt.setSizePolicy(sizePolicy) + self.image_mode_dc_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_dc_bt.setFont(font) + self.image_mode_dc_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_dc_bt.setAutoDefault(False) + self.image_mode_dc_bt.setObjectName("image_mode_dc_bt") + self.verticalLayout.addWidget(self.image_mode_dc_bt) + self.image_mode_wb_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_wb_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_wb_bt.setSizePolicy(sizePolicy) + self.image_mode_wb_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_wb_bt.setFont(font) + self.image_mode_wb_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_wb_bt.setAutoDefault(False) + self.image_mode_wb_bt.setObjectName("image_mode_wb_bt") + self.verticalLayout.addWidget(self.image_mode_wb_bt) + self.image_mode_record_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_record_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_record_bt.setSizePolicy(sizePolicy) + self.image_mode_record_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_record_bt.setFont(font) + self.image_mode_record_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_record_bt.setAutoDefault(False) + self.image_mode_record_bt.setObjectName("image_mode_record_bt") + self.verticalLayout.addWidget(self.image_mode_record_bt) + self.save_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.save_bt.sizePolicy().hasHeightForWidth()) + self.save_bt.setSizePolicy(sizePolicy) + self.save_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.save_bt.setFont(font) + self.save_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.save_bt.setAutoDefault(False) + self.save_bt.setObjectName("save_bt") + self.verticalLayout.addWidget(self.save_bt) + self.gridLayout_4.addLayout(self.verticalLayout, 0, 0, 1, 1) + self.gridLayout_5.addWidget(self.frame_7, 0, 0, 1, 1) + self.frame_6 = QtWidgets.QFrame(self.frame_3) + self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_6.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_6.setObjectName("frame_6") + self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_6) + self.gridLayout_3.setContentsMargins(0, 0, 0, 0) + self.gridLayout_3.setObjectName("gridLayout_3") + self.frame_8 = QtWidgets.QFrame(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_8.sizePolicy().hasHeightForWidth()) + self.frame_8.setSizePolicy(sizePolicy) + self.frame_8.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_8.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_8.setLineWidth(0) + self.frame_8.setObjectName("frame_8") + self.gridLayout_3.addWidget(self.frame_8, 3, 0, 1, 1) + self.frame_10 = QtWidgets.QFrame(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_10.sizePolicy().hasHeightForWidth()) + self.frame_10.setSizePolicy(sizePolicy) + self.frame_10.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_10.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_10.setObjectName("frame_10") + self.gridLayout_8 = QtWidgets.QGridLayout(self.frame_10) + self.gridLayout_8.setContentsMargins(0, 0, 0, 0) + self.gridLayout_8.setSpacing(0) + self.gridLayout_8.setObjectName("gridLayout_8") + self.label_2 = QtWidgets.QLabel(self.frame_10) + self.label_2.setMinimumSize(QtCore.QSize(110, 0)) + self.label_2.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.gridLayout_8.addWidget(self.label_2, 0, 0, 1, 1) + self.framenumber_le = QtWidgets.QLineEdit(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.framenumber_le.sizePolicy().hasHeightForWidth()) + self.framenumber_le.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setPointSize(42) + self.framenumber_le.setFont(font) + self.framenumber_le.setObjectName("framenumber_le") + self.gridLayout_8.addWidget(self.framenumber_le, 0, 1, 1, 1) + self.gridLayout_3.addWidget(self.frame_10, 4, 0, 1, 1) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.label_3 = QtWidgets.QLabel(self.frame_6) + self.label_3.setMinimumSize(QtCore.QSize(110, 0)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(20) + self.label_3.setFont(font) + self.label_3.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.horizontalLayout_3.addWidget(self.label_3) + self.framerate_le = QtWidgets.QLineEdit(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.framerate_le.sizePolicy().hasHeightForWidth()) + self.framerate_le.setSizePolicy(sizePolicy) + self.framerate_le.setMaximumSize(QtCore.QSize(16777215, 106)) + font = QtGui.QFont() + font.setPointSize(42) + self.framerate_le.setFont(font) + self.framerate_le.setReadOnly(False) + self.framerate_le.setObjectName("framerate_le") + self.horizontalLayout_3.addWidget(self.framerate_le) + self.gridLayout_3.addLayout(self.horizontalLayout_3, 1, 0, 1, 1) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.label_5 = QtWidgets.QLabel(self.frame_6) + self.label_5.setMinimumSize(QtCore.QSize(110, 0)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(20) + self.label_5.setFont(font) + self.label_5.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_5.setObjectName("label_5") + self.horizontalLayout_4.addWidget(self.label_5) + self.exposure_time_le = QtWidgets.QLineEdit(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.exposure_time_le.sizePolicy().hasHeightForWidth()) + self.exposure_time_le.setSizePolicy(sizePolicy) + self.exposure_time_le.setMaximumSize(QtCore.QSize(16777215, 106)) + font = QtGui.QFont() + font.setPointSize(42) + self.exposure_time_le.setFont(font) + self.exposure_time_le.setObjectName("exposure_time_le") + self.horizontalLayout_4.addWidget(self.exposure_time_le) + self.gridLayout_3.addLayout(self.horizontalLayout_4, 0, 0, 1, 1) + self.frame_5 = QtWidgets.QFrame(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_5.sizePolicy().hasHeightForWidth()) + self.frame_5.setSizePolicy(sizePolicy) + self.frame_5.setMinimumSize(QtCore.QSize(160, 0)) + self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_5.setObjectName("frame_5") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_5) + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_7 = QtWidgets.QLabel(self.frame_5) + self.label_7.setMinimumSize(QtCore.QSize(110, 0)) + self.label_7.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_7.setAlignment(QtCore.Qt.AlignCenter) + self.label_7.setObjectName("label_7") + self.horizontalLayout_2.addWidget(self.label_7) + self.arcus_left_bt = QtWidgets.QPushButton(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_left_bt.sizePolicy().hasHeightForWidth()) + self.arcus_left_bt.setSizePolicy(sizePolicy) + self.arcus_left_bt.setMinimumSize(QtCore.QSize(50, 0)) + self.arcus_left_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.arcus_left_bt.setFont(font) + self.arcus_left_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.arcus_left_bt.setAutoDefault(False) + self.arcus_left_bt.setObjectName("arcus_left_bt") + self.horizontalLayout_2.addWidget(self.arcus_left_bt) + self.arcus_speed_le = QtWidgets.QLineEdit(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_speed_le.sizePolicy().hasHeightForWidth()) + self.arcus_speed_le.setSizePolicy(sizePolicy) + self.arcus_speed_le.setMinimumSize(QtCore.QSize(60, 0)) + self.arcus_speed_le.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setPointSize(42) + self.arcus_speed_le.setFont(font) + self.arcus_speed_le.setObjectName("arcus_speed_le") + self.horizontalLayout_2.addWidget(self.arcus_speed_le) + self.arcus_right_bt = QtWidgets.QPushButton(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_right_bt.sizePolicy().hasHeightForWidth()) + self.arcus_right_bt.setSizePolicy(sizePolicy) + self.arcus_right_bt.setMinimumSize(QtCore.QSize(50, 0)) + self.arcus_right_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.arcus_right_bt.setFont(font) + self.arcus_right_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.arcus_right_bt.setAutoDefault(False) + self.arcus_right_bt.setObjectName("arcus_right_bt") + self.horizontalLayout_2.addWidget(self.arcus_right_bt) + self.gridLayout_3.addWidget(self.frame_5, 2, 0, 1, 1) + self.frame_9 = QtWidgets.QFrame(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_9.sizePolicy().hasHeightForWidth()) + self.frame_9.setSizePolicy(sizePolicy) + self.frame_9.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_9.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_9.setLineWidth(0) + self.frame_9.setObjectName("frame_9") + self.gridLayout_7 = QtWidgets.QGridLayout(self.frame_9) + self.gridLayout_7.setContentsMargins(0, 0, 0, 0) + self.gridLayout_7.setSpacing(0) + self.gridLayout_7.setObjectName("gridLayout_7") + self.filename_le = QtWidgets.QLineEdit(self.frame_9) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.filename_le.sizePolicy().hasHeightForWidth()) + self.filename_le.setSizePolicy(sizePolicy) + self.filename_le.setMaximumSize(QtCore.QSize(16777215, 106)) + font = QtGui.QFont() + font.setPointSize(42) + self.filename_le.setFont(font) + self.filename_le.setObjectName("filename_le") + self.gridLayout_7.addWidget(self.filename_le, 0, 1, 1, 1) + self.file_number_label = QtWidgets.QLabel(self.frame_9) + self.file_number_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.file_number_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.file_number_label.setAlignment(QtCore.Qt.AlignCenter) + self.file_number_label.setObjectName("file_number_label") + self.gridLayout_7.addWidget(self.file_number_label, 0, 2, 1, 1) + self.label_6 = QtWidgets.QLabel(self.frame_9) + self.label_6.setMinimumSize(QtCore.QSize(110, 0)) + self.label_6.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_6.setAlignment(QtCore.Qt.AlignCenter) + self.label_6.setObjectName("label_6") + self.gridLayout_7.addWidget(self.label_6, 0, 0, 1, 1) + self.gridLayout_3.addWidget(self.frame_9, 6, 0, 1, 1) + self.gridLayout_5.addWidget(self.frame_6, 0, 1, 1, 1) + self.gridLayout_6.addWidget(self.frame_3, 1, 0, 1, 1) + self.frame_4 = QtWidgets.QFrame(image_Window_phone) + self.frame_4.setMinimumSize(QtCore.QSize(0, 0)) + self.frame_4.setMaximumSize(QtCore.QSize(16777215, 35)) + self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_4.setObjectName("frame_4") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_4) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout.setSpacing(0) + self.horizontalLayout.setObjectName("horizontalLayout") + spacerItem = QtWidgets.QSpacerItem(233, 12, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.t_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.t_label.sizePolicy().hasHeightForWidth()) + self.t_label.setSizePolicy(sizePolicy) + self.t_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.t_label.setAlignment(QtCore.Qt.AlignCenter) + self.t_label.setObjectName("t_label") + self.horizontalLayout.addWidget(self.t_label) + self.hum_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.hum_label.sizePolicy().hasHeightForWidth()) + self.hum_label.setSizePolicy(sizePolicy) + self.hum_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.hum_label.setAlignment(QtCore.Qt.AlignCenter) + self.hum_label.setObjectName("hum_label") + self.horizontalLayout.addWidget(self.hum_label) + self.camera_status_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.camera_status_label.sizePolicy().hasHeightForWidth()) + self.camera_status_label.setSizePolicy(sizePolicy) + self.camera_status_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.camera_status_label.setAlignment(QtCore.Qt.AlignCenter) + self.camera_status_label.setObjectName("camera_status_label") + self.horizontalLayout.addWidget(self.camera_status_label) + self.arcus_status_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_status_label.sizePolicy().hasHeightForWidth()) + self.arcus_status_label.setSizePolicy(sizePolicy) + self.arcus_status_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.arcus_status_label.setAlignment(QtCore.Qt.AlignCenter) + self.arcus_status_label.setObjectName("arcus_status_label") + self.horizontalLayout.addWidget(self.arcus_status_label) + self.gridLayout_6.addWidget(self.frame_4, 2, 0, 1, 1) + + self.retranslateUi(image_Window_phone) + QtCore.QMetaObject.connectSlotsByName(image_Window_phone) + + def retranslateUi(self, image_Window_phone): + _translate = QtCore.QCoreApplication.translate + image_Window_phone.setWindowTitle(_translate("image_Window_phone", "影像窗口")) + self.image_mode_exposureTime_bt.setText(_translate("image_Window_phone", "曝 光")) + self.image_mode_focus_bt.setText(_translate("image_Window_phone", "调 焦")) + self.image_mode_dc_bt.setText(_translate("image_Window_phone", "暗 电 流")) + self.image_mode_wb_bt.setText(_translate("image_Window_phone", "白 板")) + self.image_mode_record_bt.setText(_translate("image_Window_phone", "采 集")) + self.save_bt.setText(_translate("image_Window_phone", "保 存")) + self.label_2.setText(_translate("image_Window_phone", "帧 数")) + self.label_3.setText(_translate("image_Window_phone", "帧 率")) + self.label_5.setText(_translate("image_Window_phone", "积分时间")) + self.label_7.setText(_translate("image_Window_phone", "马 达")) + self.arcus_left_bt.setText(_translate("image_Window_phone", "<")) + self.arcus_right_bt.setText(_translate("image_Window_phone", ">")) + self.file_number_label.setText(_translate("image_Window_phone", "文件号")) + self.label_6.setText(_translate("image_Window_phone", "命 名")) + self.t_label.setText(_translate("image_Window_phone", "温度:无数据")) + self.hum_label.setText(_translate("image_Window_phone", "湿度:无数据")) + self.camera_status_label.setText(_translate("image_Window_phone", "光谱仪:连接失败")) + self.arcus_status_label.setText(_translate("image_Window_phone", "马达:连接失败!")) diff --git a/record_system_v26/ui/image_Window_phone.ui b/record_system_v26/ui/image_Window_phone.ui new file mode 100644 index 0000000..4c21f58 --- /dev/null +++ b/record_system_v26/ui/image_Window_phone.ui @@ -0,0 +1,1323 @@ + + + image_Window_phone + + + true + + + + 0 + 0 + 518 + 1174 + + + + false + + + 影像窗口 + + + false + + + false + + + false + + + + + + Qt::Vertical + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 16777215 + 600 + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 600 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 曝 光 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 调 焦 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 暗 电 流 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 白 板 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 采 集 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 保 存 + + + false + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + 0 + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 数 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 42 + + + + + + + + + + + + + + 110 + 0 + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 率 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + false + + + + + + + + + + + + 110 + 0 + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 积分时间 + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + + + 0 + 0 + + + + + 160 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 马 达 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + < + + + false + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + > + + + false + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + 200 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文件号 + + + Qt::AlignCenter + + + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 命 名 + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 233 + 12 + + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 温度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 湿度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 光谱仪:连接失败 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 马达:连接失败! + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/record_system_v26/ui/spectral_Window_phone.py b/record_system_v26/ui/spectral_Window_phone.py new file mode 100644 index 0000000..1e6c05d --- /dev/null +++ b/record_system_v26/ui/spectral_Window_phone.py @@ -0,0 +1,629 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'spectral_Window_phone.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_spectral_Window_phone(object): + def setupUi(self, spectral_Window_phone): + spectral_Window_phone.setObjectName("spectral_Window_phone") + spectral_Window_phone.resize(540, 1175) + self.gridLayout_6 = QtWidgets.QGridLayout(spectral_Window_phone) + self.gridLayout_6.setObjectName("gridLayout_6") + self.frame = QtWidgets.QFrame(spectral_Window_phone) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth()) + self.frame.setSizePolicy(sizePolicy) + self.frame.setMinimumSize(QtCore.QSize(0, 600)) + self.frame.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame.setObjectName("frame") + self.gridLayout = QtWidgets.QGridLayout(self.frame) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.spe_glo = QtWidgets.QGridLayout() + self.spe_glo.setObjectName("spe_glo") + self.gridLayout.addLayout(self.spe_glo, 0, 0, 1, 1) + self.gridLayout_6.addWidget(self.frame, 0, 0, 1, 1) + self.frame_2 = QtWidgets.QFrame(spectral_Window_phone) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth()) + self.frame_2.setSizePolicy(sizePolicy) + self.frame_2.setMaximumSize(QtCore.QSize(16777215, 600)) + self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_2.setObjectName("frame_2") + self.gridLayout_8 = QtWidgets.QGridLayout(self.frame_2) + self.gridLayout_8.setContentsMargins(0, 0, 0, 0) + self.gridLayout_8.setSpacing(0) + self.gridLayout_8.setObjectName("gridLayout_8") + self.frame_4 = QtWidgets.QFrame(self.frame_2) + self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_4.setObjectName("frame_4") + self.gridLayout_4 = QtWidgets.QGridLayout(self.frame_4) + self.gridLayout_4.setContentsMargins(0, 0, 0, 0) + self.gridLayout_4.setSpacing(0) + self.gridLayout_4.setObjectName("gridLayout_4") + self.spectral_mode_autoexposure_bt = QtWidgets.QPushButton(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_autoexposure_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_autoexposure_bt.setSizePolicy(sizePolicy) + self.spectral_mode_autoexposure_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_autoexposure_bt.setAutoDefault(False) + self.spectral_mode_autoexposure_bt.setObjectName("spectral_mode_autoexposure_bt") + self.gridLayout_4.addWidget(self.spectral_mode_autoexposure_bt, 0, 0, 1, 1) + self.autoexposure_le = QtWidgets.QLineEdit(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.autoexposure_le.sizePolicy().hasHeightForWidth()) + self.autoexposure_le.setSizePolicy(sizePolicy) + self.autoexposure_le.setMaximumSize(QtCore.QSize(200, 16777215)) + self.autoexposure_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:40pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.autoexposure_le.setObjectName("autoexposure_le") + self.gridLayout_4.addWidget(self.autoexposure_le, 0, 1, 1, 1) + self.gridLayout_8.addWidget(self.frame_4, 0, 0, 1, 1) + self.frame_6 = QtWidgets.QFrame(self.frame_2) + self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_6.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_6.setObjectName("frame_6") + self.gridLayout_2 = QtWidgets.QGridLayout(self.frame_6) + self.gridLayout_2.setContentsMargins(0, 0, 0, 0) + self.gridLayout_2.setSpacing(0) + self.gridLayout_2.setObjectName("gridLayout_2") + self.dc_timer_label = QtWidgets.QLabel(self.frame_6) + self.dc_timer_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.dc_timer_label.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.dc_timer_label.setAlignment(QtCore.Qt.AlignCenter) + self.dc_timer_label.setObjectName("dc_timer_label") + self.gridLayout_2.addWidget(self.dc_timer_label, 0, 1, 1, 1) + self.spectral_mode_dc_bt = QtWidgets.QPushButton(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_dc_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_dc_bt.setSizePolicy(sizePolicy) + self.spectral_mode_dc_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_dc_bt.setAutoDefault(False) + self.spectral_mode_dc_bt.setObjectName("spectral_mode_dc_bt") + self.gridLayout_2.addWidget(self.spectral_mode_dc_bt, 0, 0, 1, 1) + self.gridLayout_8.addWidget(self.frame_6, 1, 0, 1, 1) + self.frame_7 = QtWidgets.QFrame(self.frame_2) + self.frame_7.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_7.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_7.setObjectName("frame_7") + self.gridLayout_7 = QtWidgets.QGridLayout(self.frame_7) + self.gridLayout_7.setContentsMargins(0, 0, 0, 0) + self.gridLayout_7.setSpacing(0) + self.gridLayout_7.setObjectName("gridLayout_7") + self.spectral_mode_wb_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_wb_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_wb_bt.setSizePolicy(sizePolicy) + self.spectral_mode_wb_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_wb_bt.setAutoDefault(False) + self.spectral_mode_wb_bt.setObjectName("spectral_mode_wb_bt") + self.gridLayout_7.addWidget(self.spectral_mode_wb_bt, 0, 0, 1, 1) + self.wb_timer_label = QtWidgets.QLabel(self.frame_7) + self.wb_timer_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.wb_timer_label.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.wb_timer_label.setAlignment(QtCore.Qt.AlignCenter) + self.wb_timer_label.setObjectName("wb_timer_label") + self.gridLayout_7.addWidget(self.wb_timer_label, 0, 1, 1, 1) + self.gridLayout_8.addWidget(self.frame_7, 2, 0, 1, 1) + self.frame_5 = QtWidgets.QFrame(self.frame_2) + self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_5.setObjectName("frame_5") + self.gridLayout_5 = QtWidgets.QGridLayout(self.frame_5) + self.gridLayout_5.setContentsMargins(0, 0, 0, 0) + self.gridLayout_5.setSpacing(0) + self.gridLayout_5.setObjectName("gridLayout_5") + self.spectral_mode_record_bt = QtWidgets.QPushButton(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_record_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_record_bt.setSizePolicy(sizePolicy) + self.spectral_mode_record_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_record_bt.setAutoDefault(False) + self.spectral_mode_record_bt.setObjectName("spectral_mode_record_bt") + self.gridLayout_5.addWidget(self.spectral_mode_record_bt, 0, 0, 1, 1) + self.data_type_comboBox = QtWidgets.QComboBox(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.data_type_comboBox.sizePolicy().hasHeightForWidth()) + self.data_type_comboBox.setSizePolicy(sizePolicy) + self.data_type_comboBox.setMaximumSize(QtCore.QSize(200, 16777215)) + self.data_type_comboBox.setStyleSheet("/*按钮普通态*/\n" +"QComboBox\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}") + self.data_type_comboBox.setFrame(False) + self.data_type_comboBox.setObjectName("data_type_comboBox") + self.data_type_comboBox.addItem("") + self.data_type_comboBox.addItem("") + self.data_type_comboBox.addItem("") + self.gridLayout_5.addWidget(self.data_type_comboBox, 0, 1, 1, 1) + self.progressBar = QtWidgets.QProgressBar(self.frame_5) + self.progressBar.setProperty("value", 0) + self.progressBar.setTextVisible(False) + self.progressBar.setObjectName("progressBar") + self.gridLayout_5.addWidget(self.progressBar, 1, 0, 1, 2) + self.gridLayout_8.addWidget(self.frame_5, 3, 0, 1, 1) + self.gridLayout_6.addWidget(self.frame_2, 1, 0, 1, 1) + self.frame_3 = QtWidgets.QFrame(spectral_Window_phone) + self.frame_3.setMaximumSize(QtCore.QSize(16777215, 200)) + self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_3.setObjectName("frame_3") + self.gridLayout_10 = QtWidgets.QGridLayout(self.frame_3) + self.gridLayout_10.setContentsMargins(0, 0, 0, 0) + self.gridLayout_10.setSpacing(0) + self.gridLayout_10.setObjectName("gridLayout_10") + self.frame_9 = QtWidgets.QFrame(self.frame_3) + self.frame_9.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_9.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_9.setObjectName("frame_9") + self.gridLayout_9 = QtWidgets.QGridLayout(self.frame_9) + self.gridLayout_9.setContentsMargins(0, 0, 0, 0) + self.gridLayout_9.setSpacing(0) + self.gridLayout_9.setObjectName("gridLayout_9") + self.filename_le = QtWidgets.QLineEdit(self.frame_9) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.filename_le.sizePolicy().hasHeightForWidth()) + self.filename_le.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(61) + self.filename_le.setFont(font) + self.filename_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:61pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.filename_le.setObjectName("filename_le") + self.gridLayout_9.addWidget(self.filename_le, 0, 2, 1, 1) + self.label_2 = QtWidgets.QLabel(self.frame_9) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth()) + self.label_2.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.label_2.setFont(font) + self.label_2.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.gridLayout_9.addWidget(self.label_2, 0, 1, 1, 1) + self.file_number_label = QtWidgets.QLabel(self.frame_9) + self.file_number_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.file_number_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.file_number_label.setAlignment(QtCore.Qt.AlignCenter) + self.file_number_label.setObjectName("file_number_label") + self.gridLayout_9.addWidget(self.file_number_label, 0, 3, 1, 1) + self.frame_10 = QtWidgets.QFrame(self.frame_9) + self.frame_10.setMinimumSize(QtCore.QSize(200, 0)) + self.frame_10.setMaximumSize(QtCore.QSize(200, 16777215)) + self.frame_10.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_10.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_10.setObjectName("frame_10") + self.gridLayout_11 = QtWidgets.QGridLayout(self.frame_10) + self.gridLayout_11.setContentsMargins(0, 0, 0, 0) + self.gridLayout_11.setSpacing(0) + self.gridLayout_11.setObjectName("gridLayout_11") + self.label_3 = QtWidgets.QLabel(self.frame_10) + self.label_3.setMinimumSize(QtCore.QSize(140, 0)) + self.label_3.setMaximumSize(QtCore.QSize(110, 16777215)) + self.label_3.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.gridLayout_11.addWidget(self.label_3, 0, 0, 1, 1) + self.label_4 = QtWidgets.QLabel(self.frame_10) + self.label_4.setMinimumSize(QtCore.QSize(140, 0)) + self.label_4.setMaximumSize(QtCore.QSize(110, 16777215)) + self.label_4.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_4.setAlignment(QtCore.Qt.AlignCenter) + self.label_4.setObjectName("label_4") + self.gridLayout_11.addWidget(self.label_4, 1, 0, 1, 1) + self.spectral_number_le = QtWidgets.QLineEdit(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_number_le.sizePolicy().hasHeightForWidth()) + self.spectral_number_le.setSizePolicy(sizePolicy) + self.spectral_number_le.setMinimumSize(QtCore.QSize(60, 0)) + self.spectral_number_le.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.spectral_number_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:30pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.spectral_number_le.setObjectName("spectral_number_le") + self.gridLayout_11.addWidget(self.spectral_number_le, 1, 2, 1, 1) + self.framenumber_average_le = QtWidgets.QLineEdit(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.framenumber_average_le.sizePolicy().hasHeightForWidth()) + self.framenumber_average_le.setSizePolicy(sizePolicy) + self.framenumber_average_le.setMinimumSize(QtCore.QSize(60, 0)) + self.framenumber_average_le.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.framenumber_average_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:30pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.framenumber_average_le.setObjectName("framenumber_average_le") + self.gridLayout_11.addWidget(self.framenumber_average_le, 0, 2, 1, 1) + self.gridLayout_9.addWidget(self.frame_10, 0, 0, 1, 1) + self.gridLayout_10.addWidget(self.frame_9, 0, 0, 1, 1) + self.frame_8 = QtWidgets.QFrame(self.frame_3) + self.frame_8.setMaximumSize(QtCore.QSize(16777215, 35)) + self.frame_8.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_8.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_8.setObjectName("frame_8") + self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_8) + self.gridLayout_3.setContentsMargins(0, 0, 0, 0) + self.gridLayout_3.setSpacing(0) + self.gridLayout_3.setObjectName("gridLayout_3") + spacerItem = QtWidgets.QSpacerItem(399, 15, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.gridLayout_3.addItem(spacerItem, 0, 0, 1, 1) + self.t_label = QtWidgets.QLabel(self.frame_8) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.t_label.sizePolicy().hasHeightForWidth()) + self.t_label.setSizePolicy(sizePolicy) + self.t_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.t_label.setAlignment(QtCore.Qt.AlignCenter) + self.t_label.setObjectName("t_label") + self.gridLayout_3.addWidget(self.t_label, 0, 1, 1, 1) + self.hum_label = QtWidgets.QLabel(self.frame_8) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.hum_label.sizePolicy().hasHeightForWidth()) + self.hum_label.setSizePolicy(sizePolicy) + self.hum_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.hum_label.setAlignment(QtCore.Qt.AlignCenter) + self.hum_label.setObjectName("hum_label") + self.gridLayout_3.addWidget(self.hum_label, 0, 2, 1, 1) + self.camera_status_label = QtWidgets.QLabel(self.frame_8) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.camera_status_label.sizePolicy().hasHeightForWidth()) + self.camera_status_label.setSizePolicy(sizePolicy) + self.camera_status_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.camera_status_label.setAlignment(QtCore.Qt.AlignCenter) + self.camera_status_label.setObjectName("camera_status_label") + self.gridLayout_3.addWidget(self.camera_status_label, 0, 3, 1, 1) + self.gridLayout_10.addWidget(self.frame_8, 1, 0, 1, 1) + self.gridLayout_6.addWidget(self.frame_3, 2, 0, 1, 1) + + self.retranslateUi(spectral_Window_phone) + QtCore.QMetaObject.connectSlotsByName(spectral_Window_phone) + + def retranslateUi(self, spectral_Window_phone): + _translate = QtCore.QCoreApplication.translate + spectral_Window_phone.setWindowTitle(_translate("spectral_Window_phone", "光谱窗口")) + self.spectral_mode_autoexposure_bt.setText(_translate("spectral_Window_phone", "曝 光")) + self.dc_timer_label.setText(_translate("spectral_Window_phone", "计时")) + self.spectral_mode_dc_bt.setText(_translate("spectral_Window_phone", "暗 电 流")) + self.spectral_mode_wb_bt.setText(_translate("spectral_Window_phone", "白 板")) + self.wb_timer_label.setText(_translate("spectral_Window_phone", "计时")) + self.spectral_mode_record_bt.setText(_translate("spectral_Window_phone", "采 集")) + self.data_type_comboBox.setCurrentText(_translate("spectral_Window_phone", "Ref")) + self.data_type_comboBox.setItemText(0, _translate("spectral_Window_phone", "Ref")) + self.data_type_comboBox.setItemText(1, _translate("spectral_Window_phone", "DN")) + self.data_type_comboBox.setItemText(2, _translate("spectral_Window_phone", "Rad")) + self.label_2.setText(_translate("spectral_Window_phone", "文 件")) + self.file_number_label.setText(_translate("spectral_Window_phone", "文件号")) + self.label_3.setText(_translate("spectral_Window_phone", "自动平均")) + self.label_4.setText(_translate("spectral_Window_phone", "连续测量")) + self.t_label.setText(_translate("spectral_Window_phone", "温度:无数据")) + self.hum_label.setText(_translate("spectral_Window_phone", "湿度:无数据")) + self.camera_status_label.setText(_translate("spectral_Window_phone", "光谱仪:连接失败")) diff --git a/record_system_v26/ui/spectral_Window_phone.ui b/record_system_v26/ui/spectral_Window_phone.ui new file mode 100644 index 0000000..7962cf0 --- /dev/null +++ b/record_system_v26/ui/spectral_Window_phone.ui @@ -0,0 +1,1057 @@ + + + spectral_Window_phone + + + + 0 + 0 + 540 + 1175 + + + + 光谱窗口 + + + + + + + 0 + 0 + + + + + 0 + 600 + + + + + 16777215 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 600 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 曝 光 + + + false + + + + + + + + 0 + 0 + + + + + 200 + 16777215 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:40pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 200 + 16777215 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 计时 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 暗 电 流 + + + false + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 白 板 + + + false + + + + + + + + 200 + 16777215 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 计时 + + + Qt::AlignCenter + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 采 集 + + + false + + + + + + + + 0 + 0 + + + + + 200 + 16777215 + + + + /*按钮普通态*/ +QComboBox +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + + + Ref + + + false + + + + Ref + + + + + DN + + + + + Rad + + + + + + + + 0 + + + false + + + + + + + + + + + + + + 16777215 + 200 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + Microsoft Yahei + 61 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:61pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + + + + + + 0 + 0 + + + + + Microsoft Yahei + 25 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文 件 + + + Qt::AlignCenter + + + + + + + + 200 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文件号 + + + Qt::AlignCenter + + + + + + + + 200 + 0 + + + + + 200 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 140 + 0 + + + + + 110 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 自动平均 + + + Qt::AlignCenter + + + + + + + + 140 + 0 + + + + + 110 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 连续测量 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:30pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:30pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + + + + + + + + + + + + 16777215 + 35 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 399 + 15 + + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 温度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 湿度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 光谱仪:连接失败 + + + Qt::AlignCenter + + + + + + + + + + + + + + diff --git a/record_system_v27/2record_system_v27.py b/record_system_v27/2record_system_v27.py new file mode 100644 index 0000000..1e115e6 --- /dev/null +++ b/record_system_v27/2record_system_v27.py @@ -0,0 +1,2304 @@ +# -*- coding:utf-8 -*- + +''' +在2record system_v2.2的基础上更新: +1、影像模式中不采集白板,直接将白板和目标物采集到一起,输出rad影像,转反射率通过envi进行 +2、 +3、 +4、 +5、 +6、 +7、 +''' + +# 内置包 +import os, sys, functools, re, shutil, traceback, time +import subprocess +import datetime # 几种Python执行时间的计算方法:https://blog.csdn.net/wangshuang1631/article/details/54286551 +import logging + +# 三方包 +import numpy as np +from ximea import xiapi +import serial +import serial.tools.list_ports +from serial.serialutil import SerialBase, SerialException + +# 界面包 +from PyQt5.QtCore import Qt, QObject, QThreadPool, QTimer, QRegExp, pyqtSignal +# from PyQt5.QtCore import QRectF, pyqtSignal, QRunnable, pyqtSlot, QT_VERSION_STR +from PyQt5.QtGui import QIntValidator, QRegExpValidator, QPixmap, QImage, QPainterPath +from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, qApp, QDialog, QFileDialog, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem + +import matplotlib +matplotlib.use("Qt5Agg") # 声明使用QT5 +from library.matplotlib_display_image_spectral import MatplotlibSpectralViewer, MatplotlibImageViewer + + +# 自己写的包 +from QtImageViewer import QtImageViewer +from QtSpectralViewer import QtSpectralViewer +from library.multithread import Worker +from library.image_reader_writer import ImageReaderWriter +from library.functions import get_path, get_resource_path, return_file_path +from library.message_box import MessageBox +from library.config import ConfigFile +from library.log import Log + +# Qtdesigner所画界面 +from record_system_v27.ui.enter_window import * +from record_system_v27.ui.image_Window_phone import * +from record_system_v27.ui.spectral_Window_phone import * + + +# 主窗口 +class EnterWindow(QMainWindow, Ui_enter_Window): + def __init__(self, camera, parent=None): + super(EnterWindow, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + + self.image_mode_phone_bt.clicked.connect(self.image_window) + + self.spectral_mode_bt.clicked.connect(self.spectral_window) + + # self.setEnabled(False) # 先设置本窗口不可用,当打开相机成功后,才设置为可用 + + system_setting.camera_status_signal.connect(self.test_imager_status) + + def image_window(self): + self.image_window_phone_instance = ImageWindowPhone() + self.image_window_phone_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + self.image_window_phone_instance.show() + + def spectral_window(self): + self.spectral_window_instance = SpectralWindow() + print(id(self.spectral_window_instance)) + self.spectral_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + self.spectral_window_instance.show() + + def test_imager_status(self, imager_status): + if imager_status == 1000: # 相机打开成功 + self.camstatus_label.setText('相机打开成功!') + + # 如果相机打开成功,界面中label颜色设置为绿色 + self.change_lable_background_color('green') + + self.setEnabled(True) # 如果相机打开成功,则窗口可用 + elif imager_status == 1001: + self.camstatus_label.setText('相机打开时出现不是ximea错误的未知错误!') + + # 如果相机打开成功,界面中label颜色设置为绿色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 1: + self.camstatus_label.setText('相机已经断开连接!请重新打开软件尝试连接相机!') + + # 如果相机打开失败,界面中label颜色设置为红色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 12: + pass + elif imager_status == 41: + pass + elif imager_status == 56: + self.camstatus_label.setText('没有检测到光谱仪!') + + # 如果相机打开失败,界面中label颜色设置为红色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 57: + self.camstatus_label.setText('相机被占用,请关机重启!') + + # 如果相机打开失败,界面中label颜色设置为红色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 103: + pass + + def change_lable_background_color(self, color): + pattern = re.compile('background-color:rgb[(](.*)[)]') + old_style_sheet = self.camstatus_label.styleSheet() + + if color == 'red': # 如果相机打开失败,界面中label颜色设置为红色 + new_style_sheet = re.sub(pattern, r'background-color:rgb(255 , 0 , 0)', old_style_sheet) + self.camstatus_label.setStyleSheet(new_style_sheet) + elif color == 'green': # 如果相机打开成功,界面中label颜色设置为绿色 + new_style_sheet = re.sub(pattern, r'background-color:rgb(0 , 255 , 0)', old_style_sheet) + self.camstatus_label.setStyleSheet(new_style_sheet) + + +class SerialPort(QObject): + # 信号必须定义为类属性,不能放在__init__方法里 + serial_signal = pyqtSignal(object) # 建立信号,用于发射获取的温湿度 + + def __init__(self): + super(SerialPort, self).__init__() + + # 建立进程池:https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 获取log温度日志的文件夹 + self.config_file_object = ConfigFile() + + # log + self.logger = logging.getLogger('root.serial') + + if not os.path.exists(self.config_file_object.log_dir + '//temperature.log'): + with open(self.config_file_object.log_dir + '//temperature.log', 'w') as f: + pass + + formatter1 = logging.Formatter('%(asctime)s %(message)s') + temperature_file_handler = logging.FileHandler(self.config_file_object.log_dir + '//temperature.log') # 输出到文件 + temperature_file_handler.setLevel(logging.DEBUG) + temperature_file_handler.setFormatter(formatter1) + + self.logger.addHandler(temperature_file_handler) + + self.connect_number = 0 # 记录打开串口的次数 + self.serial_port = self.open_serial_port() + + self.timer = QTimer() + self.timer.timeout.connect(self.receiver_data_from_port) + # self.timer.start(1000) + + self.receiver_data_from_port_wraper() + + def open_serial_port(self): + self.connect_number += 1 + port_list = list(serial.tools.list_ports.comports()) # 列出所有可用串口 + # print(port_list) + + if len(port_list) > 0: # 如果可用串口 >0 个 + # 打印出所有串口的信息 + for i in range(0, len(port_list)): + print(port_list[i]) + + # 打开第一个串口 + ser = serial.Serial(port_list[0].device) + # print('温湿度传感器打开成功!') + return ser + elif len(port_list) == 0: # 如果可用串口为0个 + if self.connect_number == 1: + self.logger.info('无可用串口,温湿度传感器不可用!') + else: + self.logger.error('串口连接上之后,断开连接!') + return 1 # 如果返回1,则代表没有可用串口;通过1来判断不执行定时器触发:self.timer.start(1000) + else: # 其他没有考虑到的情况 + return 1 + + def receiver_data_from_port_wraper(self): + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(self.receiver_data_from_port) + + self.threadpool.start(worker) + + def receiver_data_from_port(self): + ''' + 定时器QTimer没隔1s调用此函数一次 → 让串口buffer有足够的数据等待读取 + :return: 无返回值 + + 本函数功能:1、串口中接收字节数据,有两种帧 → 代表两种数据 + 2、判断帧头位置和本帧数据类型 + 3、判断帧尾 → 等效判断本帧数据是否完全 + 4、如果数据帧完整 → 解析数据,将温度湿度显示到界面上和写入到文件中 + ''' + while True: + try: + if self.serial_port.in_waiting: # 如果串口buffer有数据等待读取 + bytes_receive = self.serial_port.read(self.serial_port.inWaiting()) # 读取串口buffer的数据 + # print(len(bytes_receive)) + + # 判断帧头位置,通过正则表达式 + hex_receive = bytes_receive.hex() # 一个字节需要一个两位16进制数表示,所以:len(hex_receive) = len(bytes_receive) * 2 + p = re.compile('5a5a*') + index_head = [i.start() / 2 for i in re.finditer(p, hex_receive)] # re.finditer() + # print(hex_receive) + # print(index_head) + except SerialException: # 程序打开时,温湿度传感器的串口工作正常;如果程序运行中拔掉串口就会出现此异常 + self.logger.error('在程序运行中温湿度传感器的串口出现问题!') + + # 再次尝试打开串口 + self.serial_port = self.open_serial_port() + if not isinstance(self.serial_port, int): + self.logger.info('再次尝试连接温湿度传感器成功!') + else: + self.logger.info('再次尝试连接温湿度传感器失败!') + except AttributeError: # int object has no attribute: in_waiting + self.timer.stop() + # self.logger.info('停止定时触发器!') + except Exception as e: # 未出现过的异常。当第一次出现时,需要编写代码处理,先写入日志文件(log) + self.logger.critical('未知错误!') + else: # 当没有捕获到异常时,代表串口数据获取成功 → 执行数据解析 + # 解析数据 + try: + if len(index_head) != 0: + Lux = 1.0 + T = 1.0 + P = 1.0 + Hum = 1.0 + H = 1.0 + Lux_full = 0 # 判断光照帧的数据是否完整。0:不完整;1:完整; + T_full = 0 # 判断温度帧的数据是否完整。0:不完整;1:完整; + try: + for i in index_head: # 循环遍历每个帧头 + if bytes_receive[int(i) + 2] == 21: # 0x15=21,判断帧头类型 + if sum(bytes_receive[int(i):int(i) + 8]) & 0xff == bytes_receive[int(i) + 8]: # 判断帧尾是否正确 + # print('光照帧的帧尾正确!') + + Lux_full = 1 # 如果帧尾,此帧数据数完整的 + Lux = ((bytes_receive[int(i) + 4] << 24) | (bytes_receive[int(i) + 5] << 16) | ( + bytes_receive[int(i) + 6] << 8) | bytes_receive[int(i) + 7]) / 100 + if bytes_receive[int(i) + 2] == 69: # 0x45=69,判断帧头类型 + if sum(bytes_receive[int(i):int(i) + 14]) & 0xff == bytes_receive[int(i) + 14]: # 判断帧尾是否正确 + # print('温度帧的帧尾正确!') + + T_full = 1 # 当执行这段代码时,代表帧头帧尾都正常,此帧数据数完整的 + T = ((bytes_receive[int(i) + 4] << 8) | bytes_receive[int(i) + 5]) / 100 + P = ((bytes_receive[int(i) + 6] << 24) | (bytes_receive[int(i) + 7] << 16) | ( + bytes_receive[int(i) + 8] << 8) | bytes_receive[ + int(i) + 9]) / 100 + Hum = ((bytes_receive[int(i) + 10] << 8) | bytes_receive[int(i) + 11]) / 100 + H = ((bytes_receive[int(i) + 12] << 8) | bytes_receive[int(i) + 13]) / 100 + except IndexError as e: # 当出现帧头,但是帧头到帧尾的数据不全 → 在判断帧尾是否正确时就会出现索引越界 + # print('----------------------索引越界!') + pass + except Exception: # 当出现前面没有解决的异常时,前面的异常捕捉就失效。最后通过异常基类来捕捉 → 代表需要修改代码进行处理的新异常 + # print('---------------------------------没遇见过的异常') + pass + + # 将数据显示和写入文件 + if Lux_full + T_full == 2: # x + y == 2代表温度帧和光照帧都完整 + # self.t_label.setVisible(True) + # self.hum_label.setVisible(True) + # self.t_label.setText('温度:' + str(T)) + # self.hum_label.setText('湿度:' + str(Hum)) + + # print('发送数据') + + self.serial_signal.emit((str(T), str(Hum))) + self.logger.debug('%s %s %s', str(T), str(Hum), str(camera.get_temp())) # 将温湿度记录进log文件中 + + # print('光照强度:%f' % Lux) + # print('温度:%f' % T) + # print('气压:%f' % P) + # print('湿度:%f' % Hum) + # print('海拔:%f' % H) + # print() + elif Lux_full + T_full == 1: + # print('只有一个数据帧是完整的。(光照帧或者温度帧)') + # print() + pass + except UnboundLocalError: + # print(2222222222222222222222222222222) + # traceback.print_exc() + pass + except Exception: + self.logger.critical('未知错误!') + finally: # 不管有没有捕获到异常都会执行,一般用作资源回收 + pass + + time.sleep(3) + + +# 图像窗口 +class ImageWindowPhone(QDialog, Ui_image_Window_phone): + # 信号必须定义为类属性,不能放在__init__方法里 + arcus_status_signal = pyqtSignal(int) # arcus信号:0→马达未连接;1→马达连接成功; + plot_signal = pyqtSignal() # 采集影像时,边采集边刷新显示 + + def __init__(self, parent=None): + ''' + The super().__init__() method invokes the base class constructor from the MyForm class, + that is, the constructor of the QDialog class is invoked from MyForm class to indicate that + QDialog is displayed through this class iss a top-level window. + ''' + super(ImageWindowPhone, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + self.setWindowModality(Qt.ApplicationModal) # 阻塞此窗口:此行代码必须放在show()函数之前 + + # 配置文件读取和写入类,配置文件读写和界面分离 + # 1、采集数据需要的帧率、曝光、帧数、文件名等等都由此类从文件中读取 + # 2、并保存在此类中 + self.config_file_object = ConfigFile() + + # 数据采集保存类,采集数据并将数据保存在此类中,数据采集和界面分离 + self.image_camera_operation = CameraOperation(self.config_file_object) + + # 当配置文件读取完成后,就第一时间根据读取的配置文件设置相机曝光、帧率和gain + self.image_camera_operation.set_exposure_gain_framerate(camera) + self.initiate_arcus_speed() # 初始化arcus速度 + + # log + self.logger = logging.getLogger('root.image_phone') + + if not os.path.exists(self.config_file_object.log_dir + '//image_operate.log'): + with open(self.config_file_object.log_dir + '//image_operate.log', 'w') as f: + pass + + image_operate_file_handler = logging.FileHandler(self.config_file_object.log_dir + "//image_operate.log") # 输出到文件 + image_operate_file_handler.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + image_operate_file_handler.setFormatter(formatter) + + stream_handler = logging.StreamHandler() # 输出到控制台 + stream_handler.setLevel(logging.DEBUG) + stream_handler.setFormatter(formatter) + self.logger.addHandler(image_operate_file_handler) + self.logger.addHandler(stream_handler) + + # 在窗口中显示串口接收的温度/湿度 + serial_port.serial_signal.connect(self.update_temperature) + + # 采集影像时,边采集边刷新显示 + self.plot_signal.connect(self.plotimg) + + # 建立进程池:https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 初始化窗口中的值 + self.framenumber_le.setText(str(self.config_file_object.frame_number)) + self.framerate_le.setText(str(self.config_file_object.framerate)) + self.exposure_time_le.setText(str(self.config_file_object.exposure_time)) + self.arcus_speed_le.setText(str(self.config_file_object.arcus_speed)) + self.filename_le.setText(self.config_file_object.default_image_name) + + # 显示影像和调焦 + # self.myImageFigure = MatplotlibImageViewer() + self.myImageFigure = QtImageViewer() + self.myImageFigure.leftMouseButtonPressed.connect(self.handle_left_click) + self.image_glo.addWidget(self.myImageFigure) + + # self.myFocusFigure = MatplotlibSpectralViewer(xlabel='Wavelength (nm)') + self.myFocusFigure = QtSpectralViewer() + self.focus_glo.addWidget(self.myFocusFigure) + + # 操作光谱仪 + self.state = 0 # 光谱仪操作状态:曝光=1;暗电流=3;→ 所以只有state==4时才能开始采集影像 + self.focus_count = 1 # 用于调焦按钮点击计数,取2的余数;当余数为1是执行调焦,当余数为0时停止调焦 + self.record_count = 1 # 用于采集按钮点击计数,取2的余数;当余数为1是执行采集,当余数为0时停止采集;这是为了使用通过一个按钮控制开始采集和停止采集 + + self.image_mode_exposureTime_bt.clicked.connect(self.run) + self.image_mode_focus_bt.clicked.connect(self.run) # 停止调焦操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.image_mode_dc_bt.clicked.connect(self.run) + self.image_mode_record_bt.clicked.connect(self.run) # 停止采集操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.save_bt.clicked.connect(self.run) + + # 手动改变窗口中的值,然后将值写入camera_operation类对应的变量中 + self.exposure_time_le.setValidator(QIntValidator()) # QIntValidator是一个类 + self.framerate_le.setValidator(QIntValidator()) + self.framenumber_le.setValidator(QIntValidator()) + + my_regex = QRegExp("[a-zA-Z0-9]*") + my_validator = QRegExpValidator(my_regex, self.filename_le) + self.filename_le.setValidator(my_validator) + + self.exposure_time_le.editingFinished.connect(self.text_edited) + # self.exposure_time_le.setPlaceholderText('曝光时间') + self.framerate_le.editingFinished.connect(self.text_edited) + self.framenumber_le.editingFinished.connect(self.text_edited) + self.filename_le.editingFinished.connect(self.text_edited) + + # 马达相关操作 + self.arcus_left_bt.pressed.connect(self.leftMove) + self.arcus_left_bt.released.connect(self.stop) + self.arcus_right_bt.pressed.connect(self.rightMove) + self.arcus_right_bt.released.connect(self.stop) + + # self.arcus_speed_le.setText(self.arc.write('HSPD')) + self.arcus_speed_le.editingFinished.connect(self.text_edited) + self.arcus_speed_le.setValidator(QIntValidator()) + + self.time = time.time() # 控制arcus两次命令发送的时间间隔 + self.time_interval = 1 + + self.plot_frame_count_multiple = 1 # 用于边采集边在页面中刷新,用于确定该显示多少帧了;如何确定该显示多少帧:self.plot_frame_count_multiple * 帧率 + + system_setting.camera_status_signal.connect(self.response_to_imager_status) + + # 检测arcus马达的连接情况 + self.timer = QTimer(self) # 使用这个定时器,会造成界面卡顿 + self.timer.timeout.connect(self.test_arcus_status) + # self.timer.start(5000) + + self.test_arcus_status_wraper() + self.arcus_status_signal.connect(self.response_to_arcus_status) + + # 1)决定采集DN/red;2)反转马达 + self.rad_dn_comboBox.currentIndexChanged.connect(self.change_rad_dn) + self.arcus_direction_bt.clicked.connect(self.change_arcus_direction) + + def change_rad_dn(self): + if self.rad_dn_comboBox.currentText() == 'rad': + self.image_camera_operation.record_rad_bool = True + elif self.rad_dn_comboBox.currentText() == 'dn': + self.image_camera_operation.record_rad_bool = False + + def change_arcus_direction(self): + if self.image_camera_operation.arcus_reverse_while_record == False: + self.image_camera_operation.arcus_reverse_while_record = True + self.change_widget_background_color(self.arcus_direction_bt, 'red') + elif self.image_camera_operation.arcus_reverse_while_record == True: + self.image_camera_operation.arcus_reverse_while_record = False + self.change_widget_background_color(self.arcus_direction_bt, 'gray') + + def test_arcus_status_wraper(self): + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(self.test_arcus_status) + + self.threadpool.start(worker) + + def test_arcus_status(self): + while True: + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' DN' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=2) + if 'Arcus device connected' in output.decode('utf-8'): + self.arcus_status_signal.emit(1) + elif 'No arcus devices' in output.decode('utf-8'): + self.arcus_status_signal.emit(0) + except subprocess.TimeoutExpired: + process.kill() + output2, error2 = process.communicate() + if 'Arcus device connected' in output2.decode('utf-8'): + self.arcus_status_signal.emit(1) + elif 'No arcus devices' in output2.decode('utf-8'): + self.arcus_status_signal.emit(0) + + time.sleep(4) # 本线程沉睡3秒 + + def response_to_arcus_status(self, arcus_status): + if arcus_status == 0: + self.arcus_status_label.setText('马达:连接失败!') + self.change_widget_background_color(self.arcus_status_label, 'red') + elif arcus_status == 1: + self.arcus_status_label.setText('马达:连接正常!') + self.change_widget_background_color(self.arcus_status_label, 'green') + + def response_to_imager_status(self, imager_status): + if imager_status == 1000: # 相机打开成功 + # print('相机打开成功!') + + try: + temperature = camera.get_temp() + except Exception: + temperature = None + + self.camera_status_label.setText('光谱仪:' + str(temperature)) + + self.change_widget_background_color(self.camera_status_label, 'green') + elif imager_status == 1001: + print('相机打开时出现不是ximea错误的未知错误!') + elif imager_status == 1: + # print('相机已经断开连接!请重新打开软件尝试连接相机!') + + self.camera_status_label.setText('光谱仪:断开连接') + self.change_widget_background_color(self.camera_status_label, 'red') + + self.setEnabled(False) + self.close() + elif imager_status == 12: + pass + elif imager_status == 41: + pass + elif imager_status == 56: + print('没有检测到光谱仪!') + elif imager_status == 103: + pass + + def leftMove(self): + time_now = time.time() + if time_now - self.time > self.time_interval: + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J-' + python2_command = r'python2.exe ' + get_resource_path('./data/ArcusDevice.py') + ' CLR EO=1 J-' + + try: + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=2) + + # test_arcus_status函数不停的执行命令(DN),检测马达连接情况;当在检测的同时执行移动马达命令,就会出现:Cannot connect Arcus device + while 'Cannot connect Arcus device' in output.decode('utf-8'): + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=2) + except subprocess.TimeoutExpired: + process.kill() + + print('左移出错output', output) + print('左移出错error', error) + + def rightMove(self): + time_now = time.time() + if time_now - self.time > self.time_interval: + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J+' + python2_command = r'python2.exe ' + get_resource_path('./data/ArcusDevice.py') + ' CLR EO=1 J+' + + try: + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=2) + + # test_arcus_status函数不停的执行命令(DN),检测马达连接情况;当在检测的同时执行移动马达命令,就会出现:Cannot connect Arcus device + while 'Cannot connect Arcus device' in output.decode('utf-8'): + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=2) + except subprocess.TimeoutExpired: + process.kill() + + print('右移出错output', output) + print('右移出错error', error) + + def stop(self): + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py STOP' + python2_command = r'python2.exe ' + get_resource_path('./data/ArcusDevice.py') + ' STOP' + + try: + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=2) + + # test_arcus_status函数不停的执行命令(DN),检测马达连接情况;当在检测的同时执行移动马达命令,就会出现:Cannot connect Arcus device + while 'Cannot connect Arcus device' in output.decode('utf-8'): + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=2) + except subprocess.TimeoutExpired: + process.kill() + + print('停止出错output', output) + print('停止出错error', error) + + def handle_left_click(self, x, y): + # 画出光谱 + try: + row = int(y) + column = int(x) + # print("Pixel (row=" + str(row) + ", column=" + str(column) + ")") + + _, _, img = ImageReaderWriter.read_img('corning410_test', column, row, 1, 1) + + if isinstance(img, np.ndarray): # 如果点击到图像之外,img就是NoneType,就不重画光谱 + # print('点击有效') + + self.myFocusFigure.plot_wrap(self.image_camera_operation.wave(model='array'), img[:, 0, 0]) + except TypeError: + pass + # print('有错') + # self.logger.critical('TypeError:', exc_info=True) + except Exception: + self.logger.critical('点击显示光谱时出现未知错误:', exc_info=True) + traceback.print_exc() + + # 手动修改界面中的值后,为相机重新设置如下参数:exposure, gain, framerate + def text_edited(self): + try: + # 将改变值1)保存到配置文件对象,供程序运行使用2)写入到配置文件,供程序下次打开读取 + self.config_file_object.image_signal.emit( + {'exposure_time': int(self.exposure_time_le.text()), + 'framerate': int(self.framerate_le.text()), 'frame_number': int(self.framenumber_le.text()), + 'default_image_name': self.filename_le.text(), 'arcus_speed': self.arcus_speed_le.text()}) + except ValueError: + self.x = MessageBox('请输入正确的值!') + self.x.exec() + except Exception: + self.logger.critical('设置曝光/gain/帧率/帧数时出现未知错误!', exe_info=True) + + if self.sender().objectName() == 'exposure_time_le': + self.state = 1 # 手动改变曝光时间后,强制让用户重新采集暗电流+白板 + + print('exposure_time_le改变') + self.image_camera_operation.set_exposure_gain_framerate(camera) + + if self.sender().objectName() == 'framerate_le': + self.state = 0 # 改变帧率后,需要重新曝光 + + print('framerate_le改变') + self.image_camera_operation.set_exposure_gain_framerate(camera) + + if self.sender().objectName() == 'framenumber_le': + self.image_camera_operation.create_rgb() + + if self.sender().objectName() == 'arcus_speed_le': + time_now = time.time() + if time_now - self.time > self.time_interval: + self.time = time.time() + + python2_command = r'python2.exe ' + get_resource_path('./data/ArcusDevice.py') + ' HSPD=' + str(self.arcus_speed_le.text()) + + try: + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=1) + + # test_arcus_status函数不停的执行命令(DN),检测马达连接情况;当在检测的同时执行移动马达命令,就会出现:Cannot connect Arcus device + while 'Cannot connect Arcus device' in output.decode('utf-8'): + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + + print('改变arcus速度出错output', output) + print('改变arcus速度出错error', error) + + def initiate_arcus_speed(self): + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' HSPD=' + str(self.config_file_object.arcus_speed) + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + # print(output) + # print(error) + print('初始化速度ok!') + + def update_temperature(self, data): + try: + self.t_label.setText('温度:' + data[0]) + self.hum_label.setText('湿度:' + data[1]) + + self.change_widget_background_color(self.t_label, 'green') + self.change_widget_background_color(self.hum_label, 'green') + except: + print('有问题') + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + self.t_label.setText('温度:无数据') + self.hum_label.setText('湿度:无数据') + + def timer_start(self): + ''' + 本函数目的是在self.timer.start(1000)外包裹一层(有点装饰器的感觉),加入判断: + 1、如果self.serial_port为串口类型,就触发定时器self.timer.start(1000) + 2、如果self.serial_port == 1(为int类型),则代表硬件中没有温湿度传感器,就没必要触发定时器self.timer.start(1000) + :return: 无返回值 + ''' + + if isinstance(self.serial_port, serial.serialwin32.Serial): + self.timer.start(1000) + elif isinstance(self.serial_port, int): + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + else: + pass + + def plotimg(self): + try: + if self.qt_sender == 'image_mode_record_bt': + frame_number_to_plot = self.plot_frame_count_multiple * self.config_file_object.framerate + + self.framenumber_recorded_label.setText(str(frame_number_to_plot)) + + img = np.dstack((self.image_camera_operation.rgb[2, 0:frame_number_to_plot, :], self.image_camera_operation.rgb[1, 0:frame_number_to_plot, :], + self.image_camera_operation.rgb[0, 0:frame_number_to_plot, :])) + + self.myImageFigure.setImage(img) + + self.plot_frame_count_multiple += 1 + elif self.qt_sender == 'image_mode_focus_bt': + self.myImageFigure.setImage(self.image_camera_operation.image_container) + + n = int(self.image_camera_operation.image_container.shape[0] / 2) + self.myFocusFigure.plot_wrap(self.image_camera_operation.image_container[n, :]) + + # worker = Worker(self.myImageFigure.setImage, self.image_camera_operation.image_container) + # self.threadpool.start(worker) + except: + self.logger.critical('未知错误--界面中绘制影像和光谱时!\n%s', exc_info=True) + + # 调焦、采集暗电流、采集白板、采集影像 都通过此函数 + def run(self): + try: + self.qt_sender = self.sender().objectName() + + if self.qt_sender == 'image_mode_focus_bt': + if self.focus_count % 2 == 1: + self.image_mode_focus_bt.setText('停止调焦') + self.core_operation() + self.focus_count += 1 + + self.change_widget_background_color(self.image_mode_focus_bt, 'red') + elif self.focus_count % 2 == 0: # 停止调焦操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.image_camera_operation.focus = False + self.image_mode_focus_bt.setText('调焦') + self.focus_count += 1 + elif self.qt_sender == 'image_mode_exposureTime_bt': + self.state = 1 + + self.core_operation() + + self.change_widget_background_color(self.image_mode_exposureTime_bt, 'red') + elif self.qt_sender == 'image_mode_dc_bt': + if self.state == 0: + self.x = MessageBox('请先曝光!') + self.x.exec() + elif self.state == 1 or self.state == 4: # 正常采集暗电流 + self.x = MessageBox('请先确认镜头盖已安装!') + self.x.exec() + + self.state = 4 + + self.core_operation() + + self.change_widget_background_color(self.image_mode_dc_bt, 'red') + elif self.qt_sender == 'image_mode_record_bt': + if self.record_count % 2 == 1: + if self.state == 0: + self.x = MessageBox('请先曝光!') + self.x.exec() + elif self.state == 1: # + self.x = MessageBox('请采集暗电流!') + self.x.exec() + elif self.state == 4: # 正常采集影像,采集DN/反射率的判断 放在CameraOperation类中 + self.record_count += 1 + self.plot_frame_count_multiple = 1 # 每次点击采集按钮都将此变量设置为1,用于正常边采集影像边在界面中显示影像 + + self.image_mode_record_bt.setText('停止采集') + + self.core_operation() + + self.change_widget_background_color(self.image_mode_record_bt, 'red') + elif self.record_count % 2 == 0: # 停止采集操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.image_camera_operation.record = False + self.image_mode_record_bt.setText('采集') + elif self.qt_sender == 'save_bt': + worker = Worker(self.savedata) + + worker.signals.error.connect(self.operate_failed) + worker.signals.finished.connect(self.operate_success) + + self.threadpool.start(worker) + + self.change_widget_background_color(self.save_bt, 'red') + except Exception: + traceback.print_exc() + + # 改变按钮三态中普通态的背景颜色 + def change_widget_background_color(self, qt_widget, color): + pattern = re.compile('background-color(.*)(normal\*/)') + old_style_sheet = qt_widget.styleSheet() + + if color == 'red': + new_style_sheet = re.sub(pattern, r'background-color:rgb(255 , 0 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'green': + new_style_sheet = re.sub(pattern, r'background-color:rgb(0 , 255 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'gray': + new_style_sheet = re.sub(pattern, r'background-color:rgb(225 , 225 , 225);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + + def core_operation(self): + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(self.image_camera_operation.start_AcquireData, camera, self.qt_sender, self.plot_signal) + + worker.signals.error.connect(self.operate_failed) + worker.signals.finished.connect(self.operate_success) + if self.qt_sender == 'image_mode_exposureTime_bt': + ''' + 曝光参数的设置过程: + (1)曝光参数返回到界面中的QLineEdit; + (2)通过QLineEdit的textChanged事件将值写入到camera_operation对应的变量; + (3)为相机设置参数:1)通过worker的finished信号【本程序使用】2)也可以通过QLineEdit的textChanged事件调用self.set_exposure函数,为相机设置参数 + 这种过程的好处是界面显示的曝光参数和实际设置的是同步的 + ''' + worker.signals.result.connect(self.post_auto_expose) + + self.threadpool.start(worker) + + self.disable_bt(True) + + def disable_bt(self, bool): + # 两个if判断存在的原因:调焦/停止调焦(采集/停止采集)使用同一个按钮,所以不能将其设置为不可用 + if self.qt_sender !='image_mode_focus_bt': + self.image_mode_focus_bt.setDisabled(bool) + if self.qt_sender != 'image_mode_record_bt': + self.image_mode_record_bt.setDisabled(bool) + + if bool == False: # 操作完成后设置为可用 + self.image_mode_record_bt.setDisabled(bool) + self.image_mode_focus_bt.setDisabled(bool) + + self.image_mode_exposureTime_bt.setDisabled(bool) + self.image_mode_dc_bt.setDisabled(bool) + self.save_bt.setDisabled(bool) + self.arcus_left_bt.setDisabled(bool) + self.arcus_right_bt.setDisabled(bool) + + self.exposure_time_le.setDisabled(bool) + self.framerate_le.setDisabled(bool) + self.arcus_speed_le.setDisabled(bool) + self.framenumber_le.setDisabled(bool) + self.filename_le.setDisabled(bool) + + self.rad_dn_comboBox.setDisabled(bool) + self.arcus_direction_bt.setDisabled(bool) + + def operate_failed(self, traceback_info): + if traceback_info[0] == xiapi.Xi_error: + if traceback_info[1].status == 1: # 在ximea的API中代表"Invalid handle":相机断开连接 + if self.qt_sender == 'image_mode_exposureTime_bt': + self.logger.error('自动曝光失败:相机断开连接!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_focus_bt': + self.logger.error('调焦失败:相机断开连接!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_dc_bt': + self.logger.error('采集暗电流失败:相机断开连接!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_record_bt': + self.logger.error('采集影像失败:相机断开连接!\n%s', traceback_info[2]) + elif traceback_info[1].status == 56: # 在ximea的API中代表"No Devices Found":在执行cam.open_device()时,无相机打开 + if self.qt_sender == 'image_mode_exposureTime_bt': + self.logger.error('自动曝光失败:无相机可供打开!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_focus_bt': + self.logger.error('调焦失败:无相机可供打开!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_dc_bt': + self.logger.error('采集暗电流失败:无相机可供打开\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_record_bt': + self.logger.error('采集影像失败:无相机可供打开\n%s', traceback_info[2]) + elif traceback_info[1].status == 12: # 在ximea的API中代表"Not supported":当相机正在采集数据时,执行代码cam.set_imgdataformat('XI_RAW16') + pass + elif traceback_info[1].status == 41: # 在ximea的API中代表"Acquisition already started":相机已经开始采集数据 + pass + elif traceback_info[0] == ValueError: + if self.qt_sender == 'save_bt': + self.logger.error('保存影像失败--影像名不正确!\n%s', traceback_info[2]) + + self.x = MessageBox('请输入正确的影像名!') + self.x.exec() + elif traceback_info[0] == FileNotFoundError: + if self.qt_sender == 'save_bt': + self.logger.error('保存影像失败--没有采集影像!\n%s', traceback_info[2]) + + self.x = MessageBox('请先采集影像!') + self.x.exec() + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + + print('operate_failed函数运行成功!') + + def operate_success(self): + if self.qt_sender == 'image_mode_exposureTime_bt': + self.logger.info('自动曝光成功----------------!') + + self.image_mode_exposureTime_bt.setText(re.sub('✔', '', self.image_mode_exposureTime_bt.text()) + '✔') + elif self.qt_sender == 'image_mode_focus_bt': + self.logger.info('调焦成功!') + + self.image_mode_focus_bt.setText(re.sub('✔', '', self.image_mode_focus_bt.text()) + '✔') + elif self.qt_sender == 'image_mode_dc_bt': + self.logger.info('采集暗电流成功!') + + self.image_mode_dc_bt.setText(re.sub('✔', '', self.image_mode_dc_bt.text()) + '✔') + elif self.qt_sender == 'image_mode_record_bt': + self.logger.info('采集影像成功!') + + self.image_mode_record_bt.setText('采集') + self.image_mode_record_bt.setDisabled(True) # 要等马达回到初始位置才能用 + self.record_count += 1 + + self.image_mode_record_bt.setText(re.sub('✔', '', self.image_mode_record_bt.text()) + '✔') + + self.save_bt.setText(re.sub('✔', '', self.save_bt.text())) + elif self.qt_sender == 'save_bt': + self.save_bt.setText(re.sub('✔', '', self.save_bt.text()) + '✔') + + self.image_mode_record_bt.setText(re.sub('✔', '', self.image_mode_record_bt.text())) + + self.logger.info('保存影像成功!') + + worker = Worker(self.wwww) + self.threadpool.start(worker) + + def wwww(self): + while True: + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' PX' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=2) + if 'arcus is return to initial position' in output.decode('utf-8'): + self.ssss() + + break + elif 'No arcus devices' in output.decode('utf-8'): + self.ssss() + + break + elif 'arcus is still returning' in output.decode('utf-8'): + pass + except subprocess.TimeoutExpired: + process.kill() + output2, error2 = process.communicate() + if 'Arcus device connected' in output2.decode('utf-8'): + self.ssss() + + break + elif 'No arcus devices' in output2.decode('utf-8'): + self.ssss() + + break + + def ssss(self): + self.disable_bt(False) + + # 当操作成功后,所有按钮都变为初始颜色:灰色 + self.change_widget_background_color(self.image_mode_exposureTime_bt, 'gray') + self.change_widget_background_color(self.image_mode_focus_bt, 'gray') + self.change_widget_background_color(self.image_mode_dc_bt, 'gray') + self.change_widget_background_color(self.image_mode_record_bt, 'gray') + self.change_widget_background_color(self.save_bt, 'gray') + + # 保存影像数据 + def savedata(self): + self.disable_bt(True) # 因为保存影像所需时间较多,所以需要将此行代码放在最前面 + + # 保存路径 + # filename = "%s%s%s" % (re.sub('/', '\\\\', self.config_file_object.image_dir), '\\', self.config_file_object.default_image_name) + filename, file_number = return_file_path([], self.config_file_object.image_dir, + self.config_file_object.default_image_name) + + # 保存影像和头文件 + imagefile = "%s%s%s" % (os.getcwd(), '\\', 'corning410_test') + shutil.copyfile(imagefile, filename) + shutil.copyfile("%s%s" % (imagefile, '.hdr'), "%s%s" % (filename, '.hdr')) + + self.file_number_label.setText(str(file_number)) + + # 将自动曝光返回值写入到界面中的QLineEdit和self.config对象中 + def post_auto_expose(self, result): + ''' + :param result: return cam.get_exposure(), cam.get_gain(), cls.autoexposure_feedback + :return: + ''' + try: + # 将自动曝光得到的结果显示到界面(QLineEdit) + self.exposure_time_le.setText(str(result[0])) + + # 为了防止后面的信号执行延迟;如果延迟,设置曝光时间就会设置为self.config.exposure_time的旧值 + self.config_file_object.exposure_time = result[0] + self.config_file_object.gain = result[1] + + try: + # 将自动曝光值保存到配置文件中 + self.config_file_object.image_signal.emit({'exposure_time': result[0], 'gain': result[1]}) + except: + traceback.print_exc() + + + self.image_camera_operation.set_exposure_gain_framerate(camera) + + if result[2] == 1: + self.x = MessageBox('光线不足,曝光时间已设置为最大!') + self.x.exec() + self.image_camera_operation.autoexposure_feedback = 0 + except: + traceback.print_exc() + + def closeEvent(self, a0: QtGui.QCloseEvent): + camera.stop_acquisition() + + +# 光谱窗口 +class SpectralWindow(QDialog, Ui_spectral_Window_phone): + # 信号必须定义为类属性,不能放在__init__方法里 + progress_bar_and_plot_spectral_signal = pyqtSignal(int) + + def __init__(self, parent=None): + super(SpectralWindow, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + self.setWindowModality(Qt.ApplicationModal) # 阻塞此窗口:此行代码必须放在show()函数之前 + + # 数据采集保存类,采集数据并将数据保存在此类中,数据采集和界面分离 + + # 配置文件读取和写入类,配置文件读写和界面分离 + # 1、采集数据需要的帧率、曝光、帧数、文件名等等都由此类从文件中读取 + # 2、并保存在此类中 + self.config_file_object = ConfigFile() + + self.spectral_camera_operation = SpectralCameraOperation(self.config_file_object) + + self.progress_bar_and_plot_spectral_signal.connect(self.plot_save_spectral) + + self.state = 0 # 光谱仪操作状态:曝光=1;暗电流=3;白板=5 → 所以只有state==9时才能开始采集光谱 + self.dc_time = time.time() # 用于暗电流计时(从采集成功后那一刻开始) + self.dc_timer = QTimer(self) + self.dc_timer.timeout.connect(self.dc_timer_slot) + + self.wb_time = time.time() # 用于暗电流计时(从采集成功后那一刻开始) + self.wb_timer = QTimer(self) + self.wb_timer.timeout.connect(self.wb_timer_slot) + + self.progressBar.setMaximum(self.config_file_object.spectral_number) + self.progressBar.setValue(0) + + # log + self.logger = logging.getLogger('root.spectral') + + if not os.path.exists(self.config_file_object.log_dir + '//spectral_operate.log'): + with open(self.config_file_object.log_dir + '//spectral_operate.log', 'w') as f: + pass + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + spectral_operate_file_handler = logging.FileHandler(self.config_file_object.log_dir + "//spectral_operate.log") # 输出到文件 + spectral_operate_file_handler.setLevel(logging.INFO) + spectral_operate_file_handler.setFormatter(formatter) + self.logger.addHandler(spectral_operate_file_handler) + + # 在窗口中显示串口接收的温度/湿度 + serial_port.serial_signal.connect(self.update_temperature) + + # 建立进程池 + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 初始化值 + self.filename_le.setText(self.config_file_object.default_spectral_name) + self.spectral_number_le.setText(str(self.config_file_object.spectral_number)) + self.framenumber_average_le.setText(str(self.config_file_object.framenumber_average)) + self.autoexposure_le.setText(str(self.config_file_object.exposure_time_spectral)) + + # 显示光谱和align + # self.spectralFigure = MatplotlibSpectralViewer(xlabel='Wavelength (nm)', ylabel='reflectance') + self.spectralFigure = QtSpectralViewer(ylabel_and_range='reflectance') + self.spe_glo.addWidget(self.spectralFigure) + + #操作光谱仪 + # self.dc_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.wb_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + # self.record_bt.clicked.connect(functools.partial(spectral_camera_operation.start_AcquireData, camera)) + self.spectral_mode_autoexposure_bt.clicked.connect(self.run) + self.spectral_mode_wb_bt.clicked.connect(self.run) # 曝光 + 采集白板 + self.spectral_mode_dc_bt.clicked.connect(self.run) + self.spectral_mode_record_bt.clicked.connect(self.run) + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + self.filename_le.editingFinished.connect(self.onchange) + my_regex1 = QRegExp("[a-zA-Z0-9]*") + my_validator1 = QRegExpValidator(my_regex1, self.filename_le) + self.filename_le.setValidator(my_validator1) + + self.autoexposure_le.editingFinished.connect(self.onchange) + my_regex2 = QRegExp("[0-9]*") + my_validator2 = QRegExpValidator(my_regex2, self.autoexposure_le) + self.autoexposure_le.setValidator(my_validator2) + + self.spectral_number_le.editingFinished.connect(self.onchange) + self.framenumber_average_le.editingFinished.connect(self.onchange) + my_regex3 = QRegExp("[0-9]*") + my_validator3 = QRegExpValidator(my_regex2, self.autoexposure_le) + self.spectral_number_le.setValidator(my_validator2) + self.framenumber_average_le.setValidator(my_validator2) + + system_setting.camera_status_signal.connect(self.test_imager_status) + + self.hpi_temperature = None + + def test_imager_status(self, imager_status): + if imager_status == 1000: # 相机打开成功 + # print('相机打开成功!') + + try: + temperature = camera.get_temp() + except Exception: + temperature = None + + self.camera_status_label.setText('光谱仪:' + str(temperature)) + self.change_widget_background_color(self.camera_status_label, 'green') + elif imager_status == 1001: + print('相机打开时出现不是ximea错误的未知错误!') + elif imager_status == 1: + # print('相机已经断开连接!请重新打开软件尝试连接相机!') + + self.camera_status_label.setText('光谱仪:断开连接') + self.change_widget_background_color(self.camera_status_label, 'red') + + self.setEnabled(False) + self.close() + elif imager_status == 12: + pass + elif imager_status == 41: + pass + elif imager_status == 56: + print('没有检测到光谱仪!') + elif imager_status == 103: + pass + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + def onchange(self): + try: + if self.sender().objectName() == 'autoexposure_le': + self.state = 1 # 手动改变曝光时间后,需要强制让用户重新采集暗电流和白板 + + exposure_time_tmp = int(self.autoexposure_le.text()) + + self.config_file_object.spectral_signal.emit({'exposure_time_spectral': exposure_time_tmp}) + + camera.set_exposure(exposure_time_tmp) # 曝光时间单位为微秒,1s共有1000000微秒 + # camera.set_gain(int(float(self.config_file_object.gain))) # int('0.0')会报错,int(float('0.0'))不会报错 + + self.logger.info('手动改变曝光时间!') + elif self.sender().objectName() == 'framenumber_average_le': + framenumber_average_tmp = int(self.framenumber_average_le.text()) + + self.config_file_object.spectral_signal.emit({'framenumber_average': framenumber_average_tmp}) + + self.spectral_camera_operation.create_image_container(framenumber_average_tmp) + + self.logger.info('手动改变每条光谱的平均帧数!') + elif self.sender().objectName() == 'spectral_number_le': + spectral_number_tmp = int(self.spectral_number_le.text()) + + self.config_file_object.spectral_signal.emit({'spectral_number': spectral_number_tmp}) + + self.progressBar.setMaximum(spectral_number_tmp) + self.progressBar.setValue(0) + + self.spectral_camera_operation.create_spectral_container(spectral_number_tmp) + + self.logger.info('手动改变保存的光谱数!') + elif self.sender().objectName() == 'filename_le': + filename = self.filename_le.text() + + if filename != '': + self.config_file_object.spectral_signal.emit({'default_spectral_name': filename}) + + self.logger.info('改变光谱文件名!') + except: + traceback.print_exc() + + def plot_save_spectral(self, x): + try: + self.progressBar.setValue(x) + + # 画出光谱 + if self.data_type_comboBox.currentText() == 'DN': + self.spectralFigure.plot_wrap(self.spectral_camera_operation.spectral_dn[:, 0], self.spectral_camera_operation.spectral_dn[:, x]) + if self.data_type_comboBox.currentText() == 'Rad': + self.spectralFigure.plot_wrap(self.spectral_camera_operation.spectral_dn[:, 0], self.spectral_camera_operation.spectral_rad[:, x]) + if self.data_type_comboBox.currentText() == 'Ref': + self.spectralFigure.plot_wrap(self.spectral_camera_operation.spectral_dn[:, 0], self.spectral_camera_operation.spectral_ref[:, x]) + + # 保存光谱 + filename_dn, file_number_dn = return_file_path([], self.config_file_object.spectral_dir, + self.config_file_object.default_spectral_name + '_dn', model='spectral') + filename_rad, file_number_rad = return_file_path([], self.config_file_object.spectral_dir, + self.config_file_object.default_spectral_name + '_rad', model='spectral') + filename_ref, file_number_ref = return_file_path([], self.config_file_object.spectral_dir, + self.config_file_object.default_spectral_name + '_ref', model='spectral') + # print(filename_ref) + + header_dn = self.get_spectral_metadata('DN') + header_rad = self.get_spectral_metadata('RAD') + header_ref = self.get_spectral_metadata('REF') + + np.savetxt(filename_dn, self.spectral_camera_operation.spectral_dn[:, [0, x]], fmt='%f', header=header_dn) + np.savetxt(filename_rad, self.spectral_camera_operation.spectral_rad[:, [0, x]], fmt='%f', header=header_rad) + np.savetxt(filename_ref, self.spectral_camera_operation.spectral_ref[:, [0, x]], fmt='%f', header=header_ref) + + self.file_number_label.setText(str(file_number_dn)) + except: + traceback.print_exc() + + def get_spectral_metadata(self, data_type_str): + + record_time = "%s%s" % ('RecordTime = ', str(datetime.datetime.now())) + SN = 'SN = 0001' + exposure_time = "%s%s" % ('ExposureTime = ', str(camera.get_exposure())) + data_type = "%s%s" % ('DataType = ', data_type_str) + sensor_temperature = "%s%s" % ('sensor_temperature = ', str(camera.get_temp())) + hpi_temperature = "%s%s" % ('hpi_temperature = ', str(self.hpi_temperature)) + + header = '%s%s%s%s%s%s%s%s%s%s%s' % ( + record_time, '\n', SN, '\n', exposure_time, '\n', data_type, '\n', sensor_temperature, '\n', hpi_temperature) + return header + + def update_temperature(self, data): + try: + self.hpi_temperature = data[0] + + self.t_label.setText('温度:' + data[0]) + self.hum_label.setText('湿度:' + data[1]) + + self.change_widget_background_color(self.t_label, 'green') + self.change_widget_background_color(self.hum_label, 'green') + except: + traceback.print_exc() + print('有问题') + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + self.t_label.setText('温度:无数据') + self.hum_label.setText('湿度:无数据') + + def dc_timer_slot(self): + now = time.time() + x = now - self.dc_time + self.dc_timer_label.setText(str(int(x)) + 's') + + def wb_timer_slot(self): + now = time.time() + x = now - self.wb_time + self.wb_timer_label.setText(str(int(x)) + 's') + + def run(self): + self.qt_sender = self.sender().objectName() + + # 操作状态显示 + if self.qt_sender == 'spectral_mode_autoexposure_bt': + print('SpectralWindow采集曝光') + + self.logger.info('曝光...') + + self.state = 1 + + self.core_operation() + + self.change_widget_background_color(self.spectral_mode_autoexposure_bt, 'red') + elif self.qt_sender == 'spectral_mode_dc_bt': + try: + if self.state == 0: + self.x = MessageBox('请先曝光!') + self.x.exec() + elif self.state == 1 or self.state == 4 or self.state == 9: + self.x = MessageBox('请先确认光纤盖已安装!') + self.x.exec() + + self.logger.info('采集暗电流...') + self.state = 4 + + # 暗电流计时 + self.dc_time = time.time() + self.dc_timer.start(2000) + + self.core_operation() + + self.change_widget_background_color(self.spectral_mode_dc_bt, 'red') + except: + traceback.print_exc() + elif self.qt_sender == 'spectral_mode_wb_bt': + if self.state == 0: + self.x = MessageBox('请先曝光+暗电流!') + self.x.exec() + elif self.state == 1: + self.x = MessageBox('请先采集暗电流!') + self.x.exec() + elif self.state == 4 or self.state == 9: + self.logger.info('采集白板...') + self.state = 9 + + # 白板计时 + self.wb_time = time.time() + self.wb_timer.start(2000) + + self.core_operation() + + self.change_widget_background_color(self.spectral_mode_wb_bt, 'red') + elif self.qt_sender == 'spectral_mode_record_bt': + if self.state == 0: + self.x = MessageBox('请先曝光+暗电流+白板') + self.x.exec() + elif self.state == 1: + self.x = MessageBox('请先暗电流+白板') + self.x.exec() + elif self.state == 4: + self.x = MessageBox('请先白板') + self.x.exec() + elif self.state == 9: + self.logger.info('采集光谱...') + + self.core_operation() + + self.change_widget_background_color(self.spectral_mode_record_bt, 'red') + + # 改变按钮三态中普通态的背景颜色 + def change_widget_background_color(self, qt_widget, color): + pattern = re.compile('background-color(.*)(normal\*/)') + old_style_sheet = qt_widget.styleSheet() + + if color == 'red': + new_style_sheet = re.sub(pattern, r'background-color:rgb(255 , 0 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'green': + new_style_sheet = re.sub(pattern, r'background-color:rgb(0 , 255 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'gray': + new_style_sheet = re.sub(pattern, r'background-color:rgb(225 , 225 , 225);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + + # 将自动曝光返回值写入到界面中的QLineEdit和self.config_file_object对象中 + def post_auto_expose(self, result): + ''' + :param result: return cam.get_exposure(), cam.get_gain(), cls.autoexposure_feedback + :return: + ''' + + # 将自动曝光得到的结果显示到界面(QLineEdit) + self.autoexposure_le.setText(str(result[0])) + + # # 为了防止后面的信号执行延迟;如果延迟,设置曝光时间就会设置为self.config_file_object.exposure_time的旧值 + # self.config_file_object.exposure_time = result[0] + # self.config_file_object.gain = result[1] + + def core_operation(self): + worker = Worker(self.spectral_camera_operation.start_AcquireData, camera, self.qt_sender, + self.progress_bar_and_plot_spectral_signal) + worker.signals.finished.connect(self.operate_success) + worker.signals.error.connect(self.operate_failed) + + if self.qt_sender == 'spectral_mode_autoexposure_bt': + ''' + 曝光参数的设置过程: + (1)曝光参数返回到界面中的QLineEdit; + (2)通过QLineEdit的textChanged事件将值写入到camera_operation对应的变量; + (3)为相机设置参数:1)通过worker的finished信号【本程序使用】2)也可以通过QLineEdit的textChanged事件调用self.set_exposure函数,为相机设置参数 + 这种过程的好处是界面显示的曝光参数和实际设置的是同步的 + ''' + worker.signals.result.connect(self.post_auto_expose) + + self.threadpool.start(worker) + + self.disable_bt_le(True) + + def operate_failed(self, traceback_info): + if traceback_info[0] == xiapi.Xi_error: + if self.qt_sender == 'spectral_mode_wb_bt': + self.logger.error('曝光/白板失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_align_bt': + self.logger.error('align 失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_dc_bt': + self.logger.error('采集暗电流失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif self.qt_sender == 'spectral_mode_record_bt': + self.logger.error('采集光谱失败:光谱仪正在工作中,请稍等!\n%s', traceback_info[2]) + elif traceback_info[0] == ValueError: + if self.qt_sender == 'spectral_mode_record_bt': + self.logger.error('保存光谱失败!\n%s', traceback_info[2]) + + self.x = MessageBox('请输入正确的光谱名!') + self.x.exec() + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + + def operate_success(self): + # 操作状态显示 + if self.qt_sender == 'spectral_mode_autoexposure_bt': + self.logger.info('曝光成功!') + elif self.qt_sender == 'spectral_mode_dc_bt': + self.logger.info('采集暗电流成功!') + elif self.qt_sender == 'spectral_mode_wb_bt': + self.logger.info('采集白板成功!') + elif self.qt_sender == 'spectral_mode_align_bt': + self.logger.info('align successfully!') + elif self.qt_sender == 'spectral_mode_record_bt': + self.logger.info('采集光谱成功!') + + self.disable_bt_le(False) + + # 当操作成功后,所有按钮都变为初始颜色:灰色 + self.change_widget_background_color(self.spectral_mode_autoexposure_bt, 'gray') + self.change_widget_background_color(self.spectral_mode_dc_bt, 'gray') + self.change_widget_background_color(self.spectral_mode_wb_bt, 'gray') + self.change_widget_background_color(self.spectral_mode_record_bt, 'gray') + + def disable_bt_le(self, bool): + self.spectral_mode_autoexposure_bt.setDisabled(bool) + self.spectral_mode_dc_bt.setDisabled(bool) + self.spectral_mode_wb_bt.setDisabled(bool) + self.spectral_mode_record_bt.setDisabled(bool) + + self.spectral_number_le.setDisabled(bool) + self.framenumber_average_le.setDisabled(bool) + self.autoexposure_le.setDisabled(bool) + self.filename_le.setDisabled(bool) + + def closeEvent(self, a0: QtGui.QCloseEvent): + camera.stop_acquisition() + + +# 影像模式类:相关的函数和变量 +class CameraOperation(object): + def __init__(self, config_file_object): + self.config_file_object = config_file_object + + # 转辐亮度 + self.rad_or_not = False + if self.config_file_object.binning == 1: + self.img_gain = get_resource_path('./data/lens_bin1_gain_SN0073') + self.cal_it = 7289 + elif self.config_file_object.binning == 2: + self.img_gain = get_resource_path('./data/lens_bin2_gain_SN0073') + self.cal_it = 1654 + _, _, self.gain = ImageReaderWriter.read_img(self.img_gain) + + self.gain = self.gain.astype(np.float32) + self.target_it = None + self.gain_scale = None + + # + self.arcus_reverse_while_record = False + self.record_rad_bool = True # True → 采集rad影像,False → 采集dn影像 + + # 开始采集数据 + self.image_dc = None # 此变量用于存储采集到的暗电流影像 + self.focus = True # 用于停止调焦 + self.record = True # 用于停止采集 + self.img_datatype = 2 # 在头文件中确定影像数据类型:Integer(np.int16) → A 16-bit signed integer ranging from -32,768 to +32,767. + + self.autoexposure_feedback = 0 # 指示:自动曝光所得到的shutter值是否为最大;如果为最大→值设置为1 + + # 创建rgb数据,用于在界面中显示 + self.create_rgb() + + def create_rgb(self): + self.rgb = np.ones((3, int(self.config_file_object.frame_number), self.config_file_object.end_column - self.config_file_object.start_column)) + + # 手动改变界面上的曝光值和gain值后,设置相机的曝光值和gain值所用 + def set_exposure_gain_framerate(self, cam): + # settings,cam.set_param("exposure",10000) + cam.set_framerate(self.config_file_object.framerate) + cam.set_exposure(self.config_file_object.exposure_time) # 曝光时间单位为微秒,1s共有1000000微秒 + cam.set_gain(self.config_file_object.gain) #int('0.0')会报错,int(float('0.0'))不会报错 + + def start_AcquireData(self, cam, qt_sender, plot_signal=None): # qt_sender是指qt窗口中事件的发生者 + ''' + :param cam: 实例化的相机句柄 + :param qt_sender: 调用本方法时,点击的界面上的按钮名; + :param plot_signal: + :return: + ''' + # 创建img = xiapi.Image()前需要设置一系列img参数,例如:格式、位深度、 + # 如果格式设置为XI_RAW8,image_raw_numpy.dtype -> dtype('uint8'), uint8 + # 如果格式设置为XI_RAW16,image_raw_numpy.dtype -> dtype('= 4090: + cam.set_exposure(int(0.9 * cam.get_exposure())) + + cam.start_acquisition() + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + image_raw_numpy = img.get_image_data_numpy() + + # 当关闭调焦后,再次打开调焦功能需要将cls.focus的值从False变为True + if not self.focus: + self.focus = True + + cam.start_acquisition() + + while self.focus: + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + self.image_container = image_raw_numpy[ + self.config_file_object.start_row:self.config_file_object.end_row, + self.config_file_object.start_column:self.config_file_object.end_column] + + if plot_signal is not None: + plot_signal.emit() + + # 调焦完成之后,将相机的曝光和帧率设置为配置文件中的值 + self.set_exposure_gain_framerate(cam) + + if qt_sender == 'image_mode_exposureTime_bt': + print('start_AcquireData--自动曝光运行开始') + + # 设置自动曝光的CCD--roi + cam.set_framerate(self.config_file_object.framerate) + cam.set_aeag_roi_offset_x(self.config_file_object.start_column) + cam.set_aeag_roi_offset_y(self.config_file_object.start_row) + cam.set_aeag_roi_height(self.config_file_object.end_row - self.config_file_object.start_row) + cam.set_aeag_roi_width(self.config_file_object.end_column - self.config_file_object.start_column) + # cam.set_exp_priority(1) # Exposure priority (0.8 - exposure 80%, gain 20%).XI_PRM_EXP_PRIORITY + # cam.set_ae_max_limit(24000) # Maximum time (us) used for exposure in AEAG procedureXI_PRM_AE_MAX_LIMIT + # cam.set_ag_max_limit(12) + # cam.set_aeag_level(50) # Average intensity of output signal AEAG should achieve(in %)XI_PRM_AEAG_LEVEL + # 还有两个不知怎么用的参数:XI_PRM_GAIN_SELECTOR or "gain_selector"和XI_PRM_SHUTTER_TYPE or "shutter_type" + + # 使用相机自动曝光功能得到初始曝光值 + cam.enable_aeag() # 开启自动曝光 + cam.start_acquisition() + for i in range(10): + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + cam.disable_aeag() # 关闭自动曝光 + + # 根据自动曝光所得初始曝光值,循环迭代获取不过曝的曝光值 + image_raw_numpy = img.get_image_data_numpy() + while image_raw_numpy.max() >= 2730: + cam.set_exposure(int(0.9 * cam.get_exposure())) + + cam.start_acquisition() + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + image_raw_numpy = img.get_image_data_numpy() + + # 如果因为光线不足曝光值达到了最大,就将曝光反馈变量设置为1 + if cam.get_exposure() > int(1 / self.config_file_object.framerate * 10**6): + cam.set_exposure(int(1 / self.config_file_object.framerate * 10**6)) + self.autoexposure_feedback = 1 + else: + cam.set_exposure(cam.get_exposure()) + + # 计算gain + self.target_it = cam.get_exposure() + self.gain_scale = self.cal_it / self.target_it + self.gain = self.gain * self.gain_scale + + print('start_AcquireData--自动曝光运行结束') + + # 如果点击“暗电流”按钮,采集并保存暗电流影像到image_dc + if qt_sender == 'image_mode_dc_bt': + framenumber = 10 + image_container = np.empty(( + self.config_file_object.end_row - self.config_file_object.start_row, framenumber, + self.config_file_object.end_column - self.config_file_object.start_column)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[ + self.config_file_object.start_row:self.config_file_object.end_row, + self.config_file_object.start_column:self.config_file_object.end_column] + + image_container = image_container.mean(axis=1) + + self.image_dc = image_container + + # 如果点击“采集”按钮,自动去除暗电流,并且转化成反射率 + if qt_sender == 'image_mode_record_bt': + frameCount = 1 # 统计采集的帧数,用于停止采集使用 + + # 当停止采集后,再次开始采集需要将cls.record的值从False变为True + if not self.record: + self.record = True + + # 启动马达 + self.arcus_start() + + # 开始采集数据 并且 将数据写入到硬盘中 + cam.start_acquisition() + with open('corning410_test', 'wb') as f: + + print('Starting data acquisition...') + startTime = datetime.datetime.now() + + while self.record: + cam.get_image(img) # get data and pass them from camera to img + # image_raw_numpy.dtype -> dtype(' + + enter_Window + + + true + + + + 0 + 0 + 651 + 474 + + + + 主窗口 + + + + + + + true + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:30pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + + + 正在打开相机... + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0); + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 光谱模式 + + + + + + + true + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0); + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 影像模式 + + + + + + + + + 0 + 0 + 651 + 23 + + + + + + + wew e + + + + + + diff --git a/record_system_v27/ui/image_Window_phone - 副本 (2).ui b/record_system_v27/ui/image_Window_phone - 副本 (2).ui new file mode 100644 index 0000000..ac44ed4 --- /dev/null +++ b/record_system_v27/ui/image_Window_phone - 副本 (2).ui @@ -0,0 +1,1358 @@ + + + image_Window_phone + + + true + + + + 0 + 0 + 531 + 1174 + + + + false + + + 影像窗口 + + + false + + + false + + + false + + + + + + Qt::Vertical + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 16777215 + 600 + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 600 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 曝 光 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 调 焦 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 暗 电 流 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 采 集 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 保 存 + + + false + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + 140 + 0 + + + + + 200 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文件号 + + + Qt::AlignCenter + + + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 命 名 + + + Qt::AlignCenter + + + + + + + + + + + + + 110 + 0 + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 积分时间 + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + + + 0 + 0 + + + + + 160 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 马 达 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + < + + + false + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + > + + + false + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + rad + + + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 数 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 反转 + + + + + + + + + + + + + 110 + 0 + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 率 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + false + + + + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 233 + 12 + + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 温度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 湿度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 光谱仪:连接失败 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 马达:连接失败! + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/record_system_v27/ui/image_Window_phone.py b/record_system_v27/ui/image_Window_phone.py new file mode 100644 index 0000000..1b04e4e --- /dev/null +++ b/record_system_v27/ui/image_Window_phone.py @@ -0,0 +1,868 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'image_Window_phone.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_image_Window_phone(object): + def setupUi(self, image_Window_phone): + image_Window_phone.setObjectName("image_Window_phone") + image_Window_phone.setEnabled(True) + image_Window_phone.resize(562, 1174) + image_Window_phone.setMouseTracking(False) + image_Window_phone.setAutoFillBackground(False) + image_Window_phone.setSizeGripEnabled(False) + image_Window_phone.setModal(False) + self.gridLayout_6 = QtWidgets.QGridLayout(image_Window_phone) + self.gridLayout_6.setObjectName("gridLayout_6") + self.frame_3 = QtWidgets.QFrame(image_Window_phone) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_3.sizePolicy().hasHeightForWidth()) + self.frame_3.setSizePolicy(sizePolicy) + self.frame_3.setMaximumSize(QtCore.QSize(16777215, 600)) + self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_3.setObjectName("frame_3") + self.gridLayout_5 = QtWidgets.QGridLayout(self.frame_3) + self.gridLayout_5.setContentsMargins(0, 0, 0, 0) + self.gridLayout_5.setObjectName("gridLayout_5") + self.frame_7 = QtWidgets.QFrame(self.frame_3) + self.frame_7.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_7.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_7.setObjectName("frame_7") + self.gridLayout_4 = QtWidgets.QGridLayout(self.frame_7) + self.gridLayout_4.setContentsMargins(0, 0, 0, 0) + self.gridLayout_4.setObjectName("gridLayout_4") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.image_mode_focus_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_focus_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_focus_bt.setSizePolicy(sizePolicy) + self.image_mode_focus_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_focus_bt.setFont(font) + self.image_mode_focus_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_focus_bt.setAutoDefault(False) + self.image_mode_focus_bt.setObjectName("image_mode_focus_bt") + self.verticalLayout.addWidget(self.image_mode_focus_bt) + self.image_mode_exposureTime_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_exposureTime_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_exposureTime_bt.setSizePolicy(sizePolicy) + self.image_mode_exposureTime_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_exposureTime_bt.setFont(font) + self.image_mode_exposureTime_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_exposureTime_bt.setAutoDefault(False) + self.image_mode_exposureTime_bt.setObjectName("image_mode_exposureTime_bt") + self.verticalLayout.addWidget(self.image_mode_exposureTime_bt) + self.image_mode_dc_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_dc_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_dc_bt.setSizePolicy(sizePolicy) + self.image_mode_dc_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_dc_bt.setFont(font) + self.image_mode_dc_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_dc_bt.setAutoDefault(False) + self.image_mode_dc_bt.setObjectName("image_mode_dc_bt") + self.verticalLayout.addWidget(self.image_mode_dc_bt) + self.image_mode_record_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_record_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_record_bt.setSizePolicy(sizePolicy) + self.image_mode_record_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_record_bt.setFont(font) + self.image_mode_record_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_record_bt.setAutoDefault(False) + self.image_mode_record_bt.setObjectName("image_mode_record_bt") + self.verticalLayout.addWidget(self.image_mode_record_bt) + self.save_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.save_bt.sizePolicy().hasHeightForWidth()) + self.save_bt.setSizePolicy(sizePolicy) + self.save_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.save_bt.setFont(font) + self.save_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.save_bt.setAutoDefault(False) + self.save_bt.setObjectName("save_bt") + self.verticalLayout.addWidget(self.save_bt) + self.gridLayout_4.addLayout(self.verticalLayout, 0, 0, 1, 1) + self.gridLayout_5.addWidget(self.frame_7, 0, 0, 1, 1) + self.frame_6 = QtWidgets.QFrame(self.frame_3) + self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_6.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_6.setObjectName("frame_6") + self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_6) + self.gridLayout_3.setContentsMargins(0, 0, 0, 0) + self.gridLayout_3.setObjectName("gridLayout_3") + self.frame_10 = QtWidgets.QFrame(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_10.sizePolicy().hasHeightForWidth()) + self.frame_10.setSizePolicy(sizePolicy) + self.frame_10.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_10.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_10.setObjectName("frame_10") + self.gridLayout_8 = QtWidgets.QGridLayout(self.frame_10) + self.gridLayout_8.setContentsMargins(0, 0, 0, 0) + self.gridLayout_8.setSpacing(0) + self.gridLayout_8.setObjectName("gridLayout_8") + self.rad_dn_comboBox = QtWidgets.QComboBox(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.rad_dn_comboBox.sizePolicy().hasHeightForWidth()) + self.rad_dn_comboBox.setSizePolicy(sizePolicy) + self.rad_dn_comboBox.setMinimumSize(QtCore.QSize(90, 0)) + self.rad_dn_comboBox.setStyleSheet("/*按钮普通态*/\n" +"QComboBox\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}") + self.rad_dn_comboBox.setObjectName("rad_dn_comboBox") + self.rad_dn_comboBox.addItem("") + self.rad_dn_comboBox.addItem("") + self.gridLayout_8.addWidget(self.rad_dn_comboBox, 0, 2, 1, 1) + self.framenumber_le = QtWidgets.QLineEdit(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.framenumber_le.sizePolicy().hasHeightForWidth()) + self.framenumber_le.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setPointSize(42) + self.framenumber_le.setFont(font) + self.framenumber_le.setObjectName("framenumber_le") + self.gridLayout_8.addWidget(self.framenumber_le, 0, 1, 1, 1) + self.arcus_direction_bt = QtWidgets.QPushButton(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_direction_bt.sizePolicy().hasHeightForWidth()) + self.arcus_direction_bt.setSizePolicy(sizePolicy) + self.arcus_direction_bt.setMinimumSize(QtCore.QSize(90, 0)) + self.arcus_direction_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.arcus_direction_bt.setFont(font) + self.arcus_direction_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.arcus_direction_bt.setAutoDefault(False) + self.arcus_direction_bt.setObjectName("arcus_direction_bt") + self.gridLayout_8.addWidget(self.arcus_direction_bt, 0, 3, 1, 1) + self.label_2 = QtWidgets.QLabel(self.frame_10) + self.label_2.setMinimumSize(QtCore.QSize(110, 0)) + self.label_2.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.gridLayout_8.addWidget(self.label_2, 0, 0, 1, 1) + self.gridLayout_3.addWidget(self.frame_10, 4, 0, 1, 1) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.label_3 = QtWidgets.QLabel(self.frame_6) + self.label_3.setMinimumSize(QtCore.QSize(110, 0)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(20) + self.label_3.setFont(font) + self.label_3.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.horizontalLayout_3.addWidget(self.label_3) + self.framerate_le = QtWidgets.QLineEdit(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.framerate_le.sizePolicy().hasHeightForWidth()) + self.framerate_le.setSizePolicy(sizePolicy) + self.framerate_le.setMaximumSize(QtCore.QSize(16777215, 106)) + font = QtGui.QFont() + font.setPointSize(42) + self.framerate_le.setFont(font) + self.framerate_le.setReadOnly(False) + self.framerate_le.setObjectName("framerate_le") + self.horizontalLayout_3.addWidget(self.framerate_le) + self.framenumber_recorded_label = QtWidgets.QLabel(self.frame_6) + self.framenumber_recorded_label.setMinimumSize(QtCore.QSize(180, 0)) + self.framenumber_recorded_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.framenumber_recorded_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.framenumber_recorded_label.setAlignment(QtCore.Qt.AlignCenter) + self.framenumber_recorded_label.setObjectName("framenumber_recorded_label") + self.horizontalLayout_3.addWidget(self.framenumber_recorded_label) + self.gridLayout_3.addLayout(self.horizontalLayout_3, 1, 0, 1, 1) + self.frame_9 = QtWidgets.QFrame(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_9.sizePolicy().hasHeightForWidth()) + self.frame_9.setSizePolicy(sizePolicy) + self.frame_9.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_9.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_9.setLineWidth(0) + self.frame_9.setObjectName("frame_9") + self.gridLayout_7 = QtWidgets.QGridLayout(self.frame_9) + self.gridLayout_7.setContentsMargins(0, 0, 0, 0) + self.gridLayout_7.setSpacing(0) + self.gridLayout_7.setObjectName("gridLayout_7") + self.filename_le = QtWidgets.QLineEdit(self.frame_9) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.filename_le.sizePolicy().hasHeightForWidth()) + self.filename_le.setSizePolicy(sizePolicy) + self.filename_le.setMaximumSize(QtCore.QSize(16777215, 106)) + font = QtGui.QFont() + font.setPointSize(42) + self.filename_le.setFont(font) + self.filename_le.setObjectName("filename_le") + self.gridLayout_7.addWidget(self.filename_le, 0, 1, 1, 1) + self.label_6 = QtWidgets.QLabel(self.frame_9) + self.label_6.setMinimumSize(QtCore.QSize(110, 0)) + self.label_6.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_6.setAlignment(QtCore.Qt.AlignCenter) + self.label_6.setObjectName("label_6") + self.gridLayout_7.addWidget(self.label_6, 0, 0, 1, 1) + self.file_number_label = QtWidgets.QLabel(self.frame_9) + self.file_number_label.setMinimumSize(QtCore.QSize(180, 0)) + self.file_number_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.file_number_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.file_number_label.setAlignment(QtCore.Qt.AlignCenter) + self.file_number_label.setObjectName("file_number_label") + self.gridLayout_7.addWidget(self.file_number_label, 0, 2, 1, 1) + self.gridLayout_3.addWidget(self.frame_9, 6, 0, 1, 1) + self.frame_5 = QtWidgets.QFrame(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_5.sizePolicy().hasHeightForWidth()) + self.frame_5.setSizePolicy(sizePolicy) + self.frame_5.setMinimumSize(QtCore.QSize(160, 0)) + self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_5.setObjectName("frame_5") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_5) + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_7 = QtWidgets.QLabel(self.frame_5) + self.label_7.setMinimumSize(QtCore.QSize(110, 0)) + self.label_7.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_7.setAlignment(QtCore.Qt.AlignCenter) + self.label_7.setObjectName("label_7") + self.horizontalLayout_2.addWidget(self.label_7) + self.arcus_left_bt = QtWidgets.QPushButton(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_left_bt.sizePolicy().hasHeightForWidth()) + self.arcus_left_bt.setSizePolicy(sizePolicy) + self.arcus_left_bt.setMinimumSize(QtCore.QSize(50, 0)) + self.arcus_left_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.arcus_left_bt.setFont(font) + self.arcus_left_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.arcus_left_bt.setAutoDefault(False) + self.arcus_left_bt.setObjectName("arcus_left_bt") + self.horizontalLayout_2.addWidget(self.arcus_left_bt) + self.arcus_speed_le = QtWidgets.QLineEdit(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_speed_le.sizePolicy().hasHeightForWidth()) + self.arcus_speed_le.setSizePolicy(sizePolicy) + self.arcus_speed_le.setMinimumSize(QtCore.QSize(60, 0)) + self.arcus_speed_le.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setPointSize(42) + self.arcus_speed_le.setFont(font) + self.arcus_speed_le.setObjectName("arcus_speed_le") + self.horizontalLayout_2.addWidget(self.arcus_speed_le) + self.arcus_right_bt = QtWidgets.QPushButton(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_right_bt.sizePolicy().hasHeightForWidth()) + self.arcus_right_bt.setSizePolicy(sizePolicy) + self.arcus_right_bt.setMinimumSize(QtCore.QSize(50, 0)) + self.arcus_right_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.arcus_right_bt.setFont(font) + self.arcus_right_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.arcus_right_bt.setAutoDefault(False) + self.arcus_right_bt.setObjectName("arcus_right_bt") + self.horizontalLayout_2.addWidget(self.arcus_right_bt) + self.gridLayout_3.addWidget(self.frame_5, 3, 0, 1, 1) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.label_5 = QtWidgets.QLabel(self.frame_6) + self.label_5.setMinimumSize(QtCore.QSize(110, 0)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(20) + self.label_5.setFont(font) + self.label_5.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_5.setObjectName("label_5") + self.horizontalLayout_4.addWidget(self.label_5) + self.exposure_time_le = QtWidgets.QLineEdit(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.exposure_time_le.sizePolicy().hasHeightForWidth()) + self.exposure_time_le.setSizePolicy(sizePolicy) + self.exposure_time_le.setMaximumSize(QtCore.QSize(16777215, 106)) + font = QtGui.QFont() + font.setPointSize(42) + self.exposure_time_le.setFont(font) + self.exposure_time_le.setObjectName("exposure_time_le") + self.horizontalLayout_4.addWidget(self.exposure_time_le) + self.gridLayout_3.addLayout(self.horizontalLayout_4, 2, 0, 1, 1) + self.gridLayout_5.addWidget(self.frame_6, 0, 1, 1, 1) + self.gridLayout_6.addWidget(self.frame_3, 1, 0, 1, 1) + self.frame_4 = QtWidgets.QFrame(image_Window_phone) + self.frame_4.setMinimumSize(QtCore.QSize(0, 0)) + self.frame_4.setMaximumSize(QtCore.QSize(16777215, 35)) + self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_4.setObjectName("frame_4") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_4) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout.setSpacing(0) + self.horizontalLayout.setObjectName("horizontalLayout") + spacerItem = QtWidgets.QSpacerItem(233, 12, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.t_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.t_label.sizePolicy().hasHeightForWidth()) + self.t_label.setSizePolicy(sizePolicy) + self.t_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.t_label.setAlignment(QtCore.Qt.AlignCenter) + self.t_label.setObjectName("t_label") + self.horizontalLayout.addWidget(self.t_label) + self.hum_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.hum_label.sizePolicy().hasHeightForWidth()) + self.hum_label.setSizePolicy(sizePolicy) + self.hum_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.hum_label.setAlignment(QtCore.Qt.AlignCenter) + self.hum_label.setObjectName("hum_label") + self.horizontalLayout.addWidget(self.hum_label) + self.camera_status_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.camera_status_label.sizePolicy().hasHeightForWidth()) + self.camera_status_label.setSizePolicy(sizePolicy) + self.camera_status_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.camera_status_label.setAlignment(QtCore.Qt.AlignCenter) + self.camera_status_label.setObjectName("camera_status_label") + self.horizontalLayout.addWidget(self.camera_status_label) + self.arcus_status_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_status_label.sizePolicy().hasHeightForWidth()) + self.arcus_status_label.setSizePolicy(sizePolicy) + self.arcus_status_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.arcus_status_label.setAlignment(QtCore.Qt.AlignCenter) + self.arcus_status_label.setObjectName("arcus_status_label") + self.horizontalLayout.addWidget(self.arcus_status_label) + self.gridLayout_6.addWidget(self.frame_4, 2, 0, 1, 1) + self.splitter = QtWidgets.QSplitter(image_Window_phone) + self.splitter.setOrientation(QtCore.Qt.Vertical) + self.splitter.setObjectName("splitter") + self.frame_2 = QtWidgets.QFrame(self.splitter) + self.frame_2.setFrameShape(QtWidgets.QFrame.Box) + self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_2.setObjectName("frame_2") + self.gridLayout_2 = QtWidgets.QGridLayout(self.frame_2) + self.gridLayout_2.setContentsMargins(0, 0, 0, 0) + self.gridLayout_2.setObjectName("gridLayout_2") + self.image_glo = QtWidgets.QGridLayout() + self.image_glo.setObjectName("image_glo") + self.gridLayout_2.addLayout(self.image_glo, 0, 0, 1, 1) + self.frame = QtWidgets.QFrame(self.splitter) + self.frame.setMaximumSize(QtCore.QSize(16777215, 600)) + self.frame.setFrameShape(QtWidgets.QFrame.Box) + self.frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame.setObjectName("frame") + self.gridLayout = QtWidgets.QGridLayout(self.frame) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.focus_glo = QtWidgets.QGridLayout() + self.focus_glo.setObjectName("focus_glo") + self.gridLayout.addLayout(self.focus_glo, 0, 0, 1, 1) + self.gridLayout_6.addWidget(self.splitter, 0, 0, 1, 1) + + self.retranslateUi(image_Window_phone) + QtCore.QMetaObject.connectSlotsByName(image_Window_phone) + + def retranslateUi(self, image_Window_phone): + _translate = QtCore.QCoreApplication.translate + image_Window_phone.setWindowTitle(_translate("image_Window_phone", "影像窗口")) + self.image_mode_focus_bt.setText(_translate("image_Window_phone", "调 焦")) + self.image_mode_exposureTime_bt.setText(_translate("image_Window_phone", "曝 光")) + self.image_mode_dc_bt.setText(_translate("image_Window_phone", "暗 电 流")) + self.image_mode_record_bt.setText(_translate("image_Window_phone", "采 集")) + self.save_bt.setText(_translate("image_Window_phone", "保 存")) + self.rad_dn_comboBox.setItemText(0, _translate("image_Window_phone", "rad")) + self.rad_dn_comboBox.setItemText(1, _translate("image_Window_phone", "dn")) + self.arcus_direction_bt.setText(_translate("image_Window_phone", "反转")) + self.label_2.setText(_translate("image_Window_phone", "帧 数")) + self.label_3.setText(_translate("image_Window_phone", "帧 率")) + self.framenumber_recorded_label.setText(_translate("image_Window_phone", "文件号")) + self.label_6.setText(_translate("image_Window_phone", "命 名")) + self.file_number_label.setText(_translate("image_Window_phone", "文件号")) + self.label_7.setText(_translate("image_Window_phone", "马 达")) + self.arcus_left_bt.setText(_translate("image_Window_phone", "<")) + self.arcus_right_bt.setText(_translate("image_Window_phone", ">")) + self.label_5.setText(_translate("image_Window_phone", "积分时间")) + self.t_label.setText(_translate("image_Window_phone", "温度:无数据")) + self.hum_label.setText(_translate("image_Window_phone", "湿度:无数据")) + self.camera_status_label.setText(_translate("image_Window_phone", "光谱仪:连接失败")) + self.arcus_status_label.setText(_translate("image_Window_phone", "马达:连接失败!")) diff --git a/record_system_v27/ui/image_Window_phone.ui b/record_system_v27/ui/image_Window_phone.ui new file mode 100644 index 0000000..72cea97 --- /dev/null +++ b/record_system_v27/ui/image_Window_phone.ui @@ -0,0 +1,1395 @@ + + + image_Window_phone + + + true + + + + 0 + 0 + 562 + 1174 + + + + false + + + 影像窗口 + + + false + + + false + + + false + + + + + + + 0 + 0 + + + + + 16777215 + 600 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 调 焦 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 曝 光 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 暗 电 流 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 采 集 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 保 存 + + + false + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 90 + 0 + + + + /*按钮普通态*/ +QComboBox +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + + + + rad + + + + + dn + + + + + + + + + 0 + 0 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 90 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 反转 + + + false + + + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 数 + + + Qt::AlignCenter + + + + + + + + + + + + + 110 + 0 + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 率 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + false + + + + + + + + 180 + 0 + + + + + 200 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文件号 + + + Qt::AlignCenter + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 命 名 + + + Qt::AlignCenter + + + + + + + + 180 + 0 + + + + + 200 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文件号 + + + Qt::AlignCenter + + + + + + + + + + + 0 + 0 + + + + + 160 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 马 达 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + < + + + false + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + > + + + false + + + + + + + + + + + + + 110 + 0 + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 积分时间 + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 233 + 12 + + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 温度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 湿度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 光谱仪:连接失败 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 马达:连接失败! + + + Qt::AlignCenter + + + + + + + + + + Qt::Vertical + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 16777215 + 600 + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + diff --git a/record_system_v27/ui/spectral_Window_phone.py b/record_system_v27/ui/spectral_Window_phone.py new file mode 100644 index 0000000..1e6c05d --- /dev/null +++ b/record_system_v27/ui/spectral_Window_phone.py @@ -0,0 +1,629 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'spectral_Window_phone.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_spectral_Window_phone(object): + def setupUi(self, spectral_Window_phone): + spectral_Window_phone.setObjectName("spectral_Window_phone") + spectral_Window_phone.resize(540, 1175) + self.gridLayout_6 = QtWidgets.QGridLayout(spectral_Window_phone) + self.gridLayout_6.setObjectName("gridLayout_6") + self.frame = QtWidgets.QFrame(spectral_Window_phone) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth()) + self.frame.setSizePolicy(sizePolicy) + self.frame.setMinimumSize(QtCore.QSize(0, 600)) + self.frame.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame.setObjectName("frame") + self.gridLayout = QtWidgets.QGridLayout(self.frame) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.spe_glo = QtWidgets.QGridLayout() + self.spe_glo.setObjectName("spe_glo") + self.gridLayout.addLayout(self.spe_glo, 0, 0, 1, 1) + self.gridLayout_6.addWidget(self.frame, 0, 0, 1, 1) + self.frame_2 = QtWidgets.QFrame(spectral_Window_phone) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth()) + self.frame_2.setSizePolicy(sizePolicy) + self.frame_2.setMaximumSize(QtCore.QSize(16777215, 600)) + self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_2.setObjectName("frame_2") + self.gridLayout_8 = QtWidgets.QGridLayout(self.frame_2) + self.gridLayout_8.setContentsMargins(0, 0, 0, 0) + self.gridLayout_8.setSpacing(0) + self.gridLayout_8.setObjectName("gridLayout_8") + self.frame_4 = QtWidgets.QFrame(self.frame_2) + self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_4.setObjectName("frame_4") + self.gridLayout_4 = QtWidgets.QGridLayout(self.frame_4) + self.gridLayout_4.setContentsMargins(0, 0, 0, 0) + self.gridLayout_4.setSpacing(0) + self.gridLayout_4.setObjectName("gridLayout_4") + self.spectral_mode_autoexposure_bt = QtWidgets.QPushButton(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_autoexposure_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_autoexposure_bt.setSizePolicy(sizePolicy) + self.spectral_mode_autoexposure_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_autoexposure_bt.setAutoDefault(False) + self.spectral_mode_autoexposure_bt.setObjectName("spectral_mode_autoexposure_bt") + self.gridLayout_4.addWidget(self.spectral_mode_autoexposure_bt, 0, 0, 1, 1) + self.autoexposure_le = QtWidgets.QLineEdit(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.autoexposure_le.sizePolicy().hasHeightForWidth()) + self.autoexposure_le.setSizePolicy(sizePolicy) + self.autoexposure_le.setMaximumSize(QtCore.QSize(200, 16777215)) + self.autoexposure_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:40pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.autoexposure_le.setObjectName("autoexposure_le") + self.gridLayout_4.addWidget(self.autoexposure_le, 0, 1, 1, 1) + self.gridLayout_8.addWidget(self.frame_4, 0, 0, 1, 1) + self.frame_6 = QtWidgets.QFrame(self.frame_2) + self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_6.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_6.setObjectName("frame_6") + self.gridLayout_2 = QtWidgets.QGridLayout(self.frame_6) + self.gridLayout_2.setContentsMargins(0, 0, 0, 0) + self.gridLayout_2.setSpacing(0) + self.gridLayout_2.setObjectName("gridLayout_2") + self.dc_timer_label = QtWidgets.QLabel(self.frame_6) + self.dc_timer_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.dc_timer_label.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.dc_timer_label.setAlignment(QtCore.Qt.AlignCenter) + self.dc_timer_label.setObjectName("dc_timer_label") + self.gridLayout_2.addWidget(self.dc_timer_label, 0, 1, 1, 1) + self.spectral_mode_dc_bt = QtWidgets.QPushButton(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_dc_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_dc_bt.setSizePolicy(sizePolicy) + self.spectral_mode_dc_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_dc_bt.setAutoDefault(False) + self.spectral_mode_dc_bt.setObjectName("spectral_mode_dc_bt") + self.gridLayout_2.addWidget(self.spectral_mode_dc_bt, 0, 0, 1, 1) + self.gridLayout_8.addWidget(self.frame_6, 1, 0, 1, 1) + self.frame_7 = QtWidgets.QFrame(self.frame_2) + self.frame_7.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_7.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_7.setObjectName("frame_7") + self.gridLayout_7 = QtWidgets.QGridLayout(self.frame_7) + self.gridLayout_7.setContentsMargins(0, 0, 0, 0) + self.gridLayout_7.setSpacing(0) + self.gridLayout_7.setObjectName("gridLayout_7") + self.spectral_mode_wb_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_wb_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_wb_bt.setSizePolicy(sizePolicy) + self.spectral_mode_wb_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_wb_bt.setAutoDefault(False) + self.spectral_mode_wb_bt.setObjectName("spectral_mode_wb_bt") + self.gridLayout_7.addWidget(self.spectral_mode_wb_bt, 0, 0, 1, 1) + self.wb_timer_label = QtWidgets.QLabel(self.frame_7) + self.wb_timer_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.wb_timer_label.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.wb_timer_label.setAlignment(QtCore.Qt.AlignCenter) + self.wb_timer_label.setObjectName("wb_timer_label") + self.gridLayout_7.addWidget(self.wb_timer_label, 0, 1, 1, 1) + self.gridLayout_8.addWidget(self.frame_7, 2, 0, 1, 1) + self.frame_5 = QtWidgets.QFrame(self.frame_2) + self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_5.setObjectName("frame_5") + self.gridLayout_5 = QtWidgets.QGridLayout(self.frame_5) + self.gridLayout_5.setContentsMargins(0, 0, 0, 0) + self.gridLayout_5.setSpacing(0) + self.gridLayout_5.setObjectName("gridLayout_5") + self.spectral_mode_record_bt = QtWidgets.QPushButton(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_record_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_record_bt.setSizePolicy(sizePolicy) + self.spectral_mode_record_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_record_bt.setAutoDefault(False) + self.spectral_mode_record_bt.setObjectName("spectral_mode_record_bt") + self.gridLayout_5.addWidget(self.spectral_mode_record_bt, 0, 0, 1, 1) + self.data_type_comboBox = QtWidgets.QComboBox(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.data_type_comboBox.sizePolicy().hasHeightForWidth()) + self.data_type_comboBox.setSizePolicy(sizePolicy) + self.data_type_comboBox.setMaximumSize(QtCore.QSize(200, 16777215)) + self.data_type_comboBox.setStyleSheet("/*按钮普通态*/\n" +"QComboBox\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}") + self.data_type_comboBox.setFrame(False) + self.data_type_comboBox.setObjectName("data_type_comboBox") + self.data_type_comboBox.addItem("") + self.data_type_comboBox.addItem("") + self.data_type_comboBox.addItem("") + self.gridLayout_5.addWidget(self.data_type_comboBox, 0, 1, 1, 1) + self.progressBar = QtWidgets.QProgressBar(self.frame_5) + self.progressBar.setProperty("value", 0) + self.progressBar.setTextVisible(False) + self.progressBar.setObjectName("progressBar") + self.gridLayout_5.addWidget(self.progressBar, 1, 0, 1, 2) + self.gridLayout_8.addWidget(self.frame_5, 3, 0, 1, 1) + self.gridLayout_6.addWidget(self.frame_2, 1, 0, 1, 1) + self.frame_3 = QtWidgets.QFrame(spectral_Window_phone) + self.frame_3.setMaximumSize(QtCore.QSize(16777215, 200)) + self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_3.setObjectName("frame_3") + self.gridLayout_10 = QtWidgets.QGridLayout(self.frame_3) + self.gridLayout_10.setContentsMargins(0, 0, 0, 0) + self.gridLayout_10.setSpacing(0) + self.gridLayout_10.setObjectName("gridLayout_10") + self.frame_9 = QtWidgets.QFrame(self.frame_3) + self.frame_9.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_9.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_9.setObjectName("frame_9") + self.gridLayout_9 = QtWidgets.QGridLayout(self.frame_9) + self.gridLayout_9.setContentsMargins(0, 0, 0, 0) + self.gridLayout_9.setSpacing(0) + self.gridLayout_9.setObjectName("gridLayout_9") + self.filename_le = QtWidgets.QLineEdit(self.frame_9) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.filename_le.sizePolicy().hasHeightForWidth()) + self.filename_le.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(61) + self.filename_le.setFont(font) + self.filename_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:61pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.filename_le.setObjectName("filename_le") + self.gridLayout_9.addWidget(self.filename_le, 0, 2, 1, 1) + self.label_2 = QtWidgets.QLabel(self.frame_9) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth()) + self.label_2.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.label_2.setFont(font) + self.label_2.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.gridLayout_9.addWidget(self.label_2, 0, 1, 1, 1) + self.file_number_label = QtWidgets.QLabel(self.frame_9) + self.file_number_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.file_number_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.file_number_label.setAlignment(QtCore.Qt.AlignCenter) + self.file_number_label.setObjectName("file_number_label") + self.gridLayout_9.addWidget(self.file_number_label, 0, 3, 1, 1) + self.frame_10 = QtWidgets.QFrame(self.frame_9) + self.frame_10.setMinimumSize(QtCore.QSize(200, 0)) + self.frame_10.setMaximumSize(QtCore.QSize(200, 16777215)) + self.frame_10.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_10.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_10.setObjectName("frame_10") + self.gridLayout_11 = QtWidgets.QGridLayout(self.frame_10) + self.gridLayout_11.setContentsMargins(0, 0, 0, 0) + self.gridLayout_11.setSpacing(0) + self.gridLayout_11.setObjectName("gridLayout_11") + self.label_3 = QtWidgets.QLabel(self.frame_10) + self.label_3.setMinimumSize(QtCore.QSize(140, 0)) + self.label_3.setMaximumSize(QtCore.QSize(110, 16777215)) + self.label_3.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.gridLayout_11.addWidget(self.label_3, 0, 0, 1, 1) + self.label_4 = QtWidgets.QLabel(self.frame_10) + self.label_4.setMinimumSize(QtCore.QSize(140, 0)) + self.label_4.setMaximumSize(QtCore.QSize(110, 16777215)) + self.label_4.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_4.setAlignment(QtCore.Qt.AlignCenter) + self.label_4.setObjectName("label_4") + self.gridLayout_11.addWidget(self.label_4, 1, 0, 1, 1) + self.spectral_number_le = QtWidgets.QLineEdit(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_number_le.sizePolicy().hasHeightForWidth()) + self.spectral_number_le.setSizePolicy(sizePolicy) + self.spectral_number_le.setMinimumSize(QtCore.QSize(60, 0)) + self.spectral_number_le.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.spectral_number_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:30pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.spectral_number_le.setObjectName("spectral_number_le") + self.gridLayout_11.addWidget(self.spectral_number_le, 1, 2, 1, 1) + self.framenumber_average_le = QtWidgets.QLineEdit(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.framenumber_average_le.sizePolicy().hasHeightForWidth()) + self.framenumber_average_le.setSizePolicy(sizePolicy) + self.framenumber_average_le.setMinimumSize(QtCore.QSize(60, 0)) + self.framenumber_average_le.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.framenumber_average_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:30pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.framenumber_average_le.setObjectName("framenumber_average_le") + self.gridLayout_11.addWidget(self.framenumber_average_le, 0, 2, 1, 1) + self.gridLayout_9.addWidget(self.frame_10, 0, 0, 1, 1) + self.gridLayout_10.addWidget(self.frame_9, 0, 0, 1, 1) + self.frame_8 = QtWidgets.QFrame(self.frame_3) + self.frame_8.setMaximumSize(QtCore.QSize(16777215, 35)) + self.frame_8.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_8.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_8.setObjectName("frame_8") + self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_8) + self.gridLayout_3.setContentsMargins(0, 0, 0, 0) + self.gridLayout_3.setSpacing(0) + self.gridLayout_3.setObjectName("gridLayout_3") + spacerItem = QtWidgets.QSpacerItem(399, 15, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.gridLayout_3.addItem(spacerItem, 0, 0, 1, 1) + self.t_label = QtWidgets.QLabel(self.frame_8) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.t_label.sizePolicy().hasHeightForWidth()) + self.t_label.setSizePolicy(sizePolicy) + self.t_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.t_label.setAlignment(QtCore.Qt.AlignCenter) + self.t_label.setObjectName("t_label") + self.gridLayout_3.addWidget(self.t_label, 0, 1, 1, 1) + self.hum_label = QtWidgets.QLabel(self.frame_8) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.hum_label.sizePolicy().hasHeightForWidth()) + self.hum_label.setSizePolicy(sizePolicy) + self.hum_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.hum_label.setAlignment(QtCore.Qt.AlignCenter) + self.hum_label.setObjectName("hum_label") + self.gridLayout_3.addWidget(self.hum_label, 0, 2, 1, 1) + self.camera_status_label = QtWidgets.QLabel(self.frame_8) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.camera_status_label.sizePolicy().hasHeightForWidth()) + self.camera_status_label.setSizePolicy(sizePolicy) + self.camera_status_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.camera_status_label.setAlignment(QtCore.Qt.AlignCenter) + self.camera_status_label.setObjectName("camera_status_label") + self.gridLayout_3.addWidget(self.camera_status_label, 0, 3, 1, 1) + self.gridLayout_10.addWidget(self.frame_8, 1, 0, 1, 1) + self.gridLayout_6.addWidget(self.frame_3, 2, 0, 1, 1) + + self.retranslateUi(spectral_Window_phone) + QtCore.QMetaObject.connectSlotsByName(spectral_Window_phone) + + def retranslateUi(self, spectral_Window_phone): + _translate = QtCore.QCoreApplication.translate + spectral_Window_phone.setWindowTitle(_translate("spectral_Window_phone", "光谱窗口")) + self.spectral_mode_autoexposure_bt.setText(_translate("spectral_Window_phone", "曝 光")) + self.dc_timer_label.setText(_translate("spectral_Window_phone", "计时")) + self.spectral_mode_dc_bt.setText(_translate("spectral_Window_phone", "暗 电 流")) + self.spectral_mode_wb_bt.setText(_translate("spectral_Window_phone", "白 板")) + self.wb_timer_label.setText(_translate("spectral_Window_phone", "计时")) + self.spectral_mode_record_bt.setText(_translate("spectral_Window_phone", "采 集")) + self.data_type_comboBox.setCurrentText(_translate("spectral_Window_phone", "Ref")) + self.data_type_comboBox.setItemText(0, _translate("spectral_Window_phone", "Ref")) + self.data_type_comboBox.setItemText(1, _translate("spectral_Window_phone", "DN")) + self.data_type_comboBox.setItemText(2, _translate("spectral_Window_phone", "Rad")) + self.label_2.setText(_translate("spectral_Window_phone", "文 件")) + self.file_number_label.setText(_translate("spectral_Window_phone", "文件号")) + self.label_3.setText(_translate("spectral_Window_phone", "自动平均")) + self.label_4.setText(_translate("spectral_Window_phone", "连续测量")) + self.t_label.setText(_translate("spectral_Window_phone", "温度:无数据")) + self.hum_label.setText(_translate("spectral_Window_phone", "湿度:无数据")) + self.camera_status_label.setText(_translate("spectral_Window_phone", "光谱仪:连接失败")) diff --git a/record_system_v27/ui/spectral_Window_phone.ui b/record_system_v27/ui/spectral_Window_phone.ui new file mode 100644 index 0000000..7962cf0 --- /dev/null +++ b/record_system_v27/ui/spectral_Window_phone.ui @@ -0,0 +1,1057 @@ + + + spectral_Window_phone + + + + 0 + 0 + 540 + 1175 + + + + 光谱窗口 + + + + + + + 0 + 0 + + + + + 0 + 600 + + + + + 16777215 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 600 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 曝 光 + + + false + + + + + + + + 0 + 0 + + + + + 200 + 16777215 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:40pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 200 + 16777215 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 计时 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 暗 电 流 + + + false + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 白 板 + + + false + + + + + + + + 200 + 16777215 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 计时 + + + Qt::AlignCenter + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 采 集 + + + false + + + + + + + + 0 + 0 + + + + + 200 + 16777215 + + + + /*按钮普通态*/ +QComboBox +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + + + Ref + + + false + + + + Ref + + + + + DN + + + + + Rad + + + + + + + + 0 + + + false + + + + + + + + + + + + + + 16777215 + 200 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + Microsoft Yahei + 61 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:61pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + + + + + + 0 + 0 + + + + + Microsoft Yahei + 25 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文 件 + + + Qt::AlignCenter + + + + + + + + 200 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文件号 + + + Qt::AlignCenter + + + + + + + + 200 + 0 + + + + + 200 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 140 + 0 + + + + + 110 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 自动平均 + + + Qt::AlignCenter + + + + + + + + 140 + 0 + + + + + 110 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 连续测量 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:30pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:30pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + + + + + + + + + + + + 16777215 + 35 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 399 + 15 + + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 温度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 湿度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 光谱仪:连接失败 + + + Qt::AlignCenter + + + + + + + + + + + + + + diff --git a/record_system_v28/2record_system_v28.py b/record_system_v28/2record_system_v28.py new file mode 100644 index 0000000..bf9d108 --- /dev/null +++ b/record_system_v28/2record_system_v28.py @@ -0,0 +1,2313 @@ +# -*- coding:utf-8 -*- + +''' +在2record system_v2.2的基础上更新: +1、光谱模式像asd一样,不停的采集和显示,但是不保存,点击保存按钮时才保存光谱 +2、 +3、 +4、 +5、 +6、 +7、 +''' + +# 内置包 +import os, sys, functools, re, shutil, traceback, time +import subprocess +import datetime # 几种Python执行时间的计算方法:https://blog.csdn.net/wangshuang1631/article/details/54286551 +import logging + +# 三方包 +import numpy as np +from ximea import xiapi +import serial +import serial.tools.list_ports +from serial.serialutil import SerialBase, SerialException + +# 界面包 +from PyQt5.QtCore import Qt, QObject, QThreadPool, QTimer, QRegExp, pyqtSignal +# from PyQt5.QtCore import QRectF, pyqtSignal, QRunnable, pyqtSlot, QT_VERSION_STR +from PyQt5.QtGui import QIntValidator, QRegExpValidator, QPixmap, QImage, QPainterPath +from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, qApp, QDialog, QFileDialog, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem + +import matplotlib +matplotlib.use("Qt5Agg") # 声明使用QT5 +from library.matplotlib_display_image_spectral import MatplotlibSpectralViewer, MatplotlibImageViewer + + +# 自己写的包 +from QtImageViewer import QtImageViewer +from QtSpectralViewer import QtSpectralViewer +from library.multithread import Worker +from library.image_reader_writer import ImageReaderWriter +from library.functions import get_path, get_resource_path, return_file_path +from library.message_box import MessageBox +from library.config import ConfigFile +from library.log import Log + +# Qtdesigner所画界面 +from record_system_v28.ui.enter_window import * +from record_system_v28.ui.image_Window_phone import * +from record_system_v28.ui.spectral_Window_phone import * + + +# 主窗口 +class EnterWindow(QMainWindow, Ui_enter_Window): + def __init__(self, camera, parent=None): + super(EnterWindow, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + + self.image_mode_phone_bt.clicked.connect(self.image_window) + + self.spectral_mode_bt.clicked.connect(self.spectral_window) + + # self.setEnabled(False) # 先设置本窗口不可用,当打开相机成功后,才设置为可用 + + system_setting.camera_status_signal.connect(self.test_imager_status) + + def image_window(self): + self.image_window_phone_instance = ImageWindowPhone() + self.image_window_phone_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + self.image_window_phone_instance.show() + + def spectral_window(self): + self.spectral_window_instance = SpectralWindow() + print(id(self.spectral_window_instance)) + self.spectral_window_instance.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) + self.spectral_window_instance.show() + + def test_imager_status(self, imager_status): + if imager_status == 1000: # 相机打开成功 + self.camstatus_label.setText('相机打开成功!') + + # 如果相机打开成功,界面中label颜色设置为绿色 + self.change_lable_background_color('green') + + self.setEnabled(True) # 如果相机打开成功,则窗口可用 + elif imager_status == 1001: + self.camstatus_label.setText('相机打开时出现不是ximea错误的未知错误!') + + # 如果相机打开成功,界面中label颜色设置为绿色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 1: + self.camstatus_label.setText('相机已经断开连接!请重新打开软件尝试连接相机!') + + # 如果相机打开失败,界面中label颜色设置为红色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 12: + pass + elif imager_status == 41: + pass + elif imager_status == 56: + self.camstatus_label.setText('没有检测到光谱仪!') + + # 如果相机打开失败,界面中label颜色设置为红色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 57: + self.camstatus_label.setText('相机被占用,请关机重启!') + + # 如果相机打开失败,界面中label颜色设置为红色 + self.change_lable_background_color('red') + + self.setEnabled(False) # 如果相机打开失败,则窗口不可用 + elif imager_status == 103: + pass + + def change_lable_background_color(self, color): + pattern = re.compile('background-color:rgb[(](.*)[)]') + old_style_sheet = self.camstatus_label.styleSheet() + + if color == 'red': # 如果相机打开失败,界面中label颜色设置为红色 + new_style_sheet = re.sub(pattern, r'background-color:rgb(255 , 0 , 0)', old_style_sheet) + self.camstatus_label.setStyleSheet(new_style_sheet) + elif color == 'green': # 如果相机打开成功,界面中label颜色设置为绿色 + new_style_sheet = re.sub(pattern, r'background-color:rgb(0 , 255 , 0)', old_style_sheet) + self.camstatus_label.setStyleSheet(new_style_sheet) + + +class SerialPort(QObject): + # 信号必须定义为类属性,不能放在__init__方法里 + serial_signal = pyqtSignal(object) # 建立信号,用于发射获取的温湿度 + + def __init__(self): + super(SerialPort, self).__init__() + + # 建立进程池:https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 获取log温度日志的文件夹 + self.config_file_object = ConfigFile() + + # log + self.logger = logging.getLogger('root.serial') + + if not os.path.exists(self.config_file_object.log_dir + '//temperature.log'): + with open(self.config_file_object.log_dir + '//temperature.log', 'w') as f: + pass + + formatter1 = logging.Formatter('%(asctime)s %(message)s') + temperature_file_handler = logging.FileHandler(self.config_file_object.log_dir + '//temperature.log') # 输出到文件 + temperature_file_handler.setLevel(logging.DEBUG) + temperature_file_handler.setFormatter(formatter1) + + self.logger.addHandler(temperature_file_handler) + + self.connect_number = 0 # 记录打开串口的次数 + self.serial_port = self.open_serial_port() + + self.timer = QTimer() + self.timer.timeout.connect(self.receiver_data_from_port) + # self.timer.start(1000) + + self.receiver_data_from_port_wraper() + + def open_serial_port(self): + self.connect_number += 1 + port_list = list(serial.tools.list_ports.comports()) # 列出所有可用串口 + # print(port_list) + + if len(port_list) > 0: # 如果可用串口 >0 个 + # 打印出所有串口的信息 + for i in range(0, len(port_list)): + print(port_list[i]) + + # 打开第一个串口 + ser = serial.Serial(port_list[0].device) + # print('温湿度传感器打开成功!') + return ser + elif len(port_list) == 0: # 如果可用串口为0个 + if self.connect_number == 1: + self.logger.info('无可用串口,温湿度传感器不可用!') + else: + self.logger.error('串口连接上之后,断开连接!') + return 1 # 如果返回1,则代表没有可用串口;通过1来判断不执行定时器触发:self.timer.start(1000) + else: # 其他没有考虑到的情况 + return 1 + + def receiver_data_from_port_wraper(self): + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(self.receiver_data_from_port) + + self.threadpool.start(worker) + + def receiver_data_from_port(self): + ''' + 定时器QTimer没隔1s调用此函数一次 → 让串口buffer有足够的数据等待读取 + :return: 无返回值 + + 本函数功能:1、串口中接收字节数据,有两种帧 → 代表两种数据 + 2、判断帧头位置和本帧数据类型 + 3、判断帧尾 → 等效判断本帧数据是否完全 + 4、如果数据帧完整 → 解析数据,将温度湿度显示到界面上和写入到文件中 + ''' + while True: + try: + if self.serial_port.in_waiting: # 如果串口buffer有数据等待读取 + bytes_receive = self.serial_port.read(self.serial_port.inWaiting()) # 读取串口buffer的数据 + # print(len(bytes_receive)) + + # 判断帧头位置,通过正则表达式 + hex_receive = bytes_receive.hex() # 一个字节需要一个两位16进制数表示,所以:len(hex_receive) = len(bytes_receive) / 2 + p = re.compile('5a5a*') + index_head = [i.start() / 2 for i in re.finditer(p, hex_receive)] # re.finditer() + # print(hex_receive) + # print(index_head) + except SerialException: # 程序打开时,温湿度传感器的串口工作正常;如果程序运行中拔掉串口就会出现此异常 + self.logger.error('在程序运行中温湿度传感器的串口出现问题!') + + # 再次尝试打开串口 + self.serial_port = self.open_serial_port() + if not isinstance(self.serial_port, int): + self.logger.info('再次尝试连接温湿度传感器成功!') + else: + self.logger.info('再次尝试连接温湿度传感器失败!') + except AttributeError: # int object has no attribute: in_waiting + self.timer.stop() + # self.logger.info('停止定时触发器!') + except Exception as e: # 未出现过的异常。当第一次出现时,需要编写代码处理,先写入日志文件(log) + self.logger.critical('未知错误!') + else: # 当没有捕获到异常时,代表串口数据获取成功 → 执行数据解析 + # 解析数据 + try: + if len(index_head) != 0: + Lux = 1.0 + T = 1.0 + P = 1.0 + Hum = 1.0 + H = 1.0 + Lux_full = 0 # 判断光照帧的数据是否完整。0:不完整;1:完整; + T_full = 0 # 判断温度帧的数据是否完整。0:不完整;1:完整; + try: + for i in index_head: # 循环遍历每个帧头 + if bytes_receive[int(i) + 2] == 21: # 0x15=21,判断帧头类型 + if sum(bytes_receive[int(i):int(i) + 8]) & 0xff == bytes_receive[int(i) + 8]: # 判断帧尾是否正确 + # print('光照帧的帧尾正确!') + + Lux_full = 1 # 如果帧尾,此帧数据数完整的 + Lux = ((bytes_receive[int(i) + 4] << 24) | (bytes_receive[int(i) + 5] << 16) | ( + bytes_receive[int(i) + 6] << 8) | bytes_receive[int(i) + 7]) / 100 + if bytes_receive[int(i) + 2] == 69: # 0x45=69,判断帧头类型 + if sum(bytes_receive[int(i):int(i) + 14]) & 0xff == bytes_receive[int(i) + 14]: # 判断帧尾是否正确 + # print('温度帧的帧尾正确!') + + T_full = 1 # 当执行这段代码时,代表帧头帧尾都正常,此帧数据数完整的 + T = ((bytes_receive[int(i) + 4] << 8) | bytes_receive[int(i) + 5]) / 100 + P = ((bytes_receive[int(i) + 6] << 24) | (bytes_receive[int(i) + 7] << 16) | ( + bytes_receive[int(i) + 8] << 8) | bytes_receive[ + int(i) + 9]) / 100 + Hum = ((bytes_receive[int(i) + 10] << 8) | bytes_receive[int(i) + 11]) / 100 + H = ((bytes_receive[int(i) + 12] << 8) | bytes_receive[int(i) + 13]) / 100 + except IndexError as e: # 当出现帧头,但是帧头到帧尾的数据不全 → 在判断帧尾是否正确时就会出现索引越界 + # print('----------------------索引越界!') + pass + except Exception: # 当出现前面没有解决的异常时,前面的异常捕捉就失效。最后通过异常基类来捕捉 → 代表需要修改代码进行处理的新异常 + # print('---------------------------------没遇见过的异常') + pass + + # 将数据显示和写入文件 + if Lux_full + T_full == 2: # x + y == 2代表温度帧和光照帧都完整 + # self.t_label.setVisible(True) + # self.hum_label.setVisible(True) + # self.t_label.setText('温度:' + str(T)) + # self.hum_label.setText('湿度:' + str(Hum)) + + # print('发送数据') + + self.serial_signal.emit((str(T), str(Hum))) + self.logger.debug('%s %s %s', str(T), str(Hum), str(camera.get_temp())) # 将温湿度记录进log文件中 + + # print('光照强度:%f' % Lux) + # print('温度:%f' % T) + # print('气压:%f' % P) + # print('湿度:%f' % Hum) + # print('海拔:%f' % H) + # print() + elif Lux_full + T_full == 1: + # print('只有一个数据帧是完整的。(光照帧或者温度帧)') + # print() + pass + except UnboundLocalError: + # print(2222222222222222222222222222222) + # traceback.print_exc() + pass + except Exception: + self.logger.critical('未知错误!') + finally: # 不管有没有捕获到异常都会执行,一般用作资源回收 + pass + + time.sleep(3) + + +# 图像窗口 +class ImageWindowPhone(QDialog, Ui_image_Window_phone): + # 信号必须定义为类属性,不能放在__init__方法里 + arcus_status_signal = pyqtSignal(int) # arcus信号:0→马达未连接;1→马达连接成功; + plot_signal = pyqtSignal() # 采集影像时,边采集边刷新显示 + + def __init__(self, parent=None): + ''' + The super().__init__() method invokes the base class constructor from the MyForm class, + that is, the constructor of the QDialog class is invoked from MyForm class to indicate that + QDialog is displayed through this class iss a top-level window. + ''' + super(ImageWindowPhone, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + self.setWindowModality(Qt.ApplicationModal) # 阻塞此窗口:此行代码必须放在show()函数之前 + + # 配置文件读取和写入类,配置文件读写和界面分离 + # 1、采集数据需要的帧率、曝光、帧数、文件名等等都由此类从文件中读取 + # 2、并保存在此类中 + self.config_file_object = ConfigFile() + + # log + self.logger = logging.getLogger('root.image_phone') + + if not os.path.exists(self.config_file_object.log_dir + '//image_operate.log'): + with open(self.config_file_object.log_dir + '//image_operate.log', 'w') as f: + pass + + image_operate_file_handler = logging.FileHandler(self.config_file_object.log_dir + "//image_operate.log") # 输出到文件 + image_operate_file_handler.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + image_operate_file_handler.setFormatter(formatter) + + stream_handler = logging.StreamHandler() # 输出到控制台 + stream_handler.setLevel(logging.DEBUG) + stream_handler.setFormatter(formatter) + self.logger.addHandler(image_operate_file_handler) + self.logger.addHandler(stream_handler) + + # 在窗口中显示串口接收的温度/湿度 + serial_port.serial_signal.connect(self.update_temperature) + self.hpi_temperature = None # 暂时保存温度,当保存影像文件时会用到 + + # 数据采集保存类,采集数据并将数据保存在此类中,数据采集和界面分离 + self.image_camera_operation = CameraOperation(self.hpi_temperature, self.config_file_object) + + # 当配置文件读取完成后,就第一时间根据读取的配置文件设置相机曝光、帧率和gain + self.image_camera_operation.set_exposure_gain_framerate(camera) + self.initiate_arcus_speed() # 初始化arcus速度 + self.set_arcus_speed_bool = True # 当马达断开后设置为False,再次连接时通过False设置马达速度 + + # 采集影像时,边采集边刷新显示 + self.plot_signal.connect(self.plotimg) + self.plot_when_record_finished_boot = False # 当点击停止采集按钮时,绘制整个采集到的影像 + + # 建立进程池:https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 初始化窗口中的值 + self.framenumber_le.setText(str(self.config_file_object.frame_number)) + self.framerate_le.setText(str(self.config_file_object.framerate)) + self.exposure_time_le.setText(str(self.config_file_object.exposure_time)) + self.arcus_speed_le.setText(str(self.config_file_object.arcus_speed)) + self.filename_le.setText(self.config_file_object.default_image_name) + + # 显示影像和调焦 + # self.myImageFigure = MatplotlibImageViewer() + self.myImageFigure = QtImageViewer() + self.myImageFigure.leftMouseButtonPressed.connect(self.handle_left_click) + self.image_glo.addWidget(self.myImageFigure) + + # self.myFocusFigure = MatplotlibSpectralViewer(xlabel='Wavelength (nm)') + self.myFocusFigure = QtSpectralViewer() + self.focus_glo.addWidget(self.myFocusFigure) + + # 操作光谱仪 + self.state = 0 # 光谱仪操作状态:曝光=1;暗电流=3;→ 所以只有state==4时才能开始采集影像 + self.focus_count = 1 # 用于调焦按钮点击计数,取2的余数;当余数为1是执行调焦,当余数为0时停止调焦 + self.record_count = 1 # 用于采集按钮点击计数,取2的余数;当余数为1是执行采集,当余数为0时停止采集;这是为了使用通过一个按钮控制开始采集和停止采集 + + self.image_mode_exposureTime_bt.clicked.connect(self.run) + self.image_mode_focus_bt.clicked.connect(self.run) # 停止调焦操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.image_mode_dc_bt.clicked.connect(self.run) + self.image_mode_record_bt.clicked.connect(self.run) # 停止采集操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.save_bt.clicked.connect(self.run) + + # 手动改变窗口中的值,然后将值写入camera_operation类对应的变量中 + self.exposure_time_le.setValidator(QIntValidator()) # QIntValidator是一个类 + self.framerate_le.setValidator(QIntValidator()) + self.framenumber_le.setValidator(QIntValidator()) + + my_regex = QRegExp("[a-zA-Z0-9]*") + my_validator = QRegExpValidator(my_regex, self.filename_le) + self.filename_le.setValidator(my_validator) + + self.exposure_time_le.editingFinished.connect(self.text_edited) + # self.exposure_time_le.setPlaceholderText('曝光时间') + self.framerate_le.editingFinished.connect(self.text_edited) + self.framenumber_le.editingFinished.connect(self.text_edited) + self.filename_le.editingFinished.connect(self.text_edited) + + # 马达相关操作 + self.arcus_left_bt.pressed.connect(self.leftMove) + self.arcus_left_bt.released.connect(self.stop) + self.arcus_right_bt.pressed.connect(self.rightMove) + self.arcus_right_bt.released.connect(self.stop) + + # self.arcus_speed_le.setText(self.arc.write('HSPD')) + self.arcus_speed_le.editingFinished.connect(self.text_edited) + self.arcus_speed_le.setValidator(QIntValidator()) + + self.time = time.time() # 控制arcus两次命令发送的时间间隔 + self.time_interval = 1 + + system_setting.camera_status_signal.connect(self.response_to_imager_status) + + # 检测arcus马达的连接情况 + self.timer = QTimer(self) # 使用这个定时器,会造成界面卡顿 + self.timer.timeout.connect(self.test_arcus_status) + # self.timer.start(5000) + + self.test_arcus_status_wraper() + self.arcus_status_signal.connect(self.response_to_arcus_status) + + # 1)决定采集DN/red;2)反转马达 + self.rad_dn_comboBox.currentIndexChanged.connect(self.change_rad_dn) + self.arcus_direction_bt.clicked.connect(self.change_arcus_direction) + + def change_rad_dn(self): + if self.rad_dn_comboBox.currentText() == 'rad': + self.image_camera_operation.record_rad_bool = True + elif self.rad_dn_comboBox.currentText() == 'dn': + self.image_camera_operation.record_rad_bool = False + + def change_arcus_direction(self): + if self.image_camera_operation.arcus_reverse_while_record == False: + self.image_camera_operation.arcus_reverse_while_record = True + self.change_widget_background_color(self.arcus_direction_bt, 'red') + elif self.image_camera_operation.arcus_reverse_while_record == True: + self.image_camera_operation.arcus_reverse_while_record = False + self.change_widget_background_color(self.arcus_direction_bt, 'gray') + + def test_arcus_status_wraper(self): + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(self.test_arcus_status) + + self.threadpool.start(worker) + + def test_arcus_status(self): + while True: + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' DN' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=2) + if 'Arcus device connected' in output.decode('utf-8'): + self.arcus_status_signal.emit(1) + + if not self.set_arcus_speed_bool: # 当马达断开再次连接时,需要重新设置速度 + python2_set_arcus_speed_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' HSPD=' + str(self.config_file_object.arcus_speed) + python2_set_arcus_speed_process = subprocess.Popen(python2_set_arcus_speed_command.split(), stdout=subprocess.PIPE) + + try: + python2_set_arcus_speed_output, python2_set_arcus_speed_error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + python2_set_arcus_speed_process.kill() + python2_set_arcus_speed_output, python2_set_arcus_speed_error = process.communicate() + + self.set_arcus_speed_bool = True + elif 'No arcus devices' in output.decode('utf-8') or 'Cannot connect Arcus device' in output.decode('utf-8'): + self.arcus_status_signal.emit(0) + self.set_arcus_speed_bool = False + except subprocess.TimeoutExpired: + process.kill() + # output2, error2 = process.communicate() + # if 'Arcus device connected' in output2.decode('utf-8'): + # self.arcus_status_signal.emit(1) + # elif 'No arcus devices' in output2.decode('utf-8'): + # self.arcus_status_signal.emit(0) + # self.set_arcus_speed_bool = False + + time.sleep(4) # 本线程沉睡3秒 + + def response_to_arcus_status(self, arcus_status): + if arcus_status == 0: + self.arcus_status_label.setText('马达:连接失败!') + self.change_widget_background_color(self.arcus_status_label, 'red') + elif arcus_status == 1: + self.arcus_status_label.setText('马达:连接正常!') + self.change_widget_background_color(self.arcus_status_label, 'green') + + def response_to_imager_status(self, imager_status): + if imager_status == 1000: # 相机打开成功 + # print('相机打开成功!') + + try: + temperature = camera.get_temp() + except Exception: + temperature = None + + self.camera_status_label.setText('光谱仪:' + str(temperature)) + + self.change_widget_background_color(self.camera_status_label, 'green') + elif imager_status == 1001: + print('相机打开时出现不是ximea错误的未知错误!') + elif imager_status == 1: + # print('相机已经断开连接!请重新打开软件尝试连接相机!') + + self.camera_status_label.setText('光谱仪:断开连接') + self.change_widget_background_color(self.camera_status_label, 'red') + + self.setEnabled(False) + self.close() + elif imager_status == 12: + pass + elif imager_status == 41: + pass + elif imager_status == 56: + print('没有检测到光谱仪!') + elif imager_status == 103: + pass + + def leftMove(self): + time_now = time.time() + if time_now - self.time > self.time_interval: + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J-' + python2_command = r'python2.exe ' + get_resource_path('./data/ArcusDevice.py') + ' CLR EO=1 J-' + + try: + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=2) + + # # test_arcus_status函数不停的执行命令(DN),检测马达连接情况;当在检测的同时执行移动马达命令,就会出现:Cannot connect Arcus device + # while 'Cannot connect Arcus device' in output.decode('utf-8'): + # process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + # output, error = process.communicate(timeout=2) + except subprocess.TimeoutExpired: + process.kill() + + def rightMove(self): + time_now = time.time() + if time_now - self.time > self.time_interval: + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py CLR EO=1 J+' + python2_command = r'python2.exe ' + get_resource_path('./data/ArcusDevice.py') + ' CLR EO=1 J+' + + try: + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=2) + + # # test_arcus_status函数不停的执行命令(DN),检测马达连接情况;当在检测的同时执行移动马达命令,就会出现:Cannot connect Arcus device + # while 'Cannot connect Arcus device' in output.decode('utf-8'): + # process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + # output, error = process.communicate(timeout=2) + except subprocess.TimeoutExpired: + process.kill() + + def stop(self): + self.time = time.time() + + # python2_command = r'D:\software\Anaconda3\envs\py27_32\python.exe D:\py27_program\arcus\ArcusDevice.py STOP' + python2_command = r'python2.exe ' + get_resource_path('./data/ArcusDevice.py') + ' STOP' + + try: + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=2) + + # # test_arcus_status函数不停的执行命令(DN),检测马达连接情况;当在检测的同时执行移动马达命令,就会出现:Cannot connect Arcus device + # while 'Cannot connect Arcus device' in output.decode('utf-8'): + # process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + # output, error = process.communicate(timeout=2) + except subprocess.TimeoutExpired: + process.kill() + + def handle_left_click(self, x, y): + # 画出光谱 + try: + row = int(y) + column = int(x) + # print("Pixel (row=" + str(row) + ", column=" + str(column) + ")") + + _, _, img = ImageReaderWriter.read_img('corning410_test', column, row, 1, 1) + + if isinstance(img, np.ndarray): # 如果点击到图像之外,img就是NoneType,就不重画光谱 + # print('点击有效') + + self.myFocusFigure.plot_wrap(self.image_camera_operation.get_wavelength_object.wave(model='array'), img[:, 0, 0]) + except TypeError: + pass + # print('有错') + # self.logger.critical('TypeError:', exc_info=True) + except Exception: + self.logger.critical('点击显示光谱时出现未知错误:', exc_info=True) + traceback.print_exc() + + # 手动修改界面中的值后,为相机重新设置如下参数:exposure, gain, framerate + def text_edited(self): + try: + # 将改变值1)保存到配置文件对象,供程序运行使用2)写入到配置文件,供程序下次打开读取 + self.config_file_object.image_signal.emit( + {'exposure_time': int(float(self.exposure_time_le.text())), + 'framerate': int(float(self.framerate_le.text())), 'frame_number': int(float(self.framenumber_le.text())), + 'default_image_name': self.filename_le.text(), 'arcus_speed': self.arcus_speed_le.text()}) + except ValueError: + self.x = MessageBox('请输入正确的值!') + self.x.exec() + except Exception: + self.logger.critical('设置曝光/gain/帧率/帧数时出现未知错误!', exe_info=True) + + if self.sender().objectName() == 'exposure_time_le': + self.state = 1 # 手动改变曝光时间后,强制让用户重新采集暗电流+白板 + + print('exposure_time_le改变') + self.image_camera_operation.set_exposure_gain_framerate(camera) + + if self.sender().objectName() == 'framerate_le': + self.state = 0 # 改变帧率后,需要重新曝光 + + print('framerate_le改变') + self.image_camera_operation.set_exposure_gain_framerate(camera) + + if self.sender().objectName() == 'framenumber_le': + self.image_camera_operation.create_rgb() + + if self.sender().objectName() == 'arcus_speed_le': + time_now = time.time() + if time_now - self.time > self.time_interval: + self.time = time.time() + + python2_command = r'python2.exe ' + get_resource_path('./data/ArcusDevice.py') + ' HSPD=' + str(self.arcus_speed_le.text()) + + try: + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=1) + + # test_arcus_status函数不停的执行命令(DN),检测马达连接情况;当在检测的同时执行移动马达命令,就会出现:Cannot connect Arcus device + while 'Cannot connect Arcus device' in output.decode('utf-8'): + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + + print('改变arcus速度出错output', output) + print('改变arcus速度出错error', error) + + def initiate_arcus_speed(self): + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' HSPD=' + str(self.config_file_object.arcus_speed) + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=1) + except subprocess.TimeoutExpired: + process.kill() + output, error = process.communicate() + + def update_temperature(self, data): + try: + self.hpi_temperature = data[0] + + self.t_label.setText('温度:' + data[0]) + self.hum_label.setText('湿度:' + data[1]) + + self.change_widget_background_color(self.t_label, 'green') + self.change_widget_background_color(self.hum_label, 'green') + except: + print('有问题') + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + self.t_label.setText('温度:无数据') + self.hum_label.setText('湿度:无数据') + + def timer_start(self): + ''' + 本函数目的是在self.timer.start(1000)外包裹一层(有点装饰器的感觉),加入判断: + 1、如果self.serial_port为串口类型,就触发定时器self.timer.start(1000) + 2、如果self.serial_port == 1(为int类型),则代表硬件中没有温湿度传感器,就没必要触发定时器self.timer.start(1000) + :return: 无返回值 + ''' + + if isinstance(self.serial_port, serial.serialwin32.Serial): + self.timer.start(1000) + elif isinstance(self.serial_port, int): + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + else: + pass + + def plotimg(self): + try: + if self.qt_sender == 'image_mode_record_bt': + frame_number_to_plot = self.image_camera_operation.record_time_for_plot * self.config_file_object.framerate + + self.framenumber_recorded_label.setText(str(frame_number_to_plot)) + + if frame_number_to_plot < 1000 or frame_number_to_plot == self.config_file_object.frame_number or self.plot_when_record_finished_boot: # 当采集的帧数大于1200帧时,为了防止界面卡死,就停止画图 + self.img = np.dstack((self.image_camera_operation.rgb[2, 0:frame_number_to_plot, :], self.image_camera_operation.rgb[1, 0:frame_number_to_plot, :], + self.image_camera_operation.rgb[0, 0:frame_number_to_plot, :])) + + self.myImageFigure.setImage(self.img) + + self.plot_when_record_finished_boot = False + elif self.qt_sender == 'image_mode_focus_bt': + self.myImageFigure.setImage(self.image_camera_operation.image_container) + + n = int(self.image_camera_operation.image_container.shape[0] / 2) + self.myFocusFigure.plot_wrap(self.image_camera_operation.image_container[n, :]) + + # worker = Worker(self.myImageFigure.setImage, self.image_camera_operation.image_container) + # self.threadpool.start(worker) + except: + self.logger.critical('未知错误--界面中绘制影像和光谱时!\n%s', exc_info=True) + + # 调焦、采集暗电流、采集白板、采集影像 都通过此函数 + def run(self): + try: + self.qt_sender = self.sender().objectName() + + if self.qt_sender == 'image_mode_focus_bt': + if self.focus_count % 2 == 1: + self.image_mode_focus_bt.setText('停止调焦') + self.core_operation() + self.focus_count += 1 + + self.change_widget_background_color(self.image_mode_focus_bt, 'red') + elif self.focus_count % 2 == 0: # 停止调焦操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.image_camera_operation.focus = False + self.image_mode_focus_bt.setText('调焦') + self.focus_count += 1 + elif self.qt_sender == 'image_mode_exposureTime_bt': + self.state = 1 + + self.core_operation() + + self.change_widget_background_color(self.image_mode_exposureTime_bt, 'red') + elif self.qt_sender == 'image_mode_dc_bt': + if self.state == 0: + self.x = MessageBox('请先曝光!') + self.x.exec() + elif self.state == 1 or self.state == 4: # 正常采集暗电流 + self.x = MessageBox('请先确认镜头盖已安装!') + self.x.exec() + + self.state = 4 + + self.core_operation() + + self.change_widget_background_color(self.image_mode_dc_bt, 'red') + elif self.qt_sender == 'image_mode_record_bt': + if self.record_count % 2 == 1: + if self.state == 0: + self.x = MessageBox('请先曝光!') + self.x.exec() + elif self.state == 1: # + self.x = MessageBox('请采集暗电流!') + self.x.exec() + elif self.state == 4: # 正常采集影像,采集DN/反射率的判断 放在CameraOperation类中 + self.record_count += 1 + self.image_mode_record_bt.setText('停止采集') + + self.core_operation() + + self.change_widget_background_color(self.image_mode_record_bt, 'red') + elif self.record_count % 2 == 0: # 停止采集操作非常简单,耗时非常短,瞬间可回到event loop,不会使界面卡死;所以不需要多线程 + self.plot_when_record_finished_boot = True + self.plot_signal.emit() + + self.image_camera_operation.record = False + self.image_mode_record_bt.setText('采集') + elif self.qt_sender == 'save_bt': + worker = Worker(self.savedata) + + worker.signals.error.connect(self.operate_failed) + worker.signals.finished.connect(self.operate_success) + + self.threadpool.start(worker) + + self.change_widget_background_color(self.save_bt, 'red') + except Exception: + traceback.print_exc() + + # 改变按钮三态中普通态的背景颜色 + def change_widget_background_color(self, qt_widget, color): + pattern = re.compile('background-color(.*)(normal\*/)') + old_style_sheet = qt_widget.styleSheet() + + if color == 'red': + new_style_sheet = re.sub(pattern, r'background-color:rgb(255 , 0 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'green': + new_style_sheet = re.sub(pattern, r'background-color:rgb(0 , 255 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'gray': + new_style_sheet = re.sub(pattern, r'background-color:rgb(225 , 225 , 225);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + + def core_operation(self): + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(self.image_camera_operation.start_AcquireData, camera, self.qt_sender, self.plot_signal) + + worker.signals.error.connect(self.operate_failed) + worker.signals.finished.connect(self.operate_success) + if self.qt_sender == 'image_mode_exposureTime_bt': + ''' + 曝光参数的设置过程: + (1)曝光参数返回到界面中的QLineEdit; + (2)通过QLineEdit的textChanged事件将值写入到camera_operation对应的变量; + (3)为相机设置参数:1)通过worker的finished信号【本程序使用】2)也可以通过QLineEdit的textChanged事件调用self.set_exposure函数,为相机设置参数 + 这种过程的好处是界面显示的曝光参数和实际设置的是同步的 + ''' + worker.signals.result.connect(self.post_auto_expose) + + self.threadpool.start(worker) + + self.disable_bt(True) + + def disable_bt(self, bool): + # 两个if判断存在的原因:调焦/停止调焦(采集/停止采集)使用同一个按钮,所以不能将其设置为不可用 + if self.qt_sender !='image_mode_focus_bt': + self.image_mode_focus_bt.setDisabled(bool) + if self.qt_sender != 'image_mode_record_bt': + self.image_mode_record_bt.setDisabled(bool) + + if bool == False: # 操作完成后设置为可用 + self.image_mode_record_bt.setDisabled(bool) + self.image_mode_focus_bt.setDisabled(bool) + + self.image_mode_exposureTime_bt.setDisabled(bool) + self.image_mode_dc_bt.setDisabled(bool) + self.save_bt.setDisabled(bool) + self.arcus_left_bt.setDisabled(bool) + self.arcus_right_bt.setDisabled(bool) + + self.exposure_time_le.setDisabled(bool) + self.framerate_le.setDisabled(bool) + self.arcus_speed_le.setDisabled(bool) + self.framenumber_le.setDisabled(bool) + self.filename_le.setDisabled(bool) + + self.rad_dn_comboBox.setDisabled(bool) + self.arcus_direction_bt.setDisabled(bool) + + def operate_failed(self, traceback_info): + if traceback_info[0] == xiapi.Xi_error: + if traceback_info[1].status == 1: # 在ximea的API中代表"Invalid handle":相机断开连接 + if self.qt_sender == 'image_mode_exposureTime_bt': + self.logger.error('自动曝光失败:相机断开连接!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_focus_bt': + self.logger.error('调焦失败:相机断开连接!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_dc_bt': + self.logger.error('采集暗电流失败:相机断开连接!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_record_bt': + self.logger.error('采集影像失败:相机断开连接!\n%s', traceback_info[2]) + elif traceback_info[1].status == 56: # 在ximea的API中代表"No Devices Found":在执行cam.open_device()时,无相机打开 + if self.qt_sender == 'image_mode_exposureTime_bt': + self.logger.error('自动曝光失败:无相机可供打开!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_focus_bt': + self.logger.error('调焦失败:无相机可供打开!\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_dc_bt': + self.logger.error('采集暗电流失败:无相机可供打开\n%s', traceback_info[2]) + elif self.qt_sender == 'image_mode_record_bt': + self.logger.error('采集影像失败:无相机可供打开\n%s', traceback_info[2]) + elif traceback_info[1].status == 12: # 在ximea的API中代表"Not supported":当相机正在采集数据时,执行代码cam.set_imgdataformat('XI_RAW16') + pass + elif traceback_info[1].status == 41: # 在ximea的API中代表"Acquisition already started":相机已经开始采集数据 + pass + elif traceback_info[0] == ValueError: + if self.qt_sender == 'save_bt': + self.logger.error('保存影像失败--影像名不正确!\n%s', traceback_info[2]) + + self.x = MessageBox('请输入正确的影像名!') + self.x.exec() + elif traceback_info[0] == FileNotFoundError: + if self.qt_sender == 'save_bt': + self.logger.error('保存影像失败--没有采集影像!\n%s', traceback_info[2]) + + self.x = MessageBox('请先采集影像!') + self.x.exec() + else: + self.logger.critical('未知错误!\n%s', traceback_info[2]) + + def operate_success(self): + if self.qt_sender == 'image_mode_exposureTime_bt': + self.logger.info('自动曝光成功----------------!') + self.enable_bt_and_change_background_to_gray() + + self.image_mode_exposureTime_bt.setText(re.sub('✔', '', self.image_mode_exposureTime_bt.text()) + '✔') + elif self.qt_sender == 'image_mode_focus_bt': + self.logger.info('调焦成功!') + self.enable_bt_and_change_background_to_gray() + + self.image_mode_focus_bt.setText(re.sub('✔', '', self.image_mode_focus_bt.text()) + '✔') + elif self.qt_sender == 'image_mode_dc_bt': + self.logger.info('采集暗电流成功!') + self.enable_bt_and_change_background_to_gray() + + self.image_mode_dc_bt.setText(re.sub('✔', '', self.image_mode_dc_bt.text()) + '✔') + elif self.qt_sender == 'image_mode_record_bt': + self.logger.info('采集影像成功!') + + self.image_mode_record_bt.setText('采集') + self.image_mode_record_bt.setDisabled(True) # 要等马达回到初始位置才能用 + self.record_count += 1 + + self.image_mode_record_bt.setText(re.sub('✔', '', self.image_mode_record_bt.text()) + '✔') + + self.save_bt.setText(re.sub('✔', '', self.save_bt.text())) + + worker = Worker(self.return_arcus_after_operate_success) + self.threadpool.start(worker) + elif self.qt_sender == 'save_bt': + self.save_bt.setText(re.sub('✔', '', self.save_bt.text()) + '✔') + self.enable_bt_and_change_background_to_gray() + + self.image_mode_record_bt.setText(re.sub('✔', '', self.image_mode_record_bt.text())) + + self.logger.info('保存影像成功!') + + def return_arcus_after_operate_success(self): + while True: + python2_command = r'python2.exe ' + get_resource_path( + './data/ArcusDevice.py') + ' PX' + process = subprocess.Popen(python2_command.split(), stdout=subprocess.PIPE) + + try: + output, error = process.communicate(timeout=2) + if 'arcus is return to initial position' in output.decode('utf-8'): + self.enable_bt_and_change_background_to_gray() + + break + elif 'No arcus devices' in output.decode('utf-8') or 'Cannot connect Arcus device' in output.decode('utf-8'): + self.enable_bt_and_change_background_to_gray() + + break + elif 'arcus is still returning' in output.decode('utf-8'): + pass + except subprocess.TimeoutExpired: + process.kill() + output2, error2 = process.communicate() + if 'Arcus device connected' in output2.decode('utf-8'): + self.enable_bt_and_change_background_to_gray() + + break + elif 'No arcus devices' in output2.decode('utf-8') or 'Cannot connect Arcus device' in output2.decode('utf-8'): + self.enable_bt_and_change_background_to_gray() + + break + + def enable_bt_and_change_background_to_gray(self): + self.disable_bt(False) + + # 当操作成功后,所有按钮都变为初始颜色:灰色 + self.change_widget_background_color(self.image_mode_exposureTime_bt, 'gray') + self.change_widget_background_color(self.image_mode_focus_bt, 'gray') + self.change_widget_background_color(self.image_mode_dc_bt, 'gray') + self.change_widget_background_color(self.image_mode_record_bt, 'gray') + self.change_widget_background_color(self.save_bt, 'gray') + + # 保存影像数据 + def savedata(self): + self.disable_bt(True) # 因为保存影像所需时间较多,所以需要将此行代码放在最前面 + + # 保存路径 + # filename = "%s%s%s" % (re.sub('/', '\\\\', self.config_file_object.image_dir), '\\', self.config_file_object.default_image_name) + filename, file_number = return_file_path([], self.config_file_object.image_dir, + self.config_file_object.default_image_name) + + # 保存影像和头文件 + imagefile = "%s%s%s" % (os.getcwd(), '\\', 'corning410_test') + shutil.copyfile(imagefile, filename) + shutil.copyfile("%s%s" % (imagefile, '.hdr'), "%s%s" % (filename, '.hdr')) + + self.file_number_label.setText(str(file_number)) + + # 将自动曝光返回值写入到界面中的QLineEdit和self.config对象中 + def post_auto_expose(self, result): + ''' + :param result: return cam.get_exposure(), cam.get_gain(), cls.autoexposure_feedback + :return: + ''' + try: + # 将自动曝光得到的结果显示到界面(QLineEdit) + self.exposure_time_le.setText(str(result[0])) + + # 为了防止后面的信号执行延迟;如果延迟,设置曝光时间就会设置为self.config.exposure_time的旧值 + self.config_file_object.exposure_time = result[0] + self.config_file_object.gain = result[1] + + try: + # 将自动曝光值保存到配置文件中 + self.config_file_object.image_signal.emit({'exposure_time': result[0], 'gain': result[1]}) + except: + traceback.print_exc() + + + self.image_camera_operation.set_exposure_gain_framerate(camera) + + if result[2] == 1: + self.x = MessageBox('光线不足,曝光时间已设置为最大!') + self.x.exec() + self.image_camera_operation.autoexposure_feedback = 0 + except: + traceback.print_exc() + + def closeEvent(self, a0: QtGui.QCloseEvent): + camera.stop_acquisition() + + +# 光谱窗口 +class SpectralWindow(QDialog, Ui_spectral_Window_phone): + # 信号必须定义为类属性,不能放在__init__方法里 + auto_expose_signal = pyqtSignal(int) + progress_bar_signal = pyqtSignal(int) + plot_spectral_signal = pyqtSignal() + save_spectral_signal = pyqtSignal(int) + operate_success_signal = pyqtSignal() + + def __init__(self, parent=None): + super(SpectralWindow, self).__init__(parent) + self.setupUi(self) + self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + self.setWindowModality(Qt.ApplicationModal) # 阻塞此窗口:此行代码必须放在show()函数之前 + + # 建立进程池 + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + # 配置文件读取和写入类,配置文件读写和界面分离 + # 1、采集数据需要的帧率、曝光、帧数、文件名等等都由此类从文件中读取 + # 2、并保存在此类中 + self.config_file_object = ConfigFile() + + # 暗电流/白板 计时 + self.dc_time = time.time() # 用于暗电流计时(从采集成功后那一刻开始) + self.dc_timer = QTimer(self) + self.dc_timer.timeout.connect(self.dc_timer_slot) + + self.wb_time = time.time() # 用于暗电流计时(从采集成功后那一刻开始) + self.wb_timer = QTimer(self) + self.wb_timer.timeout.connect(self.wb_timer_slot) + + self.progressBar.setMaximum(self.config_file_object.framenumber_average) + self.progressBar.setValue(0) + + # log + self.logger = logging.getLogger('root.spectral') + if not os.path.exists(self.config_file_object.log_dir + '//spectral_operate.log'): + with open(self.config_file_object.log_dir + '//spectral_operate.log', 'w') as f: + pass + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + spectral_operate_file_handler = logging.FileHandler(self.config_file_object.log_dir + "//spectral_operate.log") # 输出到文件 + spectral_operate_file_handler.setLevel(logging.INFO) + spectral_operate_file_handler.setFormatter(formatter) + self.logger.addHandler(spectral_operate_file_handler) + + # 在窗口中显示串口接收的温度/湿度 + serial_port.serial_signal.connect(self.update_temperature) + self.hpi_temperature = None # 暂时保存温度,当保存光谱文件时会用到 + + # 初始化值 + self.filename_le.setText(self.config_file_object.default_spectral_name) + self.spectral_number_le.setText(str(self.config_file_object.spectral_number)) + self.framenumber_average_le.setText(str(self.config_file_object.framenumber_average)) + self.autoexposure_le.setText(str(self.config_file_object.exposure_time_spectral)) + + # 光谱显示控件 + # self.spectralFigure = MatplotlibSpectralViewer(xlabel='Wavelength (nm)', ylabel='reflectance') + self.spectralFigure = QtSpectralViewer(ylabel_and_range='dn') + self.spe_glo.addWidget(self.spectralFigure) + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + self.filename_le.editingFinished.connect(self.onchange) + my_regex1 = QRegExp("[a-zA-Z0-9]*") + my_validator1 = QRegExpValidator(my_regex1, self.filename_le) + self.filename_le.setValidator(my_validator1) + + self.autoexposure_le.editingFinished.connect(self.onchange) + my_regex2 = QRegExp("[0-9]*") + my_validator2 = QRegExpValidator(my_regex2, self.autoexposure_le) + self.autoexposure_le.setValidator(my_validator2) + + self.spectral_number_le.editingFinished.connect(self.onchange) + self.framenumber_average_le.editingFinished.connect(self.onchange) + my_regex3 = QRegExp("[0-9]*") + my_validator3 = QRegExpValidator(my_regex2, self.autoexposure_le) + self.spectral_number_le.setValidator(my_validator2) + self.framenumber_average_le.setValidator(my_validator2) + + # 数据采集保存类,采集数据并将数据保存在此类中,数据采集和界面分离 + self.spectral_camera_operation = SpectralCameraOperation(self.hpi_temperature, self.config_file_object, self.progress_bar_signal, + self.plot_spectral_signal, self.save_spectral_signal, + self.auto_expose_signal, self.operate_success_signal) + + # 当配置文件读取完成后,根据读取的配置文件设置相机曝光、帧率 + self.spectral_camera_operation.set_exposure_gain_framerate(camera) + + # 光谱仪状态 + system_setting.camera_status_signal.connect(self.test_imager_status) + + # 操作光谱仪 + self.state = 0 # 光谱仪操作状态:曝光=1;暗电流=3;白板=5 → 所以只有state==9时才能开始采集光谱 + + self.auto_expose_signal.connect(self.auto_expose_signal_slot) + self.progress_bar_signal.connect(self.progress_bar_signal_slot) + self.plot_spectral_signal.connect(self.plot_spectral_signal_slot) + self.save_spectral_signal.connect(self.save_spectral2) + self.operate_success_signal.connect(self.operate_success) + + self.spectral_mode_autoexposure_bt.clicked.connect(self.run) + self.spectral_mode_dc_bt.clicked.connect(self.run) + self.spectral_mode_wb_bt.clicked.connect(self.run) + self.spectral_mode_record_bt.clicked.connect(self.run) + + self.core_operation() + + def core_operation(self): + worker = Worker(self.spectral_camera_operation.start_AcquireData, camera) + self.threadpool.start(worker) + + # 将自动曝光返回值写入到界面中的QLineEdit和self.config_file_object对象中 + def auto_expose_signal_slot(self, x): + ''' + 自动曝光完成后,会通过信号发送自动曝光获得的曝光时间,将此时间写入到界面中 + :param x: + :return: + ''' + self.autoexposure_le.setText(str(x)) + + self.config_file_object.spectral_signal.emit({'exposure_time_spectral': x}) + + def progress_bar_signal_slot(self, x): + self.progressBar.setValue(x) + + def plot_spectral_signal_slot(self): + # 画出光谱 + if self.data_type_comboBox.currentText() == 'DN': + self.spectralFigure.set_y_range(ylabel_and_range='dn') + self.spectralFigure.plot_wrap(self.spectral_camera_operation.spectral_dn_to_display[:, 0], + self.spectral_camera_operation.spectral_dn_to_display[:, 1]) + if self.data_type_comboBox.currentText() == 'Rad': + self.spectralFigure.set_y_range(ylabel_and_range='radiance') + self.spectralFigure.plot_wrap(self.spectral_camera_operation.spectral_rad_to_display[:, 0], + self.spectral_camera_operation.spectral_rad_to_display[:, 1]) + if self.data_type_comboBox.currentText() == 'Ref': + if self.spectral_camera_operation.spectral_wb is None: + self.data_type_comboBox.setCurrentIndex(0) + else: + self.spectralFigure.set_y_range(ylabel_and_range='reflectance') + self.spectralFigure.plot_wrap(self.spectral_camera_operation.spectral_ref_to_display[:, 0], + self.spectral_camera_operation.spectral_ref_to_display[:, 1]) + + def run(self): + self.qt_sender = self.sender().objectName() + + # 操作状态显示 + if self.qt_sender == 'spectral_mode_autoexposure_bt': + print('SpectralWindow采集曝光') + + self.logger.info('曝光...') + + self.state = 1 + + self.spectral_camera_operation.auto_exposure_bool = True + + self.change_widget_background_color(self.spectral_mode_autoexposure_bt, 'red') + self.disable_bt_le(True) + elif self.qt_sender == 'spectral_mode_dc_bt': + try: + if self.state == 0: + self.x = MessageBox('请先曝光!') + self.x.exec() + elif self.state == 1 or self.state == 4 or self.state == 9: + self.x = MessageBox('请先确认光纤盖已安装!') + self.x.exec() + + self.logger.info('采集暗电流...') + self.state = 4 + + # 暗电流计时 + self.dc_time = time.time() + self.dc_timer.start(2000) + + self.spectral_camera_operation.image_dc_bool = True + + self.change_widget_background_color(self.spectral_mode_dc_bt, 'red') + self.disable_bt_le(True) + except: + traceback.print_exc() + elif self.qt_sender == 'spectral_mode_wb_bt': + if self.state == 0: + self.x = MessageBox('请先曝光+暗电流!') + self.x.exec() + elif self.state == 1: + self.x = MessageBox('请先采集暗电流!') + self.x.exec() + elif self.state == 4 or self.state == 9: + self.logger.info('采集白板...') + self.state = 9 + + # 白板计时 + self.wb_time = time.time() + self.wb_timer.start(2000) + + self.spectral_camera_operation.spectral_wb_bool = True + self.data_type_comboBox.setCurrentIndex(1) + + self.change_widget_background_color(self.spectral_mode_wb_bt, 'red') + self.disable_bt_le(True) + elif self.qt_sender == 'spectral_mode_record_bt': + if self.state == 0: + self.x = MessageBox('请先曝光+暗电流+白板') + self.x.exec() + elif self.state == 1: + self.x = MessageBox('请先暗电流+白板') + self.x.exec() + elif self.state == 4: + self.x = MessageBox('请先白板') + self.x.exec() + elif self.state == 9: + self.logger.info('采集光谱...') + + self.spectral_camera_operation.save_bool = True + + self.change_widget_background_color(self.spectral_mode_record_bt, 'red') + self.disable_bt_le(True) + + def save_spectral2(self, x): + print('保存光谱:', x) + # 保存光谱 + filename_dn, file_number_dn = return_file_path([], self.config_file_object.spectral_dir, + self.config_file_object.default_spectral_name + '_dn', + model='spectral') + filename_rad, file_number_rad = return_file_path([], self.config_file_object.spectral_dir, + self.config_file_object.default_spectral_name + '_rad', + model='spectral') + filename_ref, file_number_ref = return_file_path([], self.config_file_object.spectral_dir, + self.config_file_object.default_spectral_name + '_ref', + model='spectral') + # print(filename_ref) + + header_dn = self.get_spectral_metadata('DN') + header_rad = self.get_spectral_metadata('RAD') + header_ref = self.get_spectral_metadata('REF') + + np.savetxt(filename_dn, self.spectral_camera_operation.spectral_dn[:, [0, x]], fmt='%f', header=header_dn) + np.savetxt(filename_rad, self.spectral_camera_operation.spectral_rad[:, [0, x]], fmt='%f', header=header_rad) + np.savetxt(filename_ref, self.spectral_camera_operation.spectral_ref[:, [0, x]], fmt='%f', header=header_ref) + + self.file_number_label.setText(str(file_number_dn + 1)) + + def operate_success(self): + # 操作状态显示 + if self.qt_sender == 'spectral_mode_autoexposure_bt': + self.logger.info('曝光成功!') + elif self.qt_sender == 'spectral_mode_dc_bt': + self.logger.info('采集暗电流成功!') + elif self.qt_sender == 'spectral_mode_wb_bt': + self.logger.info('采集白板成功!') + elif self.qt_sender == 'spectral_mode_align_bt': + self.logger.info('align successfully!') + elif self.qt_sender == 'spectral_mode_record_bt': + self.logger.info('采集光谱成功!') + + self.disable_bt_le(False) + + # 当操作成功后,所有按钮都变为初始颜色:灰色 + self.change_widget_background_color(self.spectral_mode_autoexposure_bt, 'gray') + self.change_widget_background_color(self.spectral_mode_dc_bt, 'gray') + self.change_widget_background_color(self.spectral_mode_wb_bt, 'gray') + self.change_widget_background_color(self.spectral_mode_record_bt, 'gray') + + def disable_bt_le(self, bool): + self.spectral_mode_autoexposure_bt.setDisabled(bool) + self.spectral_mode_dc_bt.setDisabled(bool) + self.spectral_mode_wb_bt.setDisabled(bool) + self.spectral_mode_record_bt.setDisabled(bool) + + self.spectral_number_le.setDisabled(bool) + self.framenumber_average_le.setDisabled(bool) + self.autoexposure_le.setDisabled(bool) + self.filename_le.setDisabled(bool) + + def closeEvent(self, a0: QtGui.QCloseEvent): + camera.stop_acquisition() + + # 改变按钮三态中普通态的背景颜色 + def change_widget_background_color(self, qt_widget, color): + pattern = re.compile('background-color(.*)(normal\*/)') + old_style_sheet = qt_widget.styleSheet() + + if color == 'red': + new_style_sheet = re.sub(pattern, r'background-color:rgb(255 , 0 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'green': + new_style_sheet = re.sub(pattern, r'background-color:rgb(0 , 255 , 0);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + elif color == 'gray': + new_style_sheet = re.sub(pattern, r'background-color:rgb(225 , 225 , 225);/*normal*/', old_style_sheet) + qt_widget.setStyleSheet(new_style_sheet) + + def dc_timer_slot(self): + now = time.time() + x = now - self.dc_time + self.dc_timer_label.setText(str(int(x)) + 's') + + def wb_timer_slot(self): + now = time.time() + x = now - self.wb_time + self.wb_timer_label.setText(str(int(x)) + 's') + + def get_spectral_metadata(self, data_type_str): + + record_time = "%s%s" % ('RecordTime = ', str(datetime.datetime.now())) + SN = 'SN = 0001' + exposure_time = "%s%s" % ('ExposureTime = ', str(camera.get_exposure())) + data_type = "%s%s" % ('DataType = ', data_type_str) + sensor_temperature = "%s%s" % ('sensor_temperature = ', str(camera.get_temp())) + hpi_temperature = "%s%s" % ('hpi_temperature = ', str(self.hpi_temperature)) + + header = '%s%s%s%s%s%s%s%s%s%s%s' % ( + record_time, '\n', SN, '\n', exposure_time, '\n', data_type, '\n', sensor_temperature, '\n', hpi_temperature) + return header + + def update_temperature(self, data): + try: + self.hpi_temperature = data[0] + + self.t_label.setText('温度:' + data[0]) + self.hum_label.setText('湿度:' + data[1]) + + self.change_widget_background_color(self.t_label, 'green') + self.change_widget_background_color(self.hum_label, 'green') + except: + traceback.print_exc() + print('有问题') + self.t_label.setVisible(False) + self.hum_label.setVisible(False) + self.t_label.setText('温度:无数据') + self.hum_label.setText('湿度:无数据') + + # 手动改变窗口中的值,然后将值写入spectral_camera_operation类对应的变量中 + def onchange(self): + try: + if self.sender().objectName() == 'autoexposure_le': + self.state = 1 # 手动改变曝光时间后,需要强制让用户重新采集暗电流和白板 + + exposure_time_tmp = int(float(self.autoexposure_le.text())) + + self.config_file_object.spectral_signal.emit({'exposure_time_spectral': exposure_time_tmp}) + + camera.set_exposure(exposure_time_tmp) # 曝光时间单位为微秒,1s共有1000000微秒 + # camera.set_gain(int(float(self.config_file_object.gain))) # int('0.0')会报错,int(float('0.0'))不会报错 + + self.logger.info('手动改变曝光时间!') + elif self.sender().objectName() == 'framenumber_average_le': + self.x = MessageBox('请重新打开光谱模式!') + self.x.exec() + framenumber_average_tmp = int(float(self.framenumber_average_le.text())) + + self.config_file_object.spectral_signal.emit({'framenumber_average': framenumber_average_tmp}) + + self.progressBar.setMaximum(framenumber_average_tmp) + # self.progressBar.setValue(0) + + self.spectral_camera_operation.create_image_container(framenumber_average_tmp) + + self.logger.info('手动改变每条光谱的平均帧数!') + elif self.sender().objectName() == 'spectral_number_le': + spectral_number_tmp = int(float(self.spectral_number_le.text())) + + self.config_file_object.spectral_signal.emit({'spectral_number': spectral_number_tmp}) + + self.spectral_camera_operation.create_spectral_container(spectral_number_tmp) + + self.logger.info('手动改变保存的光谱数!') + elif self.sender().objectName() == 'filename_le': + filename = self.filename_le.text() + + if filename != '': + self.config_file_object.spectral_signal.emit({'default_spectral_name': filename}) + + self.logger.info('改变光谱文件名!') + except: + traceback.print_exc() + + def test_imager_status(self, imager_status): + if imager_status == 1000: # 相机打开成功 + # print('相机打开成功!') + + try: + temperature = camera.get_temp() + except Exception: + temperature = None + + self.camera_status_label.setText('光谱仪:' + str(temperature)) + self.change_widget_background_color(self.camera_status_label, 'green') + elif imager_status == 1001: + print('相机打开时出现不是ximea错误的未知错误!') + elif imager_status == 1: + # print('相机已经断开连接!请重新打开软件尝试连接相机!') + + self.camera_status_label.setText('光谱仪:断开连接') + self.change_widget_background_color(self.camera_status_label, 'red') + + self.setEnabled(False) + self.close() + elif imager_status == 12: + pass + elif imager_status == 41: + pass + elif imager_status == 56: + print('没有检测到光谱仪!') + elif imager_status == 103: + pass + + +# 影像模式类:相关的函数和变量 +class CameraOperation(object): + def __init__(self, hpi_temperature, config_file_object): + self.hpi_temperature = hpi_temperature + self.config_file_object = config_file_object + self.record_time_for_plot = 0 # 用于边采集边在页面中刷新,用于确定该显示多少帧了;如何确定该显示多少帧:self.record_time_for_plot * 帧率 + + self.get_wavelength_object = GetWavelength(self.config_file_object, self.hpi_temperature) + + # 转辐亮度 + self.rad_or_not = False + if self.config_file_object.binning == 1: + # self.img_gain = get_resource_path('./data/lens_bin1_gain_SN0031') + self.img_gain = get_resource_path('./data/' + self.config_file_object.calibration_file_name_image) + self.cal_it = self.config_file_object.calibration_file_it_image + elif self.config_file_object.binning == 2: + # self.img_gain = get_resource_path('./data/lens_bin2_gain_SN0031') + self.img_gain = get_resource_path('./data/' + self.config_file_object.calibration_file_name_image) + self.cal_it = self.config_file_object.calibration_file_it_image + _, _, self.gainTmp = ImageReaderWriter.read_img(self.img_gain) + + self.gainTmp = self.gainTmp.astype(np.float32) + self.target_it = None + self.gain_scale = None + + # + self.arcus_reverse_while_record = False + self.record_rad_bool = True # True → 采集rad影像,False → 采集dn影像 + + # 开始采集数据 + self.image_dc = None # 此变量用于存储采集到的暗电流影像 + self.focus = True # 用于停止调焦 + self.record = True # 用于停止采集 + self.img_datatype = 2 # 在头文件中确定影像数据类型:Integer(np.int16) → A 16-bit signed integer ranging from -32,768 to +32,767. + + self.autoexposure_feedback = 0 # 指示:自动曝光所得到的shutter值是否为最大;如果为最大→值设置为1 + + # 创建rgb数据,用于在界面中显示 + self.create_rgb() + + def create_rgb(self): + self.rgb = np.ones((3, int(self.config_file_object.frame_number), self.config_file_object.end_column - self.config_file_object.start_column)) + + # 手动改变界面上的曝光值和gain值后,设置相机的曝光值和gain值所用 + def set_exposure_gain_framerate(self, cam): + # settings,cam.set_param("exposure",10000) + cam.set_framerate(self.config_file_object.framerate) + cam.set_exposure(self.config_file_object.exposure_time) # 曝光时间单位为微秒,1s共有1000000微秒 + cam.set_gain(self.config_file_object.gain) #int('0.0')会报错,int(float('0.0'))不会报错 + + def start_AcquireData(self, cam, qt_sender, plot_signal=None): # qt_sender是指qt窗口中事件的发生者 + ''' + :param cam: 实例化的相机句柄 + :param qt_sender: 调用本方法时,点击的界面上的按钮名; + :param plot_signal: + :return: + ''' + # 创建img = xiapi.Image()前需要设置一系列img参数,例如:格式、位深度、 + # 如果格式设置为XI_RAW8,image_raw_numpy.dtype -> dtype('uint8'), uint8 + # 如果格式设置为XI_RAW16,image_raw_numpy.dtype -> dtype('= 4090: + cam.set_exposure(int(0.9 * cam.get_exposure())) + + cam.start_acquisition() + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + image_raw_numpy = img.get_image_data_numpy() + + # 当关闭调焦后,再次打开调焦功能需要将cls.focus的值从False变为True + if not self.focus: + self.focus = True + + cam.start_acquisition() + + while self.focus: + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + self.image_container = image_raw_numpy[ + self.config_file_object.start_row:self.config_file_object.end_row, + self.config_file_object.start_column:self.config_file_object.end_column] + + if plot_signal is not None: + plot_signal.emit() + + # 调焦完成之后,将相机的曝光和帧率设置为配置文件中的值 + self.set_exposure_gain_framerate(cam) + + if qt_sender == 'image_mode_exposureTime_bt': + print('start_AcquireData--自动曝光运行开始') + + # 设置自动曝光的CCD--roi + cam.set_framerate(self.config_file_object.framerate) + + # cam.set_aeag_roi_offset_x(self.config_file_object.start_column) + # cam.set_aeag_roi_offset_y(self.config_file_object.start_row) + # cam.set_aeag_roi_height(self.config_file_object.end_row - self.config_file_object.start_row) + # cam.set_aeag_roi_width(self.config_file_object.end_column - self.config_file_object.start_column) + + # cam.set_exp_priority(1) # Exposure priority (0.8 - exposure 80%, gain 20%).XI_PRM_EXP_PRIORITY + # cam.set_ae_max_limit(24000) # Maximum time (us) used for exposure in AEAG procedureXI_PRM_AE_MAX_LIMIT + # cam.set_ag_max_limit(12) + # cam.set_aeag_level(50) # Average intensity of output signal AEAG should achieve(in %)XI_PRM_AEAG_LEVEL + # 还有两个不知怎么用的参数:XI_PRM_GAIN_SELECTOR or "gain_selector"和XI_PRM_SHUTTER_TYPE or "shutter_type" + + # 使用相机自动曝光功能得到初始曝光值 + cam.enable_aeag() # 开启自动曝光 + cam.start_acquisition() + for i in range(10): + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + cam.disable_aeag() # 关闭自动曝光 + + # 根据自动曝光所得初始曝光值,循环迭代获取不过曝的曝光值 + image_raw_numpy = img.get_image_data_numpy() + while image_raw_numpy.max() >= 2730: + cam.set_exposure(int(0.9 * cam.get_exposure())) + + cam.start_acquisition() + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + image_raw_numpy = img.get_image_data_numpy() + + # 如果因为光线不足曝光值达到了最大,就将曝光反馈变量设置为1 + if cam.get_exposure() > int(1 / self.config_file_object.framerate * 10**6): + cam.set_exposure(int(1 / self.config_file_object.framerate * 10**6)) + self.autoexposure_feedback = 1 + else: + cam.set_exposure(cam.get_exposure()) + + # 计算gain + self.target_it = cam.get_exposure() + self.gain_scale = self.cal_it / self.target_it + self.gain = self.gainTmp * self.gain_scale + + print('start_AcquireData--自动曝光运行结束') + + # 如果点击“暗电流”按钮,采集并保存暗电流影像到image_dc + if qt_sender == 'image_mode_dc_bt': + framenumber = 10 + image_container = np.empty(( + self.config_file_object.end_row - self.config_file_object.start_row, framenumber, + self.config_file_object.end_column - self.config_file_object.start_column)) + + cam.start_acquisition() + print('Starting data acquisition...') + for i in range(framenumber): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + image_container[:, i, :] = image_raw_numpy[ + self.config_file_object.start_row:self.config_file_object.end_row, + self.config_file_object.start_column:self.config_file_object.end_column] + + image_container = image_container.mean(axis=1) + + self.image_dc = image_container + + # 如果点击“采集”按钮,自动去除暗电流,并且转化成反射率 + if qt_sender == 'image_mode_record_bt': + self.record_time_for_plot = 0 # 每次点击采集按钮都将此变量设置为1,用于正常边采集影像边在界面中显示影像 + + frameCount = 1 # 统计采集的帧数,用于停止采集使用 + + # 当停止采集后,再次开始采集需要将cls.record的值从False变为True + if not self.record: + self.record = True + + # 启动马达,可能造成死循环 + self.arcus_start() + + # 开始采集数据 并且 将数据写入到硬盘中 + cam.start_acquisition() + with open('corning410_test', 'wb') as f: + + print('Starting data acquisition...') + startTime = datetime.datetime.now() + + while self.record: + cam.get_image(img) # get data and pass them from camera to img + # image_raw_numpy.dtype -> dtype('修正 + :return: 返回波长温度漂移修正后的波长 + ''' + # # 计算波长:Serial number = 008 + # wavelength = np.empty(639 - 339) + # for i in range(339, 639): + # wavelength[i - 339] = i * 1.999564 - 279.893 + + # wavelength = np.array(wavelength_tmp) + + wavelength_file_name = get_resource_path('./data/' + self.config_file_object.wavelength_file_name) + wavelength = np.loadtxt(wavelength_file_name) + + # 处理波长温漂 + if self.hpi_temperature is None or self.hpi_temperature < 36: + pass + elif 36 < self.hpi_temperature <= 43: + wavelength = wavelength + 2 + elif 43 < self.hpi_temperature <= 51: + wavelength = wavelength + 4 + elif 51 < self.hpi_temperature: + wavelength = wavelength + 6 + + # 波长bin + if self.config_file_object.binning != 1: + wavelength_bin = np.zeros(int(300 / self.config_file_object.binning)) + k = np.arange(300)[0::self.config_file_object.binning] + for i in range(wavelength_bin.shape[0]): + for j in range(self.config_file_object.binning): + wavelength_bin[i] += wavelength[k[i] + j] + wavelength_bin[i] = wavelength_bin[i] / self.config_file_object.binning + else: + wavelength_bin = wavelength + + if model == 'str': + # 清洗波段数据 + wavelength_str = str(wavelength_bin).replace('[', '').replace(']', '').replace('\n', '') + wavelength_str = re.sub(' +', ' ', wavelength_str) + wavelength_str = re.sub(' +$', '', wavelength_str) # 去除末尾的空格 + wavelength_str = re.sub(' ', ', ', wavelength_str) + + return wavelength_str + elif model == 'array': + return wavelength_bin + + +# 光谱模式类:相关的函数和变量 +class SpectralCameraOperation(object): + def __init__(self, hpi_temperature, config_file_object, progress_bar_signal, plot_signals, save_spectral_signal, + auto_expose_signal, operate_success_signal): + self.hpi_temperature = hpi_temperature + self.config_file_object = config_file_object + self.progress_bar_signal = progress_bar_signal + self.plot_signals = plot_signals + self.save_spectral_signal = save_spectral_signal + self.auto_expose_signal = auto_expose_signal + self.operate_success_signal = operate_success_signal + + self.get_wavelength_object = GetWavelength(self.config_file_object, self.hpi_temperature) + + # 建立进程池 + self.threadpool = QThreadPool() + + # 转辐亮度 + self.img_gain = get_resource_path('./data/' + self.config_file_object.calibration_file_name_spectral) + self.cal_it = self.config_file_object.calibration_file_it_spectral + + # self.img_gain = get_resource_path('./data/optical_fiber_bin1_gain_SN0031') + # self.cal_it = 42300 + + self.rad_or_not = False # 判断是否通过辐亮度转换成反射率 + _, _, self.gainTmp = ImageReaderWriter.read_img(self.img_gain) + self.gainTmp = self.gainTmp.astype(np.float) + self.gain = self.gainTmp + self.target_it = None + self.gain_scale = None + + # 光谱暂时保存容器 + self.spectral_dn = None + self.spectral_rad = None + self.spectral_ref = None + self.spectral_dn_to_display = None + self.spectral_rad_to_display = None + self.spectral_ref_to_display = None + + # 开始采集数据 + self.create_image_container(self.config_file_object.framenumber_average) + self.create_spectral_container(self.config_file_object.spectral_number) + self.refine_wavelength_wrapper() + + self.image_dc = None + self.spectral_wb = None + # self.image_dc = np.empty((self.config_file_object.end_row - self.config_file_object.start_row, + # self.config_file_object.end_column - self.config_file_object.start_column)).astype( + # np.float) # 此变量用于存储采集到的暗电流,一帧平均得到 + # self.spectral_wb = np.empty((self.config_file_object.end_row - self.config_file_object.start_row, + # self.config_file_object.end_column - self.config_file_object.start_column)).astype( + # np.float) # 此变量用于存储采集到的白板,一帧平均得到 + + self.image_dc_bool = False + self.spectral_wb_bool = False + self.save_bool = False + self.auto_exposure_bool = False + + def create_image_container(self, framenumber_average): + self.image_container = np.empty( + (self.config_file_object.end_row - self.config_file_object.start_row, framenumber_average, + self.config_file_object.end_column - self.config_file_object.start_column)).astype(np.float) + + def create_spectral_container(self, spectral_number): + self.number_of_spectral_to_save = spectral_number + self.number_of_spectral_saving = 1 + + # 用于暂时存储需要保存的光谱 + self.spectral_dn = np.empty((self.config_file_object.end_row - self.config_file_object.start_row, spectral_number + 1)).astype( + np.float) # 此ndarray用于存储采集到的目标物光谱,每一列为一个光谱 + self.spectral_rad = np.empty((self.config_file_object.end_row - self.config_file_object.start_row, spectral_number + 1)).astype( + np.float) # 此ndarray用于存储采集到的目标物光谱,每一列为一个光谱 + self.spectral_ref = np.empty((self.config_file_object.end_row - self.config_file_object.start_row, spectral_number + 1)).astype( + np.float) # 此ndarray用于存储采集到的目标物光谱,每一列为一个光谱 + + # 用于存储显示所用光谱 + self.spectral_dn_to_display = np.empty( + (self.config_file_object.end_row - self.config_file_object.start_row, 2)).astype( + np.float) + self.spectral_rad_to_display = np.empty( + (self.config_file_object.end_row - self.config_file_object.start_row, 2)).astype( + np.float) + self.spectral_ref_to_display = np.empty( + (self.config_file_object.end_row - self.config_file_object.start_row, 2)).astype( + np.float) + + # 写入波长信息 + wavelength = self.get_wavelength_object.wave(model='array') + + self.spectral_dn[:, 0] = wavelength + self.spectral_rad[:, 0] = wavelength + self.spectral_ref[:, 0] = wavelength + self.spectral_dn_to_display[:, 0] = wavelength + self.spectral_rad_to_display[:, 0] = wavelength + self.spectral_ref_to_display[:, 0] = wavelength + + def refine_wavelength_wrapper(self): + worker = Worker(self.refine_wavelength) + self.threadpool.start(worker) + + def refine_wavelength(self): + ''' + 1:调用时机:当调用了方法(create_spectral_container),创建了光谱容器后 + 2:本函数作用:调用self.wave()进行波长温度漂移校正 + :return: + ''' + + while True: + wavelength = self.get_wavelength_object.wave(model='array') + + if self.spectral_dn is not None: + self.spectral_dn[:, 0] = wavelength + self.spectral_rad[:, 0] = wavelength + self.spectral_ref[:, 0] = wavelength + self.spectral_dn_to_display[:, 0] = wavelength + self.spectral_rad_to_display[:, 0] = wavelength + self.spectral_ref_to_display[:, 0] = wavelength + + time.sleep(2) + + def start_AcquireData(self, cam): + cam.set_imgdataformat('XI_RAW16') + # create instance of Image to store image data and metadata + img = xiapi.Image() + cam.start_acquisition() + while True: + if self.auto_exposure_bool: # 自动曝光 + # cam.set_aeag_roi_offset_x(self.config_file_object.start_column) + # cam.set_aeag_roi_offset_y(self.config_file_object.start_row) + # cam.set_aeag_roi_height(self.config_file_object.end_row - self.config_file_object.start_row) + # cam.set_aeag_roi_width(self.config_file_object.end_column - self.config_file_object.start_column) + + cam.enable_aeag() + for i in range(10): + cam.get_image(img) # get data and pass them from camera to img + cam.disable_aeag() + + self.auto_expose_signal.emit(cam.get_exposure()) + + # 计算gain + self.target_it = cam.get_exposure() + self.gain_scale = self.cal_it / self.target_it + self.gain = self.gainTmp * self.gain_scale # 这行代码有问题:每曝光一次,self.gain就变小一次 + + self.auto_exposure_bool = False # 执行一次自动曝光后,将此变量赋值False,以便下一次循环时,不执行自动曝光 + self.operate_success_signal.emit() + else: # 正常采集光谱 + # 采集帧流 + for i in range(self.config_file_object.framenumber_average): + cam.get_image(img) # get data and pass them from camera to img + image_raw_numpy = img.get_image_data_numpy() + self.image_container[:, i, :] = image_raw_numpy[ + self.config_file_object.start_row:self.config_file_object.end_row, + self.config_file_object.start_column:self.config_file_object.end_column] + self.progress_bar_signal.emit(i+1) # 发射进度条信号:指示采集到了第几帧 + + # 判断是否采集暗电流/白板 + if self.image_dc_bool: + self.image_dc = self.image_container.mean(axis=1) + + self.operate_success_signal.emit() + self.image_dc_bool = False # 采集完成后,赋值False,以便下一次采集暗电流 + + if self.spectral_wb_bool: + if self.image_dc is not None: + self.spectral_wb = self.image_container.mean(axis=1) - self.image_dc + else: + self.spectral_wb = self.image_container.mean(axis=1) + + self.operate_success_signal.emit() + self.spectral_wb_bool = False # 采集完成后,赋值False,以便下一次采集白板 + + # 判断是否扣除暗电流 + if self.image_dc is not None: + self.one_frame = self.image_container.mean(axis=1) - self.image_dc + else: + self.one_frame = self.image_container.mean(axis=1) + + # 当不采集暗电流/白板时,才能采集和绘制光谱 + if not self.image_dc_bool and not self.spectral_wb_bool: + if self.save_bool: # 绘制 + 保存光谱 + # 采集dn光谱 + self.spectral_dn[:, self.number_of_spectral_saving] = self.one_frame.mean(axis=1) + self.spectral_dn_to_display[:, 1] = self.one_frame.mean(axis=1) # 用于显示 + + # 采集rad光谱 + self.spectral_rad[:, self.number_of_spectral_saving] = (self.one_frame * self.gain[:, 0, :]).mean(axis=1) + self.spectral_rad_to_display[:, 1] = (self.one_frame * self.gain[:, 0, :]).mean(axis=1) # 用于显示 + + # 采集ref光谱 + if self.rad_or_not: # 判断是否通过辐亮度转换成反射率 + self.spectral_ref[:, self.number_of_spectral_saving] = ((self.one_frame * self.gain[:, 0, :]) / ( + self.spectral_wb * self.gain[:, 0, :])).mean(axis=1) + self.spectral_ref_to_display[:, 1] = ((self.one_frame * self.gain[:, 0, :]) / ( + self.spectral_wb * self.gain[:, 0, :])).mean(axis=1) # 用于显示 + else: + self.spectral_ref[:, self.number_of_spectral_saving] = (self.one_frame / self.spectral_wb).mean(axis=1) + self.spectral_ref_to_display[:, 1] = (self.one_frame / self.spectral_wb).mean(axis=1) # 用于显示 + + # 判断是否采集完成 + if self.number_of_spectral_saving == self.number_of_spectral_to_save: + self.save_spectral_signal.emit(self.number_of_spectral_saving) # 保存最后一条光谱 + + self.number_of_spectral_saving = 1 + self.save_bool = False + self.operate_success_signal.emit() + else: + self.save_spectral_signal.emit(self.number_of_spectral_saving) # 保存除最后一条的所有光谱 + self.number_of_spectral_saving += 1 + else: # 当仅仅绘制光谱,不保存光谱 + self.spectral_dn_to_display[:, 1] = self.one_frame.mean(axis=1) + self.spectral_rad_to_display[:, 1] = (self.one_frame * self.gain[:, 0, :]).mean(axis=1) + if self.spectral_wb is not None: # 转反射率 + self.spectral_ref_to_display[:, 1] = (self.one_frame / self.spectral_wb).mean(axis=1) + + self.plot_signals.emit() # 发射画图信号 + + # 手动改变界面上的曝光值和gain值后,设置相机的曝光值和gain值所用 + def set_exposure_gain_framerate(self, cam): + cam.set_exposure(self.config_file_object.exposure_time_spectral) # 曝光时间单位为微秒,1s共有1000000微秒 + cam.set_framerate(10) + # cam.set_gain(config_file_object.gain) # int('0.0')会报错,int(float('0.0'))不会报错 + + +class SystemSetting(QObject): + # 相机状态信号:ximea定义的错误 + 自己定义的错误 + # 自己定义的错误:1000→相机打开成功;1001→未知错误 + camera_status_signal = pyqtSignal(int) # 信号必须定义为类属性,不能放在__init__方法里 + + def __init__(self): + super(SystemSetting, self).__init__() + + # 建立进程池:https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/ + self.threadpool = QThreadPool() + print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) + + self.cam_is_open = False # 因为程序逻辑,只能放在最前面;self.cam_is_open默认值是False,所以只在打开成功的情况下设置为True + self.cam_status = None # 相机状态信号:ximea定义的错误 + 自己定义的错误 + # 自己定义的错误:1000→相机打开成功;1001→未知错误 + + self.config_file_object = ConfigFile() + self.open_camera() + + self.timer = QTimer(self) + self.timer.timeout.connect(self.test_imager_status) + # self.timer.start(3000) + + self.test_imager_status_wraper() + + def test_imager_status_wraper(self): + # 在新线程中执行相机采集操作,避免相机采集数据时界面卡死 + worker = Worker(self.test_imager_status) + + self.threadpool.start(worker) + + def test_imager_status(self): + while True: + if self.cam_is_open is True: # 只有当相机打开成功 → 不停循环检测相机的状态 + try: + # self.cam.set_imgdataformat('XI_RAW16') # 这行代码在光谱仪在采集数据时,会出现各种错误 + self.cam.get_temp() + except xiapi.Xi_error: + exctype, value = sys.exc_info()[:2] + + if value.status == 1: # 在ximea的API中代表"Invalid handle":相机断开连接 + self.cam_status = 1 + self.camera_status_signal.emit(self.cam_status) + # print('错误代码:', 1, ' → 相机断开连接') + elif value.status == 12: # 在ximea的API中代表"Not supported":当相机正在采集数据时,执行代码cam.set_imgdataformat('XI_RAW16') + # 这代表相机工作正常,不用做出任何反应 + self.cam_status = 12 + self.camera_status_signal.emit(self.cam_status) + # print('相机现在不支持此操作!') + elif value.status == 41: # 在ximea的API中代表"Acquisition already started":相机已经开始采集数据 + self.cam_status = 41 + self.camera_status_signal.emit(self.cam_status) + # print('相机已经开始采集数据!') + elif value.status == 56: # 在ximea的API中代表"No Devices Found":在执行cam.open_device()时,无相机打开 + self.cam_status = 56 + self.camera_status_signal.emit(self.cam_status) + print('错误代码:', 56, ' → 代表无相机') + elif value.status == 103: # 在ximea的API中代表"Wrong parameter type":在没有执行cam.open_device()的情况下,执行了cam.set_imgdataformat('XI_RAW16')会出现此错误 + self.cam_status = 103 + self.camera_status_signal.emit(self.cam_status) + except Exception: + print('未知错误!!!!!!!!!!!!!') + else: + self.cam_status = 1000 + self.camera_status_signal.emit(self.cam_status) + # print('相机打开成功!') + finally: + pass + else: # 如果相机没有打开成功就发射这些信号 + self.camera_status_signal.emit(self.cam_status) + + time.sleep(1) + + # 打开相机 + def open_camera(self): + ''' + 打开相机,将打开相机的状态保存到变量self.cam_status中,然后通过函数test_imager_status中的信号发射出去 + :return: + ''' + try: + # create instance for first connected camera + self.cam = xiapi.Camera() + + # start communication to open specific device, use: cam.open_device_by_SN('41305651') + print('Opening first camera...') + self.cam.open_device() + + # 打开相机后,显示相机信息 + # print('SN: %s' % str(self.cam.get_device_sn(), encoding="utf-8")) + # print('Device name: %s' % str(self.cam.get_device_name(), encoding="utf-8")) + # print('Device name: %s' % str(self.cam.get_device_type(), encoding="utf-8")) + # print('Instance path: %s' % str(self.cam.get_device_inst_path(), encoding="utf-8")) # Returns device instance path in operating system. + # print('Location path: %s' % str(self.cam.get_device_loc_path(), encoding="utf-8")) + # print('Debug level: %s' % self.cam.get_debug_level()) + + # The number of threads per image processor + print('Default number of threads per image processor: %d' % self.cam.get_proc_num_threads()) + self.cam.set_proc_num_threads(8) + print('Current number of threads per image processor: %d' % self.cam.get_proc_num_threads()) + + # 图像水平翻转 + # print('Is horizontal flip enabled? %s' % str(self.cam.is_horizontal_flip())) + + # This mode is supported by selected camera families: CB, MC, MT, MX + self.cam.set_acq_timing_mode('XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + mode_used = self.cam.get_acq_timing_mode() + if mode_used == 'XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT': + print('Mode is XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + else: + print('Mode is not XI_ACQ_TIMING_MODE_FRAME_RATE_LIMIT') + sys.exit() + self.set_binning() + except xiapi.Xi_error: # 如果打开相机失败1 → ,出现错误(ximea错误)--这些错误已经有代码处理 + exctype, value = sys.exc_info()[:2] + + if value.status == 56: # 在ximea的API中代表"No Devices Found":在执行cam.open_device()时,无相机打开 + self.cam_status = 56 + if value.status == 57: # 在ximea的API中代表"Resource (device) or function locked by mutex" + self.cam_status = 57 + else: + print('没有处理的ximea错误??????????????????????????????????错误代码:', value.status) + except Exception: # 如果打开相机失败2 → 出现错误(除了ximea错误意外的错误)--这些错误没有代码处理 + self.camera_status_signal.emit(1001) # 这行代码会在EnterWindow实例化之前执行,所以对EnterWindow没有效果 + self.cam_status = 1001 + # print('相机打开时出现不是ximea错误的未知错误???????????????????????????????????') + else: # 如果打开没有出错 + self.cam_is_open = True # self.cam_is_open默认值是False,所以只在打开成功的情况下设置为True + self.cam_status = 1000 + finally: + pass + + # 设置binning;设置裁剪有效窗口以提高帧率 + def set_binning(self): + self.cam.set_binning_selector('XI_BIN_SELECT_HOST_CPU') # 默认为XI_BIN_SELECT_SENSOR(会报错),不可用:XI_BIN_SELECT_DEVICE_FPGA + self.cam.set_binning_horizontal_mode('XI_BIN_MODE_SUM') + self.cam.set_binning_horizontal(self.config_file_object.binning) + self.cam.set_binning_vertical_mode('XI_BIN_MODE_SUM') + self.cam.set_binning_vertical(self.config_file_object.binning) + + self.cam.set_width(self.config_file_object.effective_window_width) + self.cam.set_offsetX(self.config_file_object.effective_window_offsetx) + + self.cam.set_height(self.config_file_object.effective_window_height) + self.cam.set_offsetY(self.config_file_object.effective_window_offsety) + + # if self.config_file_object.binning == 1: + # # # Serial number = 008 + # # self.cam.set_width(1392) + # # self.cam.set_offsetX(272) + # # + # # self.cam.set_height(302) + # # self.cam.set_offsetY(338) + # + # # # Serial number = 0073 + # # self.cam.set_width(1392) + # # self.cam.set_offsetX(272) + # # + # # self.cam.set_height(302) + # # self.cam.set_offsetY(364) + # + # # # Serial number = 0095 + # # self.cam.set_width(1392) + # # self.cam.set_offsetX(272) + # # + # # self.cam.set_height(302) + # # self.cam.set_offsetY(324) + # + # + # + # # # Serial number = 0031 + # # self.cam.set_width(1392) + # # self.cam.set_offsetX(272) + # # + # # self.cam.set_height(302) + # # self.cam.set_offsetY(406) + # + # # # Serial number = 0099 + # # self.cam.set_width(1392) + # # self.cam.set_offsetX(272) + # # + # # self.cam.set_height(302) + # # self.cam.set_offsetY(354) + # elif self.config_file_object.binning == 2: + # # # Serial number = 008 + # # self.cam.set_width(696) + # # self.cam.set_offsetX(128) + # # + # # self.cam.set_height(151) + # # self.cam.set_offsetY(168) + # + # # # Serial number = 0073 + # # self.cam.set_width(696) + # # self.cam.set_offsetX(128) + # # + # # self.cam.set_height(151) + # # self.cam.set_offsetY(182) + # + # # # Serial number = 0095 + # # self.cam.set_width(696) + # # self.cam.set_offsetX(128) + # # + # # self.cam.set_height(151) + # # self.cam.set_offsetY(162) + # + # # # Serial number = 0031 + # # self.cam.set_width(696) + # # self.cam.set_offsetX(128) + # # + # # self.cam.set_height(151) + # # self.cam.set_offsetY(202) + # + # # # Serial number = 0099 + # # self.cam.set_width(696) + # # self.cam.set_offsetX(128) + # # + # # self.cam.set_height(151) + # # self.cam.set_offsetY(176) + + # 返回打开的相机对象 + def get_cam(self): + return self.cam + + def close_camera(self, cam): + # stop communication + cam.close_device() +# 相机参数设置 + + +if __name__ == '__main__': + app = QApplication(sys.argv) + + # 创建根日志:root + log = Log() + + # 用于获取温度传感器的数据 + serial_port = SerialPort() + + # 相机句柄,全局变量:用于整个程序 + system_setting = SystemSetting() + camera = system_setting.get_cam() + + # 实例化主窗口 + enter_window_instance = EnterWindow(camera) + enter_window_instance.show() + + sys.exit(app.exec_()) diff --git a/record_system_v28/delete.py b/record_system_v28/delete.py new file mode 100644 index 0000000..e12ca46 --- /dev/null +++ b/record_system_v28/delete.py @@ -0,0 +1,63 @@ +from ximea import xiapi +import numpy as np + +cam = xiapi.Camera() +cam.open_device() + + + +# self.cam.set_width(1392) +# cam.set_offsetX(272) +# +# cam.set_height(302) +# cam.set_offsetY(338) + + +# Serial number = 0031 +cam.set_width(1392) +cam.set_offsetX(272) + +cam.set_height(302) +cam.set_offsetY(406) + +framerate=20 + +cam.set_framerate(framerate) + + +# cam.set_aeag_roi_offset_x(self.config_file_object.start_column) +# cam.set_aeag_roi_offset_y(self.config_file_object.start_row) +# cam.set_aeag_roi_height(self.config_file_object.end_row - self.config_file_object.start_row) +# cam.set_aeag_roi_width(self.config_file_object.end_column - self.config_file_object.start_column) + + +img = xiapi.Image() + +# 使用相机自动曝光功能得到初始曝光值 +cam.enable_aeag() # 开启自动曝光 +cam.start_acquisition() +for i in range(10): + cam.get_image(img) # get data and pass them from camera to img +cam.stop_acquisition() +cam.disable_aeag() # 关闭自动曝光 + + +# 根据自动曝光所得初始曝光值,循环迭代获取不过曝的曝光值 +img.get_image_data_numpy() +image_raw_numpy = img.get_image_data_numpy() +while image_raw_numpy.max() >= 2730: + cam.set_exposure(int(0.9 * cam.get_exposure())) + + cam.start_acquisition() + cam.get_image(img) # get data and pass them from camera to img + cam.stop_acquisition() + image_raw_numpy = img.get_image_data_numpy() + +# 如果因为光线不足曝光值达到了最大,就将曝光反馈变量设置为1 +if cam.get_exposure() > int(1 / framerate * 10**6): + cam.set_exposure(int(1 / framerate * 10**6)) + autoexposure_feedback = 1 +else: + cam.set_exposure(cam.get_exposure()) + +haha=cam.get_exposure() diff --git a/record_system_v28/log/corning_config - 20220627.ini b/record_system_v28/log/corning_config - 20220627.ini new file mode 100644 index 0000000..bfe8c28 --- /dev/null +++ b/record_system_v28/log/corning_config - 20220627.ini @@ -0,0 +1,48 @@ +[bin] +binning = 1 +start_column_binning_1 = 12 +end_column_binning_1 = 1376 +start_row_binning_1 = 1 +end_row_binning_1 = 301 +start_column_binning_2 = 13 +end_column_binning_2 = 695 +start_row_binning_2 = 1 +end_row_binning_2 = 151 + +[effective_window] +width_binning_1 = 1392 +offsetx_binning_1 = 272 +height_binning_1 = 302 +offsety_binning_1 = 364 +width_binning_2 = 696 +offsetx_binning_2 = 128 +height_binning_2 = 151 +offsety_binning_2 = 182 + +[calibration_file] +cal_file_name_image_bining_1 = lens_bin1_gain_SN0073 +cal_file_name_image_bining_2 = lens_bin2_gain_SN0073 +cal_file_it_image_bining_1 = 6969 +cal_file_it_image_bining_2 = 1628 +cal_file_name_spectral_bining_1 = optical_fiber_bin1_gain_SN0073 +cal_file_it_spectrl_bining_1 = 42300 + +[wavelength_file_name] +file_name = wavelength0073.txt + +[image_record_param] +image_dir = D:\py_program\corning410\record_system_v28/image +default_image_name = testimage +framerate = 50 +exposure_time = 9367.0 +gain = 0.0 +frame_number = 20 +arcus_speed = 1000 + +[spectral_record_param] +spectral_dir = D:\py_program\corning410\record_system_v28/spectral +default_spectral_name = testspectral +spectral_number = 10 +framenumber_average = 10 +exposure_time_spectral = 69997 + diff --git a/record_system_v28/log/corning_config.ini b/record_system_v28/log/corning_config.ini new file mode 100644 index 0000000..98cf93b --- /dev/null +++ b/record_system_v28/log/corning_config.ini @@ -0,0 +1,48 @@ +[bin] +binning = 1 +start_column_binning_1 = 12 +end_column_binning_1 = 1376 +start_row_binning_1 = 1 +end_row_binning_1 = 301 +start_column_binning_2 = 13 +end_column_binning_2 = 695 +start_row_binning_2 = 1 +end_row_binning_2 = 151 + +[effective_window] +width_binning_1 = 1392 +offsetx_binning_1 = 272 +height_binning_1 = 302 +offsety_binning_1 = 364 +width_binning_2 = 696 +offsetx_binning_2 = 128 +height_binning_2 = 151 +offsety_binning_2 = 182 + +[calibration_file] +cal_file_name_image_bining_1 = lens_bin1_gain_SN0073 +cal_file_name_image_bining_2 = lens_bin2_gain_SN0073 +cal_file_it_image_bining_1 = 6969 +cal_file_it_image_bining_2 = 1628 +cal_file_name_spectral_bining_1 = optical_fiber_bin1_gain_SN0073 +cal_file_it_spectrl_bining_1 = 42300 + +[wavelength_file_name] +file_name = wavelength0073.txt + +[image_record_param] +image_dir = D:\py_program\corning410\record_system_v28/image +default_image_name = 20220627 +framerate = 10 +exposure_time = 23232 +gain = 0.0 +frame_number = 50 +arcus_speed = 800 + +[spectral_record_param] +spectral_dir = D:\py_program\corning410\record_system_v28/spectral +default_spectral_name = testspectral +spectral_number = 10 +framenumber_average = 10 +exposure_time_spectral = 69997 + diff --git a/record_system_v28/ui/__init__.py b/record_system_v28/ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/record_system_v28/ui/enter_window.py b/record_system_v28/ui/enter_window.py new file mode 100644 index 0000000..c84d4c9 --- /dev/null +++ b/record_system_v28/ui/enter_window.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'enter_window.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_enter_Window(object): + def setupUi(self, enter_Window): + enter_Window.setObjectName("enter_Window") + enter_Window.setEnabled(True) + enter_Window.resize(651, 474) + self.centralwidget = QtWidgets.QWidget(enter_Window) + self.centralwidget.setObjectName("centralwidget") + self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) + self.gridLayout.setObjectName("gridLayout") + self.camstatus_label = QtWidgets.QLabel(self.centralwidget) + self.camstatus_label.setEnabled(True) + self.camstatus_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:30pt;\n" +" /*字体颜色为白色*/\n" +" /*color:white;*/\n" +" /*背景颜色*/\n" +" background-color:rgb(225 , 225 , 225);\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}") + self.camstatus_label.setAlignment(QtCore.Qt.AlignCenter) + self.camstatus_label.setObjectName("camstatus_label") + self.gridLayout.addWidget(self.camstatus_label, 2, 0, 1, 1) + self.spectral_mode_bt = QtWidgets.QPushButton(self.centralwidget) + self.spectral_mode_bt.setEnabled(True) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_bt.setSizePolicy(sizePolicy) + self.spectral_mode_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_bt.setObjectName("spectral_mode_bt") + self.gridLayout.addWidget(self.spectral_mode_bt, 1, 0, 1, 1) + self.image_mode_phone_bt = QtWidgets.QPushButton(self.centralwidget) + self.image_mode_phone_bt.setEnabled(True) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_phone_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_phone_bt.setSizePolicy(sizePolicy) + self.image_mode_phone_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_phone_bt.setObjectName("image_mode_phone_bt") + self.gridLayout.addWidget(self.image_mode_phone_bt, 0, 0, 1, 1) + enter_Window.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(enter_Window) + self.menubar.setGeometry(QtCore.QRect(0, 0, 651, 23)) + self.menubar.setObjectName("menubar") + enter_Window.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(enter_Window) + self.statusbar.setObjectName("statusbar") + enter_Window.setStatusBar(self.statusbar) + self.actionwew_e = QtWidgets.QAction(enter_Window) + self.actionwew_e.setObjectName("actionwew_e") + + self.retranslateUi(enter_Window) + QtCore.QMetaObject.connectSlotsByName(enter_Window) + + def retranslateUi(self, enter_Window): + _translate = QtCore.QCoreApplication.translate + enter_Window.setWindowTitle(_translate("enter_Window", "主窗口")) + self.camstatus_label.setText(_translate("enter_Window", "正在打开相机...")) + self.spectral_mode_bt.setText(_translate("enter_Window", "光谱模式")) + self.image_mode_phone_bt.setText(_translate("enter_Window", "影像模式")) + self.actionwew_e.setText(_translate("enter_Window", "wew e")) diff --git a/record_system_v28/ui/enter_window.ui b/record_system_v28/ui/enter_window.ui new file mode 100644 index 0000000..75e1469 --- /dev/null +++ b/record_system_v28/ui/enter_window.ui @@ -0,0 +1,178 @@ + + + enter_Window + + + true + + + + 0 + 0 + 651 + 474 + + + + 主窗口 + + + + + + + true + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:30pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + + + 正在打开相机... + + + Qt::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0); + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 光谱模式 + + + + + + + true + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255); + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0); + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 影像模式 + + + + + + + + + 0 + 0 + 651 + 23 + + + + + + + wew e + + + + + + diff --git a/record_system_v28/ui/image_Window_phone - 副本 (2).ui b/record_system_v28/ui/image_Window_phone - 副本 (2).ui new file mode 100644 index 0000000..ac44ed4 --- /dev/null +++ b/record_system_v28/ui/image_Window_phone - 副本 (2).ui @@ -0,0 +1,1358 @@ + + + image_Window_phone + + + true + + + + 0 + 0 + 531 + 1174 + + + + false + + + 影像窗口 + + + false + + + false + + + false + + + + + + Qt::Vertical + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 16777215 + 600 + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 600 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 曝 光 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 调 焦 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 暗 电 流 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 采 集 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 保 存 + + + false + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + 140 + 0 + + + + + 200 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文件号 + + + Qt::AlignCenter + + + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 命 名 + + + Qt::AlignCenter + + + + + + + + + + + + + 110 + 0 + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 积分时间 + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + + + 0 + 0 + + + + + 160 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 马 达 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + < + + + false + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + > + + + false + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + rad + + + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 数 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 反转 + + + + + + + + + + + + + 110 + 0 + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 率 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + false + + + + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 233 + 12 + + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 温度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 湿度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 光谱仪:连接失败 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 马达:连接失败! + + + Qt::AlignCenter + + + + + + + + + + + diff --git a/record_system_v28/ui/image_Window_phone.py b/record_system_v28/ui/image_Window_phone.py new file mode 100644 index 0000000..96c440f --- /dev/null +++ b/record_system_v28/ui/image_Window_phone.py @@ -0,0 +1,868 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'image_Window_phone.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_image_Window_phone(object): + def setupUi(self, image_Window_phone): + image_Window_phone.setObjectName("image_Window_phone") + image_Window_phone.setEnabled(True) + image_Window_phone.resize(562, 1174) + image_Window_phone.setMouseTracking(False) + image_Window_phone.setAutoFillBackground(False) + image_Window_phone.setSizeGripEnabled(False) + image_Window_phone.setModal(False) + self.gridLayout_6 = QtWidgets.QGridLayout(image_Window_phone) + self.gridLayout_6.setObjectName("gridLayout_6") + self.frame_3 = QtWidgets.QFrame(image_Window_phone) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_3.sizePolicy().hasHeightForWidth()) + self.frame_3.setSizePolicy(sizePolicy) + self.frame_3.setMaximumSize(QtCore.QSize(16777215, 600)) + self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_3.setObjectName("frame_3") + self.gridLayout_5 = QtWidgets.QGridLayout(self.frame_3) + self.gridLayout_5.setContentsMargins(0, 0, 0, 0) + self.gridLayout_5.setObjectName("gridLayout_5") + self.frame_7 = QtWidgets.QFrame(self.frame_3) + self.frame_7.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_7.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_7.setObjectName("frame_7") + self.gridLayout_4 = QtWidgets.QGridLayout(self.frame_7) + self.gridLayout_4.setContentsMargins(0, 0, 0, 0) + self.gridLayout_4.setObjectName("gridLayout_4") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.image_mode_focus_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_focus_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_focus_bt.setSizePolicy(sizePolicy) + self.image_mode_focus_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_focus_bt.setFont(font) + self.image_mode_focus_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_focus_bt.setAutoDefault(False) + self.image_mode_focus_bt.setObjectName("image_mode_focus_bt") + self.verticalLayout.addWidget(self.image_mode_focus_bt) + self.image_mode_exposureTime_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_exposureTime_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_exposureTime_bt.setSizePolicy(sizePolicy) + self.image_mode_exposureTime_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_exposureTime_bt.setFont(font) + self.image_mode_exposureTime_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_exposureTime_bt.setAutoDefault(False) + self.image_mode_exposureTime_bt.setObjectName("image_mode_exposureTime_bt") + self.verticalLayout.addWidget(self.image_mode_exposureTime_bt) + self.image_mode_dc_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_dc_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_dc_bt.setSizePolicy(sizePolicy) + self.image_mode_dc_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_dc_bt.setFont(font) + self.image_mode_dc_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_dc_bt.setAutoDefault(False) + self.image_mode_dc_bt.setObjectName("image_mode_dc_bt") + self.verticalLayout.addWidget(self.image_mode_dc_bt) + self.image_mode_record_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.image_mode_record_bt.sizePolicy().hasHeightForWidth()) + self.image_mode_record_bt.setSizePolicy(sizePolicy) + self.image_mode_record_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.image_mode_record_bt.setFont(font) + self.image_mode_record_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.image_mode_record_bt.setAutoDefault(False) + self.image_mode_record_bt.setObjectName("image_mode_record_bt") + self.verticalLayout.addWidget(self.image_mode_record_bt) + self.save_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.save_bt.sizePolicy().hasHeightForWidth()) + self.save_bt.setSizePolicy(sizePolicy) + self.save_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.save_bt.setFont(font) + self.save_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.save_bt.setAutoDefault(False) + self.save_bt.setObjectName("save_bt") + self.verticalLayout.addWidget(self.save_bt) + self.gridLayout_4.addLayout(self.verticalLayout, 0, 0, 1, 1) + self.gridLayout_5.addWidget(self.frame_7, 0, 0, 1, 1) + self.frame_6 = QtWidgets.QFrame(self.frame_3) + self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_6.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_6.setObjectName("frame_6") + self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_6) + self.gridLayout_3.setContentsMargins(0, 0, 0, 0) + self.gridLayout_3.setObjectName("gridLayout_3") + self.frame_10 = QtWidgets.QFrame(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_10.sizePolicy().hasHeightForWidth()) + self.frame_10.setSizePolicy(sizePolicy) + self.frame_10.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_10.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_10.setObjectName("frame_10") + self.gridLayout_8 = QtWidgets.QGridLayout(self.frame_10) + self.gridLayout_8.setContentsMargins(0, 0, 0, 0) + self.gridLayout_8.setSpacing(0) + self.gridLayout_8.setObjectName("gridLayout_8") + self.rad_dn_comboBox = QtWidgets.QComboBox(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.rad_dn_comboBox.sizePolicy().hasHeightForWidth()) + self.rad_dn_comboBox.setSizePolicy(sizePolicy) + self.rad_dn_comboBox.setMinimumSize(QtCore.QSize(90, 0)) + self.rad_dn_comboBox.setStyleSheet("/*按钮普通态*/\n" +"QComboBox\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}") + self.rad_dn_comboBox.setObjectName("rad_dn_comboBox") + self.rad_dn_comboBox.addItem("") + self.rad_dn_comboBox.addItem("") + self.gridLayout_8.addWidget(self.rad_dn_comboBox, 0, 2, 1, 1) + self.framenumber_le = QtWidgets.QLineEdit(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.framenumber_le.sizePolicy().hasHeightForWidth()) + self.framenumber_le.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setPointSize(42) + self.framenumber_le.setFont(font) + self.framenumber_le.setObjectName("framenumber_le") + self.gridLayout_8.addWidget(self.framenumber_le, 0, 1, 1, 1) + self.arcus_direction_bt = QtWidgets.QPushButton(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_direction_bt.sizePolicy().hasHeightForWidth()) + self.arcus_direction_bt.setSizePolicy(sizePolicy) + self.arcus_direction_bt.setMinimumSize(QtCore.QSize(90, 0)) + self.arcus_direction_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.arcus_direction_bt.setFont(font) + self.arcus_direction_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.arcus_direction_bt.setAutoDefault(False) + self.arcus_direction_bt.setObjectName("arcus_direction_bt") + self.gridLayout_8.addWidget(self.arcus_direction_bt, 0, 3, 1, 1) + self.label_2 = QtWidgets.QLabel(self.frame_10) + self.label_2.setMinimumSize(QtCore.QSize(110, 0)) + self.label_2.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.gridLayout_8.addWidget(self.label_2, 0, 0, 1, 1) + self.gridLayout_3.addWidget(self.frame_10, 4, 0, 1, 1) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.label_3 = QtWidgets.QLabel(self.frame_6) + self.label_3.setMinimumSize(QtCore.QSize(110, 0)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(20) + self.label_3.setFont(font) + self.label_3.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.horizontalLayout_3.addWidget(self.label_3) + self.framerate_le = QtWidgets.QLineEdit(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.framerate_le.sizePolicy().hasHeightForWidth()) + self.framerate_le.setSizePolicy(sizePolicy) + self.framerate_le.setMaximumSize(QtCore.QSize(16777215, 106)) + font = QtGui.QFont() + font.setPointSize(42) + self.framerate_le.setFont(font) + self.framerate_le.setReadOnly(False) + self.framerate_le.setObjectName("framerate_le") + self.horizontalLayout_3.addWidget(self.framerate_le) + self.framenumber_recorded_label = QtWidgets.QLabel(self.frame_6) + self.framenumber_recorded_label.setMinimumSize(QtCore.QSize(180, 0)) + self.framenumber_recorded_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.framenumber_recorded_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.framenumber_recorded_label.setAlignment(QtCore.Qt.AlignCenter) + self.framenumber_recorded_label.setObjectName("framenumber_recorded_label") + self.horizontalLayout_3.addWidget(self.framenumber_recorded_label) + self.gridLayout_3.addLayout(self.horizontalLayout_3, 1, 0, 1, 1) + self.frame_9 = QtWidgets.QFrame(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_9.sizePolicy().hasHeightForWidth()) + self.frame_9.setSizePolicy(sizePolicy) + self.frame_9.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_9.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_9.setLineWidth(0) + self.frame_9.setObjectName("frame_9") + self.gridLayout_7 = QtWidgets.QGridLayout(self.frame_9) + self.gridLayout_7.setContentsMargins(0, 0, 0, 0) + self.gridLayout_7.setSpacing(0) + self.gridLayout_7.setObjectName("gridLayout_7") + self.filename_le = QtWidgets.QLineEdit(self.frame_9) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.filename_le.sizePolicy().hasHeightForWidth()) + self.filename_le.setSizePolicy(sizePolicy) + self.filename_le.setMaximumSize(QtCore.QSize(16777215, 106)) + font = QtGui.QFont() + font.setPointSize(42) + self.filename_le.setFont(font) + self.filename_le.setObjectName("filename_le") + self.gridLayout_7.addWidget(self.filename_le, 0, 1, 1, 1) + self.label_6 = QtWidgets.QLabel(self.frame_9) + self.label_6.setMinimumSize(QtCore.QSize(110, 0)) + self.label_6.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_6.setAlignment(QtCore.Qt.AlignCenter) + self.label_6.setObjectName("label_6") + self.gridLayout_7.addWidget(self.label_6, 0, 0, 1, 1) + self.file_number_label = QtWidgets.QLabel(self.frame_9) + self.file_number_label.setMinimumSize(QtCore.QSize(180, 0)) + self.file_number_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.file_number_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.file_number_label.setAlignment(QtCore.Qt.AlignCenter) + self.file_number_label.setObjectName("file_number_label") + self.gridLayout_7.addWidget(self.file_number_label, 0, 2, 1, 1) + self.gridLayout_3.addWidget(self.frame_9, 6, 0, 1, 1) + self.frame_5 = QtWidgets.QFrame(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_5.sizePolicy().hasHeightForWidth()) + self.frame_5.setSizePolicy(sizePolicy) + self.frame_5.setMinimumSize(QtCore.QSize(160, 0)) + self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_5.setObjectName("frame_5") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_5) + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_7 = QtWidgets.QLabel(self.frame_5) + self.label_7.setMinimumSize(QtCore.QSize(110, 0)) + self.label_7.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_7.setAlignment(QtCore.Qt.AlignCenter) + self.label_7.setObjectName("label_7") + self.horizontalLayout_2.addWidget(self.label_7) + self.arcus_left_bt = QtWidgets.QPushButton(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_left_bt.sizePolicy().hasHeightForWidth()) + self.arcus_left_bt.setSizePolicy(sizePolicy) + self.arcus_left_bt.setMinimumSize(QtCore.QSize(50, 0)) + self.arcus_left_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.arcus_left_bt.setFont(font) + self.arcus_left_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.arcus_left_bt.setAutoDefault(False) + self.arcus_left_bt.setObjectName("arcus_left_bt") + self.horizontalLayout_2.addWidget(self.arcus_left_bt) + self.arcus_speed_le = QtWidgets.QLineEdit(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_speed_le.sizePolicy().hasHeightForWidth()) + self.arcus_speed_le.setSizePolicy(sizePolicy) + self.arcus_speed_le.setMinimumSize(QtCore.QSize(60, 0)) + self.arcus_speed_le.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setPointSize(42) + self.arcus_speed_le.setFont(font) + self.arcus_speed_le.setObjectName("arcus_speed_le") + self.horizontalLayout_2.addWidget(self.arcus_speed_le) + self.arcus_right_bt = QtWidgets.QPushButton(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_right_bt.sizePolicy().hasHeightForWidth()) + self.arcus_right_bt.setSizePolicy(sizePolicy) + self.arcus_right_bt.setMinimumSize(QtCore.QSize(50, 0)) + self.arcus_right_bt.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.arcus_right_bt.setFont(font) + self.arcus_right_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.arcus_right_bt.setAutoDefault(False) + self.arcus_right_bt.setObjectName("arcus_right_bt") + self.horizontalLayout_2.addWidget(self.arcus_right_bt) + self.gridLayout_3.addWidget(self.frame_5, 3, 0, 1, 1) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.label_5 = QtWidgets.QLabel(self.frame_6) + self.label_5.setMinimumSize(QtCore.QSize(110, 0)) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(20) + self.label_5.setFont(font) + self.label_5.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:20pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_5.setObjectName("label_5") + self.horizontalLayout_4.addWidget(self.label_5) + self.exposure_time_le = QtWidgets.QLineEdit(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.exposure_time_le.sizePolicy().hasHeightForWidth()) + self.exposure_time_le.setSizePolicy(sizePolicy) + self.exposure_time_le.setMaximumSize(QtCore.QSize(16777215, 106)) + font = QtGui.QFont() + font.setPointSize(42) + self.exposure_time_le.setFont(font) + self.exposure_time_le.setObjectName("exposure_time_le") + self.horizontalLayout_4.addWidget(self.exposure_time_le) + self.gridLayout_3.addLayout(self.horizontalLayout_4, 2, 0, 1, 1) + self.gridLayout_5.addWidget(self.frame_6, 0, 1, 1, 1) + self.gridLayout_6.addWidget(self.frame_3, 1, 0, 1, 1) + self.frame_4 = QtWidgets.QFrame(image_Window_phone) + self.frame_4.setMinimumSize(QtCore.QSize(0, 0)) + self.frame_4.setMaximumSize(QtCore.QSize(16777215, 35)) + self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_4.setObjectName("frame_4") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_4) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout.setSpacing(0) + self.horizontalLayout.setObjectName("horizontalLayout") + spacerItem = QtWidgets.QSpacerItem(233, 12, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.t_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.t_label.sizePolicy().hasHeightForWidth()) + self.t_label.setSizePolicy(sizePolicy) + self.t_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.t_label.setAlignment(QtCore.Qt.AlignCenter) + self.t_label.setObjectName("t_label") + self.horizontalLayout.addWidget(self.t_label) + self.hum_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.hum_label.sizePolicy().hasHeightForWidth()) + self.hum_label.setSizePolicy(sizePolicy) + self.hum_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.hum_label.setAlignment(QtCore.Qt.AlignCenter) + self.hum_label.setObjectName("hum_label") + self.horizontalLayout.addWidget(self.hum_label) + self.camera_status_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.camera_status_label.sizePolicy().hasHeightForWidth()) + self.camera_status_label.setSizePolicy(sizePolicy) + self.camera_status_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.camera_status_label.setAlignment(QtCore.Qt.AlignCenter) + self.camera_status_label.setObjectName("camera_status_label") + self.horizontalLayout.addWidget(self.camera_status_label) + self.arcus_status_label = QtWidgets.QLabel(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.arcus_status_label.sizePolicy().hasHeightForWidth()) + self.arcus_status_label.setSizePolicy(sizePolicy) + self.arcus_status_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.arcus_status_label.setAlignment(QtCore.Qt.AlignCenter) + self.arcus_status_label.setObjectName("arcus_status_label") + self.horizontalLayout.addWidget(self.arcus_status_label) + self.gridLayout_6.addWidget(self.frame_4, 2, 0, 1, 1) + self.splitter = QtWidgets.QSplitter(image_Window_phone) + self.splitter.setOrientation(QtCore.Qt.Vertical) + self.splitter.setObjectName("splitter") + self.frame_2 = QtWidgets.QFrame(self.splitter) + self.frame_2.setFrameShape(QtWidgets.QFrame.Box) + self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_2.setObjectName("frame_2") + self.gridLayout_2 = QtWidgets.QGridLayout(self.frame_2) + self.gridLayout_2.setContentsMargins(0, 0, 0, 0) + self.gridLayout_2.setObjectName("gridLayout_2") + self.image_glo = QtWidgets.QGridLayout() + self.image_glo.setObjectName("image_glo") + self.gridLayout_2.addLayout(self.image_glo, 0, 0, 1, 1) + self.frame = QtWidgets.QFrame(self.splitter) + self.frame.setMaximumSize(QtCore.QSize(16777215, 600)) + self.frame.setFrameShape(QtWidgets.QFrame.Box) + self.frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame.setObjectName("frame") + self.gridLayout = QtWidgets.QGridLayout(self.frame) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.focus_glo = QtWidgets.QGridLayout() + self.focus_glo.setObjectName("focus_glo") + self.gridLayout.addLayout(self.focus_glo, 0, 0, 1, 1) + self.gridLayout_6.addWidget(self.splitter, 0, 0, 1, 1) + + self.retranslateUi(image_Window_phone) + QtCore.QMetaObject.connectSlotsByName(image_Window_phone) + + def retranslateUi(self, image_Window_phone): + _translate = QtCore.QCoreApplication.translate + image_Window_phone.setWindowTitle(_translate("image_Window_phone", "影像窗口")) + self.image_mode_focus_bt.setText(_translate("image_Window_phone", "调 焦")) + self.image_mode_exposureTime_bt.setText(_translate("image_Window_phone", "曝 光")) + self.image_mode_dc_bt.setText(_translate("image_Window_phone", "暗 电 流")) + self.image_mode_record_bt.setText(_translate("image_Window_phone", "采 集")) + self.save_bt.setText(_translate("image_Window_phone", "保 存")) + self.rad_dn_comboBox.setItemText(0, _translate("image_Window_phone", "rad")) + self.rad_dn_comboBox.setItemText(1, _translate("image_Window_phone", "dn")) + self.arcus_direction_bt.setText(_translate("image_Window_phone", "反转")) + self.label_2.setText(_translate("image_Window_phone", "帧 数")) + self.label_3.setText(_translate("image_Window_phone", "帧 率")) + self.framenumber_recorded_label.setText(_translate("image_Window_phone", "帧号")) + self.label_6.setText(_translate("image_Window_phone", "命 名")) + self.file_number_label.setText(_translate("image_Window_phone", "文件号")) + self.label_7.setText(_translate("image_Window_phone", "马 达")) + self.arcus_left_bt.setText(_translate("image_Window_phone", "<")) + self.arcus_right_bt.setText(_translate("image_Window_phone", ">")) + self.label_5.setText(_translate("image_Window_phone", "积分时间")) + self.t_label.setText(_translate("image_Window_phone", "温度:无数据")) + self.hum_label.setText(_translate("image_Window_phone", "湿度:无数据")) + self.camera_status_label.setText(_translate("image_Window_phone", "光谱仪:连接失败")) + self.arcus_status_label.setText(_translate("image_Window_phone", "马达:连接失败!")) diff --git a/record_system_v28/ui/image_Window_phone.ui b/record_system_v28/ui/image_Window_phone.ui new file mode 100644 index 0000000..3f0256b --- /dev/null +++ b/record_system_v28/ui/image_Window_phone.ui @@ -0,0 +1,1395 @@ + + + image_Window_phone + + + true + + + + 0 + 0 + 562 + 1174 + + + + false + + + 影像窗口 + + + false + + + false + + + false + + + + + + + 0 + 0 + + + + + 16777215 + 600 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 调 焦 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 曝 光 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 暗 电 流 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 采 集 + + + false + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 保 存 + + + false + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 90 + 0 + + + + /*按钮普通态*/ +QComboBox +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + + + + rad + + + + + dn + + + + + + + + + 0 + 0 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 90 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 反转 + + + false + + + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 数 + + + Qt::AlignCenter + + + + + + + + + + + + + 110 + 0 + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧 率 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + false + + + + + + + + 180 + 0 + + + + + 200 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 帧号 + + + Qt::AlignCenter + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 命 名 + + + Qt::AlignCenter + + + + + + + + 180 + 0 + + + + + 200 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文件号 + + + Qt::AlignCenter + + + + + + + + + + + 0 + 0 + + + + + 160 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 110 + 0 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 马 达 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + < + + + false + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + + 42 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + Microsoft Yahei + 25 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + > + + + false + + + + + + + + + + + + + 110 + 0 + + + + + Microsoft Yahei + 20 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:20pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 积分时间 + + + + + + + + 0 + 0 + + + + + 16777215 + 106 + + + + + 42 + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 233 + 12 + + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 温度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 湿度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 光谱仪:连接失败 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 马达:连接失败! + + + Qt::AlignCenter + + + + + + + + + + Qt::Vertical + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 16777215 + 600 + + + + QFrame::Box + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + diff --git a/record_system_v28/ui/spectral_Window_phone.py b/record_system_v28/ui/spectral_Window_phone.py new file mode 100644 index 0000000..1843a1e --- /dev/null +++ b/record_system_v28/ui/spectral_Window_phone.py @@ -0,0 +1,635 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'spectral_Window_phone.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_spectral_Window_phone(object): + def setupUi(self, spectral_Window_phone): + spectral_Window_phone.setObjectName("spectral_Window_phone") + spectral_Window_phone.resize(728, 1175) + self.gridLayout_6 = QtWidgets.QGridLayout(spectral_Window_phone) + self.gridLayout_6.setObjectName("gridLayout_6") + self.frame = QtWidgets.QFrame(spectral_Window_phone) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth()) + self.frame.setSizePolicy(sizePolicy) + self.frame.setMinimumSize(QtCore.QSize(0, 600)) + self.frame.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame.setObjectName("frame") + self.gridLayout = QtWidgets.QGridLayout(self.frame) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setObjectName("gridLayout") + self.spe_glo = QtWidgets.QGridLayout() + self.spe_glo.setObjectName("spe_glo") + self.gridLayout.addLayout(self.spe_glo, 0, 0, 1, 1) + self.gridLayout_6.addWidget(self.frame, 0, 0, 1, 1) + self.frame_2 = QtWidgets.QFrame(spectral_Window_phone) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth()) + self.frame_2.setSizePolicy(sizePolicy) + self.frame_2.setMaximumSize(QtCore.QSize(16777215, 600)) + self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_2.setObjectName("frame_2") + self.gridLayout_8 = QtWidgets.QGridLayout(self.frame_2) + self.gridLayout_8.setContentsMargins(0, 0, 0, 0) + self.gridLayout_8.setSpacing(0) + self.gridLayout_8.setObjectName("gridLayout_8") + self.frame_4 = QtWidgets.QFrame(self.frame_2) + self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_4.setObjectName("frame_4") + self.gridLayout_4 = QtWidgets.QGridLayout(self.frame_4) + self.gridLayout_4.setContentsMargins(0, 0, 0, 0) + self.gridLayout_4.setSpacing(0) + self.gridLayout_4.setObjectName("gridLayout_4") + self.spectral_mode_autoexposure_bt = QtWidgets.QPushButton(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_autoexposure_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_autoexposure_bt.setSizePolicy(sizePolicy) + self.spectral_mode_autoexposure_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_autoexposure_bt.setAutoDefault(False) + self.spectral_mode_autoexposure_bt.setObjectName("spectral_mode_autoexposure_bt") + self.gridLayout_4.addWidget(self.spectral_mode_autoexposure_bt, 0, 0, 1, 1) + self.autoexposure_le = QtWidgets.QLineEdit(self.frame_4) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.autoexposure_le.sizePolicy().hasHeightForWidth()) + self.autoexposure_le.setSizePolicy(sizePolicy) + self.autoexposure_le.setMaximumSize(QtCore.QSize(200, 16777215)) + self.autoexposure_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:40pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.autoexposure_le.setObjectName("autoexposure_le") + self.gridLayout_4.addWidget(self.autoexposure_le, 0, 1, 1, 1) + self.gridLayout_8.addWidget(self.frame_4, 0, 0, 1, 1) + self.frame_6 = QtWidgets.QFrame(self.frame_2) + self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_6.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_6.setObjectName("frame_6") + self.gridLayout_2 = QtWidgets.QGridLayout(self.frame_6) + self.gridLayout_2.setContentsMargins(0, 0, 0, 0) + self.gridLayout_2.setSpacing(0) + self.gridLayout_2.setObjectName("gridLayout_2") + self.dc_timer_label = QtWidgets.QLabel(self.frame_6) + self.dc_timer_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.dc_timer_label.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.dc_timer_label.setAlignment(QtCore.Qt.AlignCenter) + self.dc_timer_label.setObjectName("dc_timer_label") + self.gridLayout_2.addWidget(self.dc_timer_label, 0, 1, 1, 1) + self.spectral_mode_dc_bt = QtWidgets.QPushButton(self.frame_6) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_dc_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_dc_bt.setSizePolicy(sizePolicy) + self.spectral_mode_dc_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_dc_bt.setAutoDefault(False) + self.spectral_mode_dc_bt.setObjectName("spectral_mode_dc_bt") + self.gridLayout_2.addWidget(self.spectral_mode_dc_bt, 0, 0, 1, 1) + self.gridLayout_8.addWidget(self.frame_6, 1, 0, 1, 1) + self.frame_7 = QtWidgets.QFrame(self.frame_2) + self.frame_7.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_7.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_7.setObjectName("frame_7") + self.gridLayout_7 = QtWidgets.QGridLayout(self.frame_7) + self.gridLayout_7.setContentsMargins(0, 0, 0, 0) + self.gridLayout_7.setSpacing(0) + self.gridLayout_7.setObjectName("gridLayout_7") + self.spectral_mode_wb_bt = QtWidgets.QPushButton(self.frame_7) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_wb_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_wb_bt.setSizePolicy(sizePolicy) + self.spectral_mode_wb_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_wb_bt.setAutoDefault(False) + self.spectral_mode_wb_bt.setObjectName("spectral_mode_wb_bt") + self.gridLayout_7.addWidget(self.spectral_mode_wb_bt, 0, 0, 1, 1) + self.wb_timer_label = QtWidgets.QLabel(self.frame_7) + self.wb_timer_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.wb_timer_label.setStyleSheet("/*按钮普通态*/\n" +"QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.wb_timer_label.setAlignment(QtCore.Qt.AlignCenter) + self.wb_timer_label.setObjectName("wb_timer_label") + self.gridLayout_7.addWidget(self.wb_timer_label, 0, 1, 1, 1) + self.gridLayout_8.addWidget(self.frame_7, 2, 0, 1, 1) + self.frame_5 = QtWidgets.QFrame(self.frame_2) + self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_5.setObjectName("frame_5") + self.gridLayout_5 = QtWidgets.QGridLayout(self.frame_5) + self.gridLayout_5.setContentsMargins(0, 0, 0, 0) + self.gridLayout_5.setSpacing(0) + self.gridLayout_5.setObjectName("gridLayout_5") + self.spectral_mode_record_bt = QtWidgets.QPushButton(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_mode_record_bt.sizePolicy().hasHeightForWidth()) + self.spectral_mode_record_bt.setSizePolicy(sizePolicy) + self.spectral_mode_record_bt.setStyleSheet("/*按钮普通态*/\n" +"QPushButton\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}\n" +"\n" +"/*按钮停留态*/\n" +"QPushButton:hover\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(44 , 137 , 255);/*hover*/\n" +" /*边框圆角半径为8像素*/\n" +" /*border-radius:20px;*/\n" +"}\n" +"\n" +"/*按钮按下态*/\n" +"QPushButton:pressed\n" +"{\n" +" /*背景颜色*/ \n" +" background-color:rgb(255 , 0 , 0);/*pressed*/\n" +"\n" +" /*左内边距为3像素,让按下时字向右移动3像素*/ \n" +" padding-left:3px;\n" +"\n" +" /*上内边距为3像素,让按下时字向下移动3像素*/ \n" +" padding-top:3px;\n" +"}") + self.spectral_mode_record_bt.setAutoDefault(False) + self.spectral_mode_record_bt.setObjectName("spectral_mode_record_bt") + self.gridLayout_5.addWidget(self.spectral_mode_record_bt, 0, 0, 1, 1) + self.data_type_comboBox = QtWidgets.QComboBox(self.frame_5) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.data_type_comboBox.sizePolicy().hasHeightForWidth()) + self.data_type_comboBox.setSizePolicy(sizePolicy) + self.data_type_comboBox.setMaximumSize(QtCore.QSize(200, 16777215)) + self.data_type_comboBox.setStyleSheet("/*按钮普通态*/\n" +"QComboBox\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" background-color:rgb(225 , 225 , 225);\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:20px;\n" +"}") + self.data_type_comboBox.setFrame(False) + self.data_type_comboBox.setObjectName("data_type_comboBox") + self.data_type_comboBox.addItem("") + self.data_type_comboBox.addItem("") + self.data_type_comboBox.addItem("") + self.gridLayout_5.addWidget(self.data_type_comboBox, 0, 1, 1, 1) + self.progressBar = QtWidgets.QProgressBar(self.frame_5) + self.progressBar.setStyleSheet("QProgressBar\n" +"{ \n" +" background-color:rgb(225 , 225 , 225);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.progressBar.setProperty("value", 0) + self.progressBar.setTextVisible(False) + self.progressBar.setObjectName("progressBar") + self.gridLayout_5.addWidget(self.progressBar, 1, 0, 1, 2) + self.gridLayout_8.addWidget(self.frame_5, 3, 0, 1, 1) + self.gridLayout_6.addWidget(self.frame_2, 1, 0, 1, 1) + self.frame_3 = QtWidgets.QFrame(spectral_Window_phone) + self.frame_3.setMaximumSize(QtCore.QSize(16777215, 200)) + self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_3.setObjectName("frame_3") + self.gridLayout_10 = QtWidgets.QGridLayout(self.frame_3) + self.gridLayout_10.setContentsMargins(0, 0, 0, 0) + self.gridLayout_10.setSpacing(0) + self.gridLayout_10.setObjectName("gridLayout_10") + self.frame_9 = QtWidgets.QFrame(self.frame_3) + self.frame_9.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_9.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_9.setObjectName("frame_9") + self.gridLayout_9 = QtWidgets.QGridLayout(self.frame_9) + self.gridLayout_9.setContentsMargins(0, 0, 0, 0) + self.gridLayout_9.setSpacing(0) + self.gridLayout_9.setObjectName("gridLayout_9") + self.filename_le = QtWidgets.QLineEdit(self.frame_9) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.filename_le.sizePolicy().hasHeightForWidth()) + self.filename_le.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(61) + self.filename_le.setFont(font) + self.filename_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:61pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.filename_le.setObjectName("filename_le") + self.gridLayout_9.addWidget(self.filename_le, 0, 2, 1, 1) + self.label_2 = QtWidgets.QLabel(self.frame_9) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth()) + self.label_2.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setFamily("Microsoft Yahei") + font.setPointSize(25) + self.label_2.setFont(font) + self.label_2.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_2.setAlignment(QtCore.Qt.AlignCenter) + self.label_2.setObjectName("label_2") + self.gridLayout_9.addWidget(self.label_2, 0, 1, 1, 1) + self.file_number_label = QtWidgets.QLabel(self.frame_9) + self.file_number_label.setMaximumSize(QtCore.QSize(200, 16777215)) + self.file_number_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.file_number_label.setAlignment(QtCore.Qt.AlignCenter) + self.file_number_label.setObjectName("file_number_label") + self.gridLayout_9.addWidget(self.file_number_label, 0, 3, 1, 1) + self.frame_10 = QtWidgets.QFrame(self.frame_9) + self.frame_10.setMinimumSize(QtCore.QSize(200, 0)) + self.frame_10.setMaximumSize(QtCore.QSize(350, 16777215)) + self.frame_10.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_10.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_10.setObjectName("frame_10") + self.gridLayout_11 = QtWidgets.QGridLayout(self.frame_10) + self.gridLayout_11.setContentsMargins(0, 0, 0, 0) + self.gridLayout_11.setSpacing(0) + self.gridLayout_11.setObjectName("gridLayout_11") + self.label_3 = QtWidgets.QLabel(self.frame_10) + self.label_3.setMinimumSize(QtCore.QSize(140, 0)) + self.label_3.setMaximumSize(QtCore.QSize(110, 16777215)) + self.label_3.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.gridLayout_11.addWidget(self.label_3, 0, 0, 1, 1) + self.label_4 = QtWidgets.QLabel(self.frame_10) + self.label_4.setMinimumSize(QtCore.QSize(140, 0)) + self.label_4.setMaximumSize(QtCore.QSize(110, 16777215)) + self.label_4.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:25pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.label_4.setAlignment(QtCore.Qt.AlignCenter) + self.label_4.setObjectName("label_4") + self.gridLayout_11.addWidget(self.label_4, 1, 0, 1, 1) + self.spectral_number_le = QtWidgets.QLineEdit(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spectral_number_le.sizePolicy().hasHeightForWidth()) + self.spectral_number_le.setSizePolicy(sizePolicy) + self.spectral_number_le.setMinimumSize(QtCore.QSize(60, 0)) + self.spectral_number_le.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.spectral_number_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:30pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.spectral_number_le.setObjectName("spectral_number_le") + self.gridLayout_11.addWidget(self.spectral_number_le, 1, 2, 1, 1) + self.framenumber_average_le = QtWidgets.QLineEdit(self.frame_10) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.framenumber_average_le.sizePolicy().hasHeightForWidth()) + self.framenumber_average_le.setSizePolicy(sizePolicy) + self.framenumber_average_le.setMinimumSize(QtCore.QSize(60, 0)) + self.framenumber_average_le.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.framenumber_average_le.setStyleSheet("QLineEdit\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" /*字体大小为20点*/\n" +" font-size:30pt;\n" +" /*字体颜色为白色*/ \n" +" /*color:white;*/\n" +" /*背景颜色*/ \n" +" /*background-color:rgb(14 , 150 , 254);*/\n" +" /*边框圆角半径为8像素*/ \n" +" /*border-radius:8px;*/\n" +"}") + self.framenumber_average_le.setObjectName("framenumber_average_le") + self.gridLayout_11.addWidget(self.framenumber_average_le, 0, 2, 1, 1) + self.gridLayout_9.addWidget(self.frame_10, 0, 0, 1, 1) + self.gridLayout_10.addWidget(self.frame_9, 0, 0, 1, 1) + self.frame_8 = QtWidgets.QFrame(self.frame_3) + self.frame_8.setMaximumSize(QtCore.QSize(16777215, 35)) + self.frame_8.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame_8.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame_8.setObjectName("frame_8") + self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_8) + self.gridLayout_3.setContentsMargins(0, 0, 0, 0) + self.gridLayout_3.setSpacing(0) + self.gridLayout_3.setObjectName("gridLayout_3") + spacerItem = QtWidgets.QSpacerItem(399, 15, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.gridLayout_3.addItem(spacerItem, 0, 0, 1, 1) + self.t_label = QtWidgets.QLabel(self.frame_8) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.t_label.sizePolicy().hasHeightForWidth()) + self.t_label.setSizePolicy(sizePolicy) + self.t_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.t_label.setAlignment(QtCore.Qt.AlignCenter) + self.t_label.setObjectName("t_label") + self.gridLayout_3.addWidget(self.t_label, 0, 1, 1, 1) + self.hum_label = QtWidgets.QLabel(self.frame_8) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.hum_label.sizePolicy().hasHeightForWidth()) + self.hum_label.setSizePolicy(sizePolicy) + self.hum_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.hum_label.setAlignment(QtCore.Qt.AlignCenter) + self.hum_label.setObjectName("hum_label") + self.gridLayout_3.addWidget(self.hum_label, 0, 2, 1, 1) + self.camera_status_label = QtWidgets.QLabel(self.frame_8) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.camera_status_label.sizePolicy().hasHeightForWidth()) + self.camera_status_label.setSizePolicy(sizePolicy) + self.camera_status_label.setStyleSheet("QLabel\n" +"{\n" +" /*字体为微软雅黑*/\n" +" font-family:Microsoft Yahei;\n" +" background-color:rgb(255 , 0 , 0);/*normal*/\n" +" /*边框圆角半径为8像素*/ \n" +" border-radius:10px;\n" +"}") + self.camera_status_label.setAlignment(QtCore.Qt.AlignCenter) + self.camera_status_label.setObjectName("camera_status_label") + self.gridLayout_3.addWidget(self.camera_status_label, 0, 3, 1, 1) + self.gridLayout_10.addWidget(self.frame_8, 1, 0, 1, 1) + self.gridLayout_6.addWidget(self.frame_3, 2, 0, 1, 1) + + self.retranslateUi(spectral_Window_phone) + QtCore.QMetaObject.connectSlotsByName(spectral_Window_phone) + + def retranslateUi(self, spectral_Window_phone): + _translate = QtCore.QCoreApplication.translate + spectral_Window_phone.setWindowTitle(_translate("spectral_Window_phone", "光谱窗口")) + self.spectral_mode_autoexposure_bt.setText(_translate("spectral_Window_phone", "曝 光")) + self.dc_timer_label.setText(_translate("spectral_Window_phone", "计时")) + self.spectral_mode_dc_bt.setText(_translate("spectral_Window_phone", "暗 电 流")) + self.spectral_mode_wb_bt.setText(_translate("spectral_Window_phone", "白 板")) + self.wb_timer_label.setText(_translate("spectral_Window_phone", "计时")) + self.spectral_mode_record_bt.setText(_translate("spectral_Window_phone", "采 集")) + self.data_type_comboBox.setCurrentText(_translate("spectral_Window_phone", "DN")) + self.data_type_comboBox.setItemText(0, _translate("spectral_Window_phone", "DN")) + self.data_type_comboBox.setItemText(1, _translate("spectral_Window_phone", "Ref")) + self.data_type_comboBox.setItemText(2, _translate("spectral_Window_phone", "Rad")) + self.label_2.setText(_translate("spectral_Window_phone", "文 件")) + self.file_number_label.setText(_translate("spectral_Window_phone", "文件号")) + self.label_3.setText(_translate("spectral_Window_phone", "自动平均")) + self.label_4.setText(_translate("spectral_Window_phone", "连续测量")) + self.t_label.setText(_translate("spectral_Window_phone", "温度:无数据")) + self.hum_label.setText(_translate("spectral_Window_phone", "湿度:无数据")) + self.camera_status_label.setText(_translate("spectral_Window_phone", "光谱仪:连接失败")) diff --git a/record_system_v28/ui/spectral_Window_phone.ui b/record_system_v28/ui/spectral_Window_phone.ui new file mode 100644 index 0000000..ec2c6bb --- /dev/null +++ b/record_system_v28/ui/spectral_Window_phone.ui @@ -0,0 +1,1071 @@ + + + spectral_Window_phone + + + + 0 + 0 + 568 + 1175 + + + + 光谱窗口 + + + + + + + 0 + 0 + + + + + 0 + 600 + + + + + 16777215 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 600 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 曝 光 + + + false + + + + + + + + 0 + 0 + + + + + 200 + 16777215 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:40pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 200 + 16777215 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 计时 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 暗 电 流 + + + false + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 白 板 + + + false + + + + + + + + 200 + 16777215 + + + + /*按钮普通态*/ +QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 计时 + + + Qt::AlignCenter + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + /*按钮普通态*/ +QPushButton +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:20px; +} + +/*按钮停留态*/ +QPushButton:hover +{ + /*背景颜色*/ + background-color:rgb(44 , 137 , 255);/*hover*/ + /*边框圆角半径为8像素*/ + /*border-radius:20px;*/ +} + +/*按钮按下态*/ +QPushButton:pressed +{ + /*背景颜色*/ + background-color:rgb(255 , 0 , 0);/*pressed*/ + + /*左内边距为3像素,让按下时字向右移动3像素*/ + padding-left:3px; + + /*上内边距为3像素,让按下时字向下移动3像素*/ + padding-top:3px; +} + + + 采 集 + + + false + + + + + + + + 0 + 0 + + + + + 200 + 16777215 + + + + /*按钮普通态*/ +QComboBox +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + background-color:rgb(225 , 225 , 225); + /*边框圆角半径为8像素*/ + border-radius:20px; +} + + + DN + + + false + + + + DN + + + + + Ref + + + + + Rad + + + + + + + + QProgressBar +{ + background-color:rgb(225 , 225 , 225);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 0 + + + false + + + + + + + + + + + + + + 16777215 + 200 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + Microsoft Yahei + 61 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:61pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + + + + + + 0 + 0 + + + + + Microsoft Yahei + 25 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文 件 + + + Qt::AlignCenter + + + + + + + + 200 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 文件号 + + + Qt::AlignCenter + + + + + + + + 200 + 0 + + + + + 350 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 140 + 0 + + + + + 110 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 自动平均 + + + Qt::AlignCenter + + + + + + + + 140 + 0 + + + + + 110 + 16777215 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:25pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + 连续测量 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:30pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 16777215 + 16777215 + + + + QLineEdit +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + /*字体大小为20点*/ + font-size:30pt; + /*字体颜色为白色*/ + /*color:white;*/ + /*背景颜色*/ + /*background-color:rgb(14 , 150 , 254);*/ + /*边框圆角半径为8像素*/ + /*border-radius:8px;*/ +} + + + Qt::AlignCenter + + + + + + + + + + + + + + 16777215 + 35 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 399 + 15 + + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 温度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 湿度:无数据 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + QLabel +{ + /*字体为微软雅黑*/ + font-family:Microsoft Yahei; + background-color:rgb(255 , 0 , 0);/*normal*/ + /*边框圆角半径为8像素*/ + border-radius:10px; +} + + + 光谱仪:连接失败 + + + Qt::AlignCenter + + + + + + + + + + + + + +