From 8f143e51ccbf38dd3c3c96c68d52789c7b91e6f2 Mon Sep 17 00:00:00 2001 From: tangchao0503 <735056338@qq.com> Date: Sun, 12 Mar 2023 20:15:10 +0800 Subject: [PATCH] =?UTF-8?q?1.=20hpi=E5=AE=9A=E6=A0=87=EF=BC=9A=E9=87=87?= =?UTF-8?q?=E9=9B=86=E5=BD=B1=E5=83=8F=E6=97=B6=EF=BC=8C=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E6=89=A3=E6=9A=97=E7=94=B5=E6=B5=81=EF=BC=8C=E4=BB=85=E7=94=9F?= =?UTF-8?q?=E6=88=90gain=EF=BC=9B=202.=20300tc=E5=AE=9A=E6=A0=87=EF=BC=9A?= =?UTF-8?q?=E9=87=87=E9=9B=86=E6=97=B6=E5=8D=95=E7=8B=AC=E9=87=87=E9=9B=86?= =?UTF-8?q?=E6=9A=97=E7=94=B5=E6=B5=81=E5=BD=B1=E5=83=8F=EF=BC=8C=E7=94=9F?= =?UTF-8?q?=E6=88=90gain+offset=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 243 +++++++++++++++++++++ 0radiance_conversion_resonon.py | 262 ++++++++++++++++++++++ 1.1radiance_calibration_300tc.py | 251 +++++++++++++++++++++ 1.2radiance_calibration_corning410.py | 119 ++++++++++ 2radiance_conversion_corning410.py | 101 +++++++++ corning_radance.txt | 300 ++++++++++++++++++++++++++ radiance_calibration_ui.py | 151 +++++++++++++ radiance_calibration_ui.ui | 226 +++++++++++++++++++ 8 files changed, 1653 insertions(+) create mode 100644 .gitignore create mode 100644 0radiance_conversion_resonon.py create mode 100644 1.1radiance_calibration_300tc.py create mode 100644 1.2radiance_calibration_corning410.py create mode 100644 2radiance_conversion_corning410.py create mode 100644 corning_radance.txt create mode 100644 radiance_calibration_ui.py create mode 100644 radiance_calibration_ui.ui diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a648c2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,243 @@ +# tc +/.idea +*.xlsx +*.cal + +# 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/0radiance_conversion_resonon.py b/0radiance_conversion_resonon.py new file mode 100644 index 0000000..5b333a9 --- /dev/null +++ b/0radiance_conversion_resonon.py @@ -0,0 +1,262 @@ +''' + +C:\Program Files\SpectrononPro\plugins\cube\correct + +NOTES AND ASSUMPTIONS: +-Response of camera is linear after dark noise removal +- If additive binning is utilized, it must be in the header file +- If frame windowing infomation is stored on-cameras (like the Basler Ace), gain cube is collected windowed and no window header item is utilized. Otherwise, + the spatial/band windowing header item must be included. +- There is only one gain cube in vault. It is not binned or averaged. +- Offset cubes can be binned. They are located by the # of bands, not by binning numbers. +- Georeg cubes must be windowed and binned to match. This code will average down to match size, just in case, but GeoReg won't! +- If Auto Dark Noise removal is unchecked and not dark noise cube is given, no dark noise will be removed +- If Auto Dark Noise removal is unchecked, and a dark noise cube supplied, its dimensions must match the given cube + +''' + +from resonon.utils import cubetools as tools +from spectronon.workbench.plugin import CubePlugin +import numpy +from resonon.utils.spec import SpecFilename, SpecBool, SpecCube +from resonon.utils.cubevault import CubeVault +from resonon.core.data.cube import Cube, DummyCube +from resonon.core.data import _util + + +class RadianceConversion(CubePlugin): + """Calculate radiance units based on a calibration pack (.zip) or cube""" + label = "Radiance From Raw Data" + position = 3 + userLevel = 1 + + def setup(self): + datacube = self.datacube + self.calpack_path = SpecFilename('Imager Calibration', + wildcard='Imager Calibration Pack, Calibration Pack, Calibration Cube (*.icp, *.zip, *.bip)|*.icp;*.zip; *.bip', + must_exist=True) + self.removedark = SpecBool("Auto Remove Dark Noise?", defaultValue=True) + self.darkcube = SpecCube("Dark Noise Cube", datacube, self.wb, requireMatchedBandCount=True, + requireMatchedSampleCount=True) + self.returnfloat = SpecBool("Return floating point?", defaultValue=False) + + def update(self): + datacube = self.datacube + if self.removedark.value: + self.darkcube.hidden = True + else: + self.darkcube.hidden = False + + def action(self): + datacube = self.datacube + data_bands = datacube.getBandCount() + data_samples = datacube.getSampleCount() + + # 这里的windowing parameters是指传感器(CCD)的有效窗口参数------------------------------------------------------------------- + # get the windowing parameters, falling back on full frames + try: + spatial_window = eval(datacube.getMetaValue('spatial window')) # 有效窗口的列数 + except: + spatial_window = None # (0,data_samples) + try: + band_window = eval(datacube.getMetaValue('band window')) # 有效窗口的行数 + except: + band_window = None # (0,data_bands) + try: + camera_binning = int(datacube.getMetaValue('camera spectral binning')) # ?????????????????????????????????????????????? + except: + camera_binning = 1 + try: + spectral_binning = int(datacube.getMetaValue('spectral binning')) # ?????????????????????????????????????????????? + except: + spectral_binning = 1 + + try: + sample_binning = int(datacube.getMetaValue('sample binning')) + except: + sample_binning = 1 + + try: + data_gain_db = int(round(datacube.getMetaValue('gain'))) + except KeyError: + data_gain_db = None + + try: + data_shutter = float(round(datacube.getMetaValue('shutter'))) + except KeyError: + data_shutter = None + try: + flip_frame = eval(datacube.getMetaValue('flip radiometric calibration')) + except: + try: + direction = datacube.getMetaValue('direction') + if direction == 'logo left': + flip_frame = False + else: + flip_frame = True + except: + flip_frame = False + + # self.calpack_path.value是定标文件(icp文件)路径 + if self.calpack_path.value[-3:] == 'zip' or self.calpack_path.value[-3:] == 'icp': + cvault = CubeVault(self.calpack_path.value) # 打开定标文件,定标文件中包含一个gainCube和一系列offsetCube + gainCube = cvault.get_gain_cube(meta={ + 'camera spectral binning': camera_binning}) # cube dict prefers any header item to none unless exact_match=True, is this the right behavior? + + offsetCube = cvault.get_offset_cube(meta={'camera spectral binning': camera_binning, + # is it a duplicate to ask for spectral binning on top of bands? + 'samples': data_samples, + 'bands': data_bands, + 'gain': data_gain_db, + 'shutter': data_shutter}) + print offsetCube.getPath() + + # window the data:从一帧中裁剪出有效窗口对应的图像矩阵 + gain_cube_array = gainCube.getFrame(0, asBIP=True) + offset_cube_array = offsetCube.getFrame(0, asBIP=True) + + if spatial_window: # 有效窗口的列数 + gain_cube_array = gain_cube_array[spatial_window[0]:spatial_window[1], :] + offset_cube_array = offset_cube_array[spatial_window[0]:spatial_window[1], :] + if band_window: # 有效窗口的行数 + gain_cube_array = gain_cube_array[:, band_window[0]:band_window[1]] + offset_cube_array = offset_cube_array[:, band_window[0]:band_window[1]] + + # a binned cube is scaled too large by the binning factors, so we need to divide the data by the binning.?????????????????????????????? + # since the data gets multiplied by the gain_cube_array, we can just divide it by the binning factor + try: + gain_spectral_binning = int(gainCube.getMetaValue('spectral binning')) + except: + gain_spectral_binning = 1 + + try: + gain_sample_binning = int(gainCube.getMetaValue('sample binning')) + except: + gain_sample_binning = 1 + + try: + offset_spectral_binning = int(offsetCube.getMetaValue('spectral binning')) + except: + offset_spectral_binning = 1 + + try: + offset_sample_binning = int(offsetCube.getMetaValue('sample binning')) + except: + offset_sample_binning = 1 + + gc_binned_gain = gain_cube_array / ( # 这里是除法!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!已理解,这是对的!!!!!!!!!!!!!!!!!! + float(spectral_binning) * sample_binning / (gain_spectral_binning * gain_sample_binning)) + # the offset of binned data is also scaled by the binning, so we need multiply the measured offset by the binning factor. + gc_binned_offset = offset_cube_array * ( # 这里成乘法!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!已理解,这是对的!!!!!!!!!!!!!!!!!! + float(spectral_binning) * sample_binning / (offset_spectral_binning * offset_sample_binning)) + + else: + georegcube = Cube(self.calpack_path.value) + # just copying the cube so that the legacy code still works + gainCube = georegcube + # window the data + gain_cube_array = georegcube.getFrame(1, asBIP=True) + offset_cube_array = georegcube.getFrame(0, asBIP=True) + + gc_binned_gain = gain_cube_array + gc_binned_offset = offset_cube_array + + if self.darkcube.value is not None: + correctionCube = self.wb.tree.getCube(self.darkcube.value) + if correctionCube.getSampleCount() != datacube.getSampleCount() or \ + correctionCube.getBandCount() != datacube.getBandCount(): + self.wb.postMessage('Dark Noise Cube frame size (%s) does not equal datacube frame size count(%s).' % \ + (str((correctionCube.getSampleCount(), correctionCube.getBandCount())), + str((datacube.getSampleCount(), datacube.getBandCount())))) + return + gc_binned_offset = tools.meanFrameOfCube(correctionCube, asBIP=True) + + + + + + + # determine how the frames should be averaged (to get frame sizes to match)?????????????????????????????????????????????? + gc_samples = gc_binned_gain.shape[0] + gc_bands = gc_binned_gain.shape[1] + oc_samples = gc_binned_offset.shape[0] + oc_bands = gc_binned_offset.shape[1] + + if data_samples > gc_samples or data_bands > gc_bands: + self.wb.postMessage('Correction Cube frame size (%s) is smaller than datacube frame size count(%s).' % \ + (str((gc_samples, gc_bands)), + str((datacube.getSampleCount(), datacube.getBandCount())))) + return + + gain_sample_aveby = gc_samples / data_samples + gain_band_aveby = gc_bands / data_bands + + # ave the correction cube to fit the incoming datacube (doesn't assume that the shape of the gain and offset are the same) + gc_binned_gain = tools.aveFrame(gc_binned_gain, spectralAve=gain_band_aveby, spatialAve=gain_sample_aveby, # ??????????????????????????????? + interleave="bip") + offset_sample_aveby = oc_samples / data_samples + offset_band_aveby = oc_bands / data_bands + gc_binned_offset = tools.aveFrame(gc_binned_offset, spectralAve=offset_band_aveby, + spatialAve=offset_sample_aveby, interleave="bip") + + if flip_frame: + gc_binned_gain = numpy.flipud(gc_binned_gain) + gc_binned_offset = numpy.flipud(gc_binned_offset) + + # calculate the gain and shutter differences!!!!!计算校正gain和offset,在ASD计算反射率时也有类似的操作,这相当于消除积分时间和暗电流的影响!!!!!!!!!!!!!! + try: + gc_gain = 10 ** (gainCube.getMetaValue('gain') / 20.) + except (AttributeError, KeyError): + gc_gain = 1.0 + gc_shutter = gainCube.getMetaValue('shutter') + try: + data_gain = 10 ** (datacube.getMetaValue('gain') / 20.) + except (AttributeError, KeyError): + data_gain = 1.0 + data_shutter = datacube.getMetaValue('shutter') + gain_factor = (gc_shutter * gc_gain) / (data_shutter * data_gain) + + # produce the correction frames******************************************* + adjusted_gain = gain_factor * gc_binned_gain + adjusted_offset = gc_binned_offset # we no longer have any adjustment to offset cubes + + # setup the outgoing cube************************************************* + newcube = datacube.getFramelessCopy(makeTypeFloat=self.returnfloat.value) + newcube.setMetaValue("interleave", "bip") + + for hdr_item in ("reflectance scale factor", "ceiling", "bit depth"): + try: + del (newcube._metadata[hdr_item]) + except: + pass + + # bug fix - calculate maxAllowed based on the dtype BEFORE converting to float + dtype = _util._enviType2NumpyDType(newcube.getMetaValue("data type")) + maxAllowed = _util.dataTypeMax(dtype) + lines = self.datacube.getLineCount() + + # For memory cubes, it is *much* for efficient to preallocate memory + try: + newcube.extendLineBuffer(lines) + except AttributeError: + # Disk cubes don't have this ability + pass + + # produce the new cube, scaling and clipping as necessary + for f in range(datacube.getLineCount()): + frame = datacube.getFrame(f, asBIP=True).astype('f') + if self.removedark.value or (self.darkcube.value is not None): + frame = numpy.clip((frame - adjusted_offset) * adjusted_gain, 0, maxAllowed) + else: + frame = numpy.clip((frame) * adjusted_gain, 0, maxAllowed) + newcube.appendFrame(frame.astype(dtype)) + return newcube + + def getDummyResult(self): + meta = self.datacube.getMetaDictCopy() + meta['interleave'] = 'bip' + for hdr_item in ("reflectance scale factor", "ceiling", "bit depth"): + if hdr_item in meta: + del meta[hdr_item] + + return DummyCube(meta) diff --git a/1.1radiance_calibration_300tc.py b/1.1radiance_calibration_300tc.py new file mode 100644 index 0000000..2010e1b --- /dev/null +++ b/1.1radiance_calibration_300tc.py @@ -0,0 +1,251 @@ +''' +1、此版本所需文件:dn影像、dark影像和asd测定的积分球辐亮度曲线 +2、处理过程:1)扣除暗电流;2)通过辐亮度曲线生成定标文件 +''' +import numpy as np +import pandas as pd +import sys, os, traceback, re +import shutil +from radiance_calibration_ui import Ui_MainWindow +from library.multithread import Worker +import sys, traceback +from osgeo import gdal + +from PyQt5.QtWidgets import QMainWindow, QFileDialog, QApplication +from PyQt5.QtCore import Qt + + +class EnterWindow(QMainWindow, Ui_MainWindow): + def __init__(self, parent=None): + super(EnterWindow, self).__init__(parent) + self.setupUi(self) + + self.radiance_calibration_object = RadianceCalibration() + + # self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + + self.rad_bt.clicked.connect(self.select_rad) + self.dn_bt.clicked.connect(self.select_dn) + self.dark_bt.clicked.connect(self.select_dark) + self.out_file_bt.clicked.connect(self.select_out_file) + + self.operate_bt.clicked.connect(self.operate) + + self.tmp_rad_file_path = None # 用于保存当前路径,下次打开就默认在此路径下 + self.tmp_dn_file_path = None # 用于保存当前路径,下次打开就默认在此路径下 + self.tmp_dark_file_path = None # 用于保存当前路径,下次打开就默认在此路径下 + self.tmp_out_file_path = None # 用于保存当前路径,下次打开就默认在此路径下 + + def select_rad(self): + if self.tmp_rad_file_path == None: + rad_file_path = QFileDialog.getOpenFileName(self, '选择asd辐亮度文件', os.path.dirname(__file__))[0] + + self.tmp_rad_file_path = os.path.dirname(rad_file_path) + elif self.tmp_rad_file_path is not None: + rad_file_path = QFileDialog.getOpenFileName(self, '选择asd辐亮度文件', self.tmp_rad_file_path)[0] + + self.tmp_rad_file_path = os.path.dirname(rad_file_path) + + self.radiance_calibration_object.asd_radiance_file_path = rad_file_path + self.rad_le.setText(rad_file_path) + + def select_dn(self): + if self.tmp_dn_file_path == None: + dn_file_path = QFileDialog.getOpenFileName(self, '选择dn影像', os.path.dirname(__file__))[0] + + self.tmp_dn_file_path = os.path.dirname(dn_file_path) + elif self.tmp_dn_file_path is not None: + dn_file_path = QFileDialog.getOpenFileName(self, '选择dn影像', self.tmp_dn_file_path)[0] + + self.tmp_dn_file_path = os.path.dirname(dn_file_path) + + self.radiance_calibration_object.dn_file_path = dn_file_path + self.dn_le.setText(dn_file_path) + + def select_dark(self): + if self.tmp_dark_file_path == None: + dark_file_path = QFileDialog.getOpenFileName(self, '选择dark影像', os.path.dirname(__file__))[0] + + self.tmp_dark_file_path = os.path.dirname(dark_file_path) + elif self.tmp_dark_file_path is not None: + dark_file_path = QFileDialog.getOpenFileName(self, '选择dark影像', self.tmp_dark_file_path)[0] + + self.tmp_dark_file_path = os.path.dirname(dark_file_path) + + self.radiance_calibration_object.dark_file_path = dark_file_path + self.dark_le.setText(dark_file_path) + + def select_out_file(self): + if self.tmp_out_file_path == None: + out_file_path = QFileDialog.getExistingDirectory(self, '选择输出路径', os.path.dirname(__file__)) + + self.tmp_out_file_path = out_file_path + elif self.tmp_out_file_path is not None: + out_file_path = QFileDialog.getExistingDirectory(self, '选择输出路径', self.tmp_out_file_path) + + self.tmp_out_file_path = out_file_path + + self.radiance_calibration_object.out_file_path = out_file_path + self.out_file_le.setText(out_file_path) + + def operate(self): + self.radiance_calibration_object.operate() + + +class RadianceCalibration(): + def __init__(self): + # asd_radiance_file = os.path.dirname(__file__) + '\\corning_radance.txt' + # img_file_path = os.path.dirname(__file__) + '\\jfq_dn' + # img_dark_file_path = os.path.dirname(__file__) + '\\jfq_dn_dark' + # out_file = os.path.dirname(__file__) + '\\jfq_dn_gain' + + self.asd_radiance_file_path = None + self.dn_file_path = None + self.dark_file_path = None + + self.img_data = None + self.img_dark_data = None + + self.out_file_path = None + + def get_envi_header_dict(self, hdr_file): + with open(hdr_file, encoding='utf-8') as file_obj: + contents = file_obj.read() + + # Get all "key = {val}" type matches + regex = re.compile(r'^(.+?)\s*=\s*({\s*.*?\n*.*?})$', re.M | re.I) + matches = regex.findall(contents) + + # Remove them from the header + subhdr = regex.sub('', contents) + + # Get all "key = val" type matches + regex = re.compile(r'^(.+?)\s*=\s*(.*?)$', re.M | re.I) + matches.extend(regex.findall(subhdr)) + + hdr_fields = dict(matches) + keys_delete = [] + for key in hdr_fields.keys(): + if ( + key == "interleave" or key == "byte order" or key == "data type" or key == "samples" or key == "bands" or key == "lines" or key == "framerate"): + keys_delete.append(key) + + for x in range(len(keys_delete)): + hdr_fields.pop(keys_delete[x]) + + return hdr_fields + + def get_hdr_filename(self, file_path): + return os.path.splitext(file_path)[0] + ".hdr" + + def get_hdr_filename_with_bip(self, file_path): + return os.path.splitext(file_path)[0] + ".bip.hdr" + + def write_fields_to_hdrfile(self, fields, hdr_file): + with open(hdr_file, "a", encoding='utf-8') as f: + for key in fields.keys(): + f.write(key + " = " + fields[key] + "\n") + + def process_hdr(self, hdr_file_path, envi_header_dict): + self.write_fields_to_hdrfile(envi_header_dict, self.get_hdr_filename(hdr_file_path)) + shutil.copyfile(self.get_hdr_filename(hdr_file_path), self.get_hdr_filename_with_bip(hdr_file_path)) + os.remove(self.get_hdr_filename(hdr_file_path)) + + # 读图像文件 + def read_img(self, 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为例 + def write_img(self, 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_Float64, + options=["INTERLEAVE=BIP"]) + for i in range(band): + dst_ds.GetRasterBand(i + 1).WriteArray(data[i, :, :]) # gdal的band从1开始,所以dst_ds.GetRasterBand(i+1) + dst_ds = None + + def operate(self): + try: + # 读取asd辐亮度数据 + data = pd.read_csv(self.asd_radiance_file_path, sep='\t', dtype=np.float64, header=None) + self.asd_radiance = np.array(data) + + # 读取影像 + img_proj, img_geotrans, self.img_data = self.read_img(self.dn_file_path) + dn_hdr = self.get_envi_header_dict(self.get_hdr_filename(self.dn_file_path)) + img_dark_proj, img_dark_geotrans, self.img_dark_data = self.read_img(self.dark_file_path) + dark_hdr = self.get_envi_header_dict(self.get_hdr_filename(self.dark_file_path)) + + # 将影像所有行平均,得到一行(帧)影像 + img_data_ave = np.mean(self.img_data, axis=1) + img_dark_data_ave = np.mean(self.img_dark_data, axis=1) + + # 去除暗电流 + img_data_ave_rmdark = img_data_ave - img_dark_data_ave + img_dark_data_ave = img_dark_data_ave + 50 + + gain = np.empty((img_data_ave_rmdark.shape[0], 1, img_data_ave_rmdark.shape[1])) + offset = np.empty((img_data_ave_rmdark.shape[0], 1, img_data_ave_rmdark.shape[1])) + for i in range(gain.shape[2]): + gain[:, 0, i] = self.asd_radiance[:, 1] / img_data_ave_rmdark[:, i] + offset[:, 0, i] = img_dark_data_ave[:, i] + + gain_name = os.path.join(self.out_file_path, "gain.bip") + offset_name = os.path.join(self.out_file_path, "offset.bip") + self.write_img(gain_name, gain) + self.process_hdr(gain_name, dn_hdr) + self.write_img(offset_name, offset) + self.process_hdr(offset_name, dark_hdr) + except: + traceback.print_exc() + + def operate_without_dark(self): + try: + # 读取asd辐亮度数据 + data = pd.read_csv(self.asd_radiance_file_path, sep='\t', dtype=np.float64, header=None) + self.asd_radiance = np.array(data) + + # 读取影像 + img_proj, img_geotrans, self.img_data = self.read_img(self.dn_file_path) + + # 将影像所有行平均,得到一行(帧)影像 + img_data_ave = np.mean(self.img_data, axis=1) + + gain = np.empty((img_data_ave.shape[0], 1, img_data_ave.shape[1])) + for i in range(gain.shape[2]): + gain[:, 0, i] = self.asd_radiance[:, 1] / img_data_ave[:, i] + + self.write_img(self.out_file_path, gain) + except: + traceback.print_exc() + + +if __name__ == '__main__': + app = QApplication(sys.argv) + + # 实例化主窗口 + enter_window_instance = EnterWindow() + enter_window_instance.show() + + sys.exit(app.exec_()) diff --git a/1.2radiance_calibration_corning410.py b/1.2radiance_calibration_corning410.py new file mode 100644 index 0000000..a7f22ca --- /dev/null +++ b/1.2radiance_calibration_corning410.py @@ -0,0 +1,119 @@ +''' +1、此版本所需文件:dn影像和asd测定的积分球辐亮度曲线 +2、处理过程:不需要扣除暗电流,因为dn影像在采集时已经扣除了暗电流; + 1)通过辐亮度曲线生成定标文件 +''' +import numpy as np +import pandas as pd +import sys, os, traceback +from library.image_reader_writer import ImageReaderWriter +from radiance_calibration_ui import Ui_MainWindow +from library.multithread import Worker + +from PyQt5.QtWidgets import QMainWindow, QFileDialog, QApplication +from PyQt5.QtCore import Qt + + +class EnterWindow(QMainWindow, Ui_MainWindow): + def __init__(self, parent=None): + super(EnterWindow, self).__init__(parent) + self.setupUi(self) + + self.radiance_calibration_object = RadianceCalibration() + + # self.setWindowState(Qt.WindowMaximized) # 初始化时就最大化窗口 + + self.rad_bt.clicked.connect(self.select_rad) + self.dn_bt.clicked.connect(self.select_dn) + self.out_file_bt.clicked.connect(self.select_out_file) + + self.operate_bt.clicked.connect(self.operate) + + self.tmp_rad_file_path = None # 用于保存当前路径,下次打开就默认在此路径下 + self.tmp_dn_file_path = None # 用于保存当前路径,下次打开就默认在此路径下 + self.tmp_out_file_path = None # 用于保存当前路径,下次打开就默认在此路径下 + + def select_rad(self): + if self.tmp_rad_file_path == None: + rad_file_path = QFileDialog.getOpenFileName(self, '选择asd辐亮度文件', os.path.dirname(__file__))[0] + + self.tmp_rad_file_path = os.path.dirname(rad_file_path) + elif self.tmp_rad_file_path is not None: + rad_file_path = QFileDialog.getOpenFileName(self, '选择asd辐亮度文件', self.tmp_rad_file_path)[0] + + self.tmp_rad_file_path = os.path.dirname(rad_file_path) + + self.radiance_calibration_object.asd_radiance_file_path = rad_file_path + self.rad_le.setText(rad_file_path) + + def select_dn(self): + if self.tmp_dn_file_path == None: + dn_file_path = QFileDialog.getOpenFileName(self, '选择dn影像', os.path.dirname(__file__))[0] + + self.tmp_dn_file_path = os.path.dirname(dn_file_path) + elif self.tmp_dn_file_path is not None: + dn_file_path = QFileDialog.getOpenFileName(self, '选择dn影像', self.tmp_dn_file_path)[0] + + self.tmp_dn_file_path = os.path.dirname(dn_file_path) + + self.radiance_calibration_object.dn_file_path = dn_file_path + self.dn_le.setText(dn_file_path) + + def select_out_file(self): + if self.tmp_out_file_path == None: + out_file_path = QFileDialog.getSaveFileName(self, '选择输出文件路径和文件名', os.path.dirname(__file__))[0] + + self.tmp_out_file_path = os.path.dirname(out_file_path) + elif self.tmp_out_file_path is not None: + out_file_path = QFileDialog.getSaveFileName(self, '选择输出文件路径和文件名', self.tmp_out_file_path)[0] + + self.tmp_out_file_path = os.path.dirname(out_file_path) + + self.radiance_calibration_object.out_file_path = out_file_path + self.out_file_le.setText(out_file_path) + + def operate(self): + self.radiance_calibration_object.operate() + + +class RadianceCalibration(): + def __init__(self): + # asd_radiance_file = os.path.dirname(__file__) + '\\corning_radance.txt' + # img_file_path = os.path.dirname(__file__) + '\\jfq_dn' + # out_file = os.path.dirname(__file__) + '\\jfq_dn_gain' + + self.asd_radiance_file_path = None + self.dn_file_path = None + + self.img_data = None + + self.out_file_path = None + + def operate(self): + try: + # 读取asd辐亮度数据 + data = pd.read_csv(self.asd_radiance_file_path, sep='\t', dtype=np.float64, header=None) + self.asd_radiance = np.array(data) + # 读取影像 + img_proj, img_geotrans, self.img_data = ImageReaderWriter.read_img(self.dn_file_path) + + # 将影像所有行平均,得到一行(帧)影像 + img_data_ave = np.mean(self.img_data, axis=1) + + gain = np.empty((img_data_ave.shape[0], 1, img_data_ave.shape[1])) + for i in range(gain.shape[2]): + gain[:, 0, i] = self.asd_radiance[:, 1] / img_data_ave[:, i] + + ImageReaderWriter.write_img(self.out_file_path, gain) + except: + traceback.print_exc() + + +if __name__ == '__main__': + app = QApplication(sys.argv) + + # 实例化主窗口 + enter_window_instance = EnterWindow() + enter_window_instance.show() + + sys.exit(app.exec_()) diff --git a/2radiance_conversion_corning410.py b/2radiance_conversion_corning410.py new file mode 100644 index 0000000..5cd3b7f --- /dev/null +++ b/2radiance_conversion_corning410.py @@ -0,0 +1,101 @@ +''' +https://blog.csdn.net/vonuo/article/details/74783291 +本方法是使用asd的方法来进行corning的辐亮度定标(resonon的方法感觉和此方法差不多) +''' +from osgeo import gdal +import os, math +import sys +import easygui +import numpy as np +import pandas as pd +import xlwt + +# 读写影像类 +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 + +# 是否转辐亮度:0→不转,1→转 +rad_switch = 0 + +img = r'D:\py_program\corning410\record_system_v24\baiban_record' +img_baiban = r'D:\py_program\corning410\record_system_v24\baiban' +img_gain = r'D:\py_program\corning410\corning410_radiance_calibration\jfq_dn_gain' +img_offset = r'D:\py_program\corning410\record_system_v24\dark' + + +dirpath = os.path.splitext(img) + +# 读取影像 +proj, geotrans, data = Grid.read_img(img) +proj_baiban, geotrans_baiban, data_baiban = Grid.read_img(img_baiban) +proj_gain, geotrans_gain, data_gain = Grid.read_img(img_gain) +proj_offset, geotrans_offset, data_offset = Grid.read_img(img_offset) + +data_baiban = np.mean(data_baiban, axis=1) +data_offset = np.mean(data_offset, axis=1) + +if rad_switch == 1: + # 计算辐射定标参数 + cal_it = 6059 + target_it = 200004 + gain_scale = cal_it / target_it + data_gain_adjust = data_gain * gain_scale + + # 影像和白板:1、扣除暗电流;2、转换成辐亮度; + data_baiban = data_baiban - data_offset # 白板扣除暗电流 + data_baiban_rad = data_baiban * data_gain_adjust[:, 0, :] # 白板转辐亮度 + + data_rad = np.empty(data.shape) + for i in range(data.shape[1]): + data_rad[:, i, :] = (data[:, i, :] - data_offset) * data_gain_adjust[:, 0, :] # 转辐亮度 + Grid.write_img(dirpath[0] + '_rad', data_rad) + + # 转换成反射率 + data_rad_ref = np.empty(data.shape) + for i in range(data.shape[1]): + data_rad_ref[:, i, :] = data_rad[:, i, :] / data_baiban_rad # 转反射率 + + Grid.write_img(dirpath[0] + '_rad_ref', data_rad_ref) +elif rad_switch == 0: + # 影像和白板扣除暗电流 + data_baiban = data_baiban - data_offset + data_rmdark = np.empty(data.shape) + for i in range(data.shape[1]): + data_rmdark[:, i, :] = (data[:, i, :] - data_offset) + + # 转反射率 + data_ref = np.empty(data.shape) + for i in range(data.shape[1]): + data_ref[:, i, :] = data_rmdark[:, i, :] / data_baiban # 转反射率 + Grid.write_img(dirpath[0] + '_ref', data_ref) diff --git a/corning_radance.txt b/corning_radance.txt new file mode 100644 index 0000000..0d49180 --- /dev/null +++ b/corning_radance.txt @@ -0,0 +1,300 @@ +397.959198 0.016826 +399.958771 0.017833 +401.958313 0.018945 +403.957886 0.020166 +405.957458 0.021402 +407.957031 0.022727 +409.956573 0.024146 +411.956146 0.025537 +413.955719 0.026962 +415.955261 0.028384 +417.954834 0.029758 +419.954407 0.031123 +421.953949 0.032428 +423.953522 0.033733 +425.953094 0.034996 +427.952667 0.036257 +429.952209 0.037488 +431.951782 0.038767 +433.951355 0.040043 +435.950897 0.041326 +437.95047 0.0426 +439.950043 0.043897 +441.949615 0.045203 +443.949158 0.046568 +445.94873 0.047932 +447.948303 0.049302 +449.947845 0.050722 +451.947418 0.052172 +453.946991 0.053657 +455.946564 0.055149 +457.946106 0.056651 +459.945679 0.058194 +461.945251 0.059754 +463.944794 0.061342 +465.944366 0.062949 +467.943939 0.064564 +469.943512 0.066216 +471.943054 0.06789 +473.942627 0.069578 +475.9422 0.07129 +477.941742 0.073023 +479.941315 0.07477 +481.940887 0.07657 +483.94046 0.078357 +485.940002 0.080167 +487.939575 0.081986 +489.939148 0.083853 +491.93869 0.085709 +493.938263 0.087612 +495.937836 0.089504 +497.937408 0.091452 +499.936951 0.093356 +501.936523 0.095327 +503.936096 0.097268 +505.935638 0.099255 +507.935211 0.101218 +509.934784 0.103205 +511.934357 0.105188 +513.933899 0.107211 +515.933472 0.109212 +517.933044 0.111223 +519.932617 0.11324 +521.93219 0.115274 +523.931702 0.117286 +525.931274 0.119314 +527.930847 0.121342 +529.93042 0.123381 +531.929993 0.125442 +533.929565 0.127516 +535.929138 0.129566 +537.92865 0.131653 +539.928223 0.1337 +541.927795 0.13577 +543.927368 0.137831 +545.926941 0.1399 +547.926514 0.141954 +549.926086 0.144 +551.925598 0.146041 +553.925171 0.148075 +555.924744 0.150128 +557.924316 0.152166 +559.923889 0.154153 +561.923462 0.156169 +563.923035 0.158193 +565.922546 0.160218 +567.922119 0.162267 +569.921692 0.164324 +571.921265 0.166323 +573.920837 0.168311 +575.92041 0.170291 +577.919983 0.172281 +579.919495 0.17428 +581.919067 0.176234 +583.91864 0.178223 +585.918213 0.180202 +587.917786 0.182168 +589.917358 0.184131 +591.916931 0.186068 +593.916443 0.187966 +595.916016 0.189889 +597.915588 0.191788 +599.915161 0.193692 +601.914734 0.195588 +603.914307 0.197465 +605.913879 0.199339 +607.913391 0.201193 +609.912964 0.203046 +611.912537 0.204877 +613.912109 0.20672 +615.911682 0.208548 +617.911255 0.210348 +619.910828 0.212157 +621.910339 0.21397 +623.909912 0.215746 +625.909485 0.217497 +627.909058 0.219244 +629.90863 0.220984 +631.908203 0.222711 +633.907776 0.224391 +635.907288 0.226061 +637.90686 0.227713 +639.906433 0.229346 +641.906006 0.230951 +643.905579 0.232568 +645.905151 0.234142 +647.904724 0.235708 +649.904236 0.23727 +651.903809 0.238786 +653.903381 0.24031 +655.902954 0.241785 +657.902527 0.243246 +659.9021 0.244666 +661.901672 0.246061 +663.901184 0.247443 +665.900757 0.248771 +667.90033 0.250111 +669.899902 0.251449 +671.899475 0.252819 +673.899048 0.254173 +675.898621 0.255553 +677.898132 0.256968 +679.897705 0.258384 +681.897278 0.259837 +683.896851 0.261271 +685.896423 0.262646 +687.895996 0.264113 +689.895569 0.265597 +691.895081 0.267087 +693.894653 0.26856 +695.894226 0.270029 +697.893799 0.271537 +699.893372 0.273024 +701.892944 0.274497 +703.892517 0.27598 +705.892029 0.277394 +707.891602 0.278829 +709.891174 0.280229 +711.890747 0.281586 +713.89032 0.282901 +715.889893 0.284185 +717.889465 0.285366 +719.888977 0.286532 +721.88855 0.287701 +723.888123 0.288782 +725.887695 0.289826 +727.887268 0.290799 +729.886841 0.291714 +731.886414 0.292611 +733.885925 0.293465 +735.885498 0.294267 +737.885071 0.295024 +739.884644 0.295758 +741.884216 0.296422 +743.883789 0.297081 +745.883362 0.297755 +747.882874 0.2983 +749.882446 0.298894 +751.882019 0.299411 +753.881592 0.299927 +755.881165 0.300439 +757.880737 0.300789 +759.88031 0.300426 +761.879822 0.300811 +763.879395 0.301391 +765.878967 0.302141 +767.87854 0.302745 +769.878113 0.303104 +771.877686 0.303389 +773.877258 0.303661 +775.87677 0.303844 +777.876343 0.304019 +779.875916 0.304218 +781.875488 0.304372 +783.875061 0.304507 +785.874634 0.304636 +787.874146 0.304772 +789.873718 0.3049 +791.873291 0.305011 +793.872864 0.305106 +795.872437 0.305178 +797.872009 0.305277 +799.871582 0.305334 +801.871094 0.305394 +803.870667 0.305456 +805.870239 0.30557 +807.869812 0.305647 +809.869385 0.305704 +811.868958 0.305731 +813.86853 0.305728 +815.868042 0.305726 +817.867615 0.305811 +819.867188 0.305906 +821.86676 0.306007 +823.866333 0.30608 +825.865906 0.306267 +827.865479 0.306351 +829.86499 0.306463 +831.864563 0.306576 +833.864136 0.306741 +835.863708 0.306931 +837.863281 0.307127 +839.862854 0.307383 +841.862427 0.307674 +843.861938 0.307943 +845.861511 0.308249 +847.861084 0.308576 +849.860657 0.308906 +851.860229 0.309256 +853.859802 0.309625 +855.859375 0.310032 +857.858887 0.310487 +859.858459 0.310902 +861.858032 0.311381 +863.857605 0.311833 +865.857178 0.312303 +867.85675 0.312768 +869.856323 0.313248 +871.855835 0.313723 +873.855408 0.314215 +875.85498 0.314768 +877.854553 0.315275 +879.854126 0.315828 +881.853699 0.316369 +883.853271 0.316931 +885.852783 0.3174 +887.852356 0.317971 +889.851929 0.318538 +891.851501 0.319065 +893.851074 0.319602 +895.850647 0.32009 +897.85022 0.320544 +899.849731 0.320979 +901.849304 0.321402 +903.848877 0.321871 +905.84845 0.32228 +907.848022 0.322704 +909.847595 0.323072 +911.847168 0.323442 +913.84668 0.323902 +915.846252 0.324326 +917.845825 0.324707 +919.845398 0.325192 +921.844971 0.325606 +923.844543 0.326058 +925.844116 0.326512 +927.843628 0.326828 +929.843201 0.326976 +931.842773 0.327033 +933.842346 0.327205 +935.841919 0.327592 +937.841492 0.32804 +939.841064 0.328472 +941.840576 0.328777 +943.840149 0.32892 +945.839722 0.329077 +947.839294 0.329235 +949.838867 0.329399 +951.83844 0.329527 +953.838013 0.329495 +955.837524 0.32966 +957.837097 0.329701 +959.83667 0.329649 +961.836243 0.329759 +963.835815 0.329742 +965.835388 0.329725 +967.834961 0.329847 +969.834473 0.329885 +971.834045 0.329977 +973.833618 0.330035 +975.833191 0.330221 +977.832764 0.33022 +979.832336 0.330393 +981.831909 0.330477 +983.831421 0.330686 +985.830994 0.330845 +987.830566 0.331049 +989.830139 0.331023 +991.829712 0.331329 +993.829285 0.331352 +995.828857 0.331532 diff --git a/radiance_calibration_ui.py b/radiance_calibration_ui.py new file mode 100644 index 0000000..d6bf1f1 --- /dev/null +++ b/radiance_calibration_ui.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'radiance_calibration_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_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(964, 621) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget) + self.gridLayout_2.setObjectName("gridLayout_2") + self.frame = QtWidgets.QFrame(self.centralwidget) + self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame.setObjectName("frame") + self.gridLayout = QtWidgets.QGridLayout(self.frame) + self.gridLayout.setObjectName("gridLayout") + self.label = QtWidgets.QLabel(self.frame) + self.label.setAlignment(QtCore.Qt.AlignCenter) + self.label.setObjectName("label") + self.gridLayout.addWidget(self.label, 0, 0, 1, 1) + self.rad_le = QtWidgets.QLineEdit(self.frame) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.rad_le.sizePolicy().hasHeightForWidth()) + self.rad_le.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setPointSize(18) + self.rad_le.setFont(font) + self.rad_le.setReadOnly(True) + self.rad_le.setObjectName("rad_le") + self.gridLayout.addWidget(self.rad_le, 0, 1, 1, 1) + self.rad_bt = QtWidgets.QPushButton(self.frame) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.rad_bt.sizePolicy().hasHeightForWidth()) + self.rad_bt.setSizePolicy(sizePolicy) + self.rad_bt.setObjectName("rad_bt") + self.gridLayout.addWidget(self.rad_bt, 0, 2, 1, 1) + self.label_3 = QtWidgets.QLabel(self.frame) + self.label_3.setAlignment(QtCore.Qt.AlignCenter) + self.label_3.setObjectName("label_3") + self.gridLayout.addWidget(self.label_3, 1, 0, 1, 1) + self.dn_le = QtWidgets.QLineEdit(self.frame) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.dn_le.sizePolicy().hasHeightForWidth()) + self.dn_le.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setPointSize(18) + self.dn_le.setFont(font) + self.dn_le.setReadOnly(True) + self.dn_le.setObjectName("dn_le") + self.gridLayout.addWidget(self.dn_le, 1, 1, 1, 1) + self.dn_bt = QtWidgets.QPushButton(self.frame) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.dn_bt.sizePolicy().hasHeightForWidth()) + self.dn_bt.setSizePolicy(sizePolicy) + self.dn_bt.setObjectName("dn_bt") + self.gridLayout.addWidget(self.dn_bt, 1, 2, 1, 1) + self.dark_checkBox = QtWidgets.QCheckBox(self.frame) + self.dark_checkBox.setObjectName("dark_checkBox") + self.gridLayout.addWidget(self.dark_checkBox, 2, 0, 1, 1) + self.dark_le = QtWidgets.QLineEdit(self.frame) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.dark_le.sizePolicy().hasHeightForWidth()) + self.dark_le.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setPointSize(18) + self.dark_le.setFont(font) + self.dark_le.setReadOnly(True) + self.dark_le.setObjectName("dark_le") + self.gridLayout.addWidget(self.dark_le, 2, 1, 1, 1) + self.dark_bt = QtWidgets.QPushButton(self.frame) + self.dark_bt.setEnabled(True) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.dark_bt.sizePolicy().hasHeightForWidth()) + self.dark_bt.setSizePolicy(sizePolicy) + self.dark_bt.setObjectName("dark_bt") + self.gridLayout.addWidget(self.dark_bt, 2, 2, 1, 1) + self.label_4 = QtWidgets.QLabel(self.frame) + self.label_4.setAlignment(QtCore.Qt.AlignCenter) + self.label_4.setObjectName("label_4") + self.gridLayout.addWidget(self.label_4, 3, 0, 1, 1) + self.out_file_le = QtWidgets.QLineEdit(self.frame) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.out_file_le.sizePolicy().hasHeightForWidth()) + self.out_file_le.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setPointSize(18) + self.out_file_le.setFont(font) + self.out_file_le.setReadOnly(True) + self.out_file_le.setObjectName("out_file_le") + self.gridLayout.addWidget(self.out_file_le, 3, 1, 1, 1) + self.out_file_bt = QtWidgets.QPushButton(self.frame) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.out_file_bt.sizePolicy().hasHeightForWidth()) + self.out_file_bt.setSizePolicy(sizePolicy) + self.out_file_bt.setObjectName("out_file_bt") + self.gridLayout.addWidget(self.out_file_bt, 3, 2, 1, 1) + self.gridLayout_2.addWidget(self.frame, 0, 0, 1, 1) + self.operate_bt = QtWidgets.QPushButton(self.centralwidget) + self.operate_bt.setMaximumSize(QtCore.QSize(16777215, 60)) + self.operate_bt.setObjectName("operate_bt") + self.gridLayout_2.addWidget(self.operate_bt, 1, 0, 1, 1) + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(MainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 964, 26)) + self.menubar.setObjectName("menubar") + MainWindow.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) + self.label.setText(_translate("MainWindow", "ASD辐亮度")) + self.rad_bt.setText(_translate("MainWindow", "浏览...")) + self.label_3.setText(_translate("MainWindow", "DN")) + self.dn_bt.setText(_translate("MainWindow", "浏览...")) + self.dark_checkBox.setText(_translate("MainWindow", "dark_checkBox")) + self.dark_bt.setText(_translate("MainWindow", "浏览...")) + self.label_4.setText(_translate("MainWindow", "输出路径")) + self.out_file_bt.setText(_translate("MainWindow", "浏览...")) + self.operate_bt.setText(_translate("MainWindow", "执行")) diff --git a/radiance_calibration_ui.ui b/radiance_calibration_ui.ui new file mode 100644 index 0000000..112e06d --- /dev/null +++ b/radiance_calibration_ui.ui @@ -0,0 +1,226 @@ + + + MainWindow + + + + 0 + 0 + 964 + 621 + + + + MainWindow + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + ASD辐亮度 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 18 + + + + true + + + + + + + + 0 + 0 + + + + 浏览... + + + + + + + DN + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 18 + + + + true + + + + + + + + 0 + 0 + + + + 浏览... + + + + + + + dark + + + true + + + + + + + + 0 + 0 + + + + + 18 + + + + true + + + + + + + true + + + + 0 + 0 + + + + 浏览... + + + + + + + 输出路径 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 18 + + + + true + + + + + + + + 0 + 0 + + + + 浏览... + + + + + + + + + + + 16777215 + 60 + + + + 执行 + + + + + + + + + 0 + 0 + 964 + 23 + + + + + + + +