def configFilterTypeButtons(self, name=u"default", checked=False, xPos=0, yPos=0, idButton=0): button = QRadioButton(self) button.setObjectName(name) button.setEnabled(True) button.setGeometry(QRect(xPos, yPos, 82, 17)) button.setCursor(QCursor(Qt.PointingHandCursor)) button.setChecked(checked) lam = lambda id=idButton: self.buttonChecked(id) self.connect(button, SIGNAL("clicked()"), lam) self.filterTypeButtons.addButton(button, idButton)
def add_horizontal_splitter(self, layout): splitter = QSplitter() splitter.setOrientation(Qt.Orientation.Vertical) layout.addWidget(splitter) # ADD TOP top_widget = QWidget(splitter) top = QVBoxLayout(top_widget) # NORMAL btn = FillPushButton('Push Button') top.layout().addWidget(btn) #DISABLED btn = FillPushButton('Push Button Disabled') btn.setEnabled(False) top.layout().addWidget(btn) # ADD BOTTOM bottom_widget = QWidget(splitter) right = QGridLayout(bottom_widget) # NORMAL cbx = QCheckBox('Check Box') right.addWidget(cbx) #DISABLED cbx = QCheckBox('Check Box Disabled') cbx.setEnabled(False) right.addWidget(cbx) rob = QRadioButton('Radio Button') right.addWidget(rob) rob = QRadioButton('Radio Button Disabled') rob.setEnabled(False) right.addWidget(rob)
class ComparisonWidget(ToolWidget): def __init__(self, filename, image, parent=None): super(ComparisonWidget, self).__init__(parent) load_button = QPushButton(self.tr('Load reference image...')) self.comp_label = QLabel(self.tr('Comparison:')) self.normal_radio = QRadioButton(self.tr('Normal')) self.normal_radio.setToolTip(self.tr('Show reference (raw pixels)')) self.normal_radio.setChecked(True) self.difference_radio = QRadioButton(self.tr('Difference')) self.difference_radio.setToolTip( self.tr('Show evidence/reference difference')) self.ssim_radio = QRadioButton(self.tr('SSIM Map')) self.ssim_radio.setToolTip(self.tr('Structure similarity quality map')) self.butter_radio = QRadioButton(self.tr('Butteraugli')) self.butter_radio.setToolTip( self.tr('Butteraugli spatial changes heatmap')) self.gray_check = QCheckBox(self.tr('Grayscale')) self.gray_check.setToolTip(self.tr('Show desaturated output')) self.equalize_check = QCheckBox(self.tr('Equalized')) self.equalize_check.setToolTip(self.tr('Apply histogram equalization')) self.last_radio = self.normal_radio self.metric_button = QPushButton(self.tr('Compute metrics')) self.metric_button.setToolTip( self.tr('Image quality assessment metrics')) self.evidence = image self.reference = self.difference = self.ssim_map = self.butter_map = None basename = os.path.basename(filename) self.evidence_viewer = ImageViewer( self.evidence, None, self.tr('Evidence: {}'.format(basename))) self.reference_viewer = ImageViewer(np.full_like(self.evidence, 127), None, self.tr('Reference')) self.table_widget = QTableWidget(21, 3) self.table_widget.setHorizontalHeaderLabels( [self.tr('Metric'), self.tr('Value'), self.tr('Better')]) self.table_widget.setItem(0, 0, QTableWidgetItem(self.tr('RMSE'))) self.table_widget.setItem( 0, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(0, 0).setToolTip( self. tr('Root Mean Square Error (RMSE) is commonly used to compare \n' 'the difference between the reference and evidence images \n' 'by directly computing the variation in pixel values. \n' 'The combined image is close to the reference image when \n' 'RMSE value is zero. RMSE is a good indicator of the spectral \n' 'quality of the reference image.')) self.table_widget.setItem(1, 0, QTableWidgetItem(self.tr('SAM'))) self.table_widget.setItem( 1, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(1, 0).setToolTip( self. tr('It computes the spectral angle between the pixel, vector of the \n' 'evidence image and reference image. It is worked out in either \n' 'degrees or radians. It is performed on a pixel-by-pixel base. \n' 'A SAM equal to zero denotes the absence of spectral distortion.' )) self.table_widget.setItem(2, 0, QTableWidgetItem(self.tr('ERGAS'))) self.table_widget.setItem( 2, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(2, 0).setToolTip( self. tr('It is used to compute the quality of reference image in terms \n' 'of normalized average error of each band of the reference image. \n' 'Increase in the value of ERGAS indicates distortion in the \n' 'reference image, lower value of ERGAS indicates that it is \n' 'similar to the reference image.')) self.table_widget.setItem(3, 0, QTableWidgetItem(self.tr('MB'))) self.table_widget.setItem( 3, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(3, 0).setToolTip( self. tr('Mean Bias is the difference between the mean of the evidence \n' 'image and reference image. The ideal value is zero and indicates \n' 'that the evidence and reference images are similar. Mean value \n' 'refers to the grey level of pixels in an image.')) self.table_widget.setItem(4, 0, QTableWidgetItem(self.tr('PFE'))) self.table_widget.setItem( 4, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(4, 0).setToolTip( self. tr('It computes the norm of the difference between the corresponding \n' 'pixels of the reference and fused image to the norm of the reference \n' 'image. When the calculated value is zero, it indicates that both the \n' 'reference and fused images are similar and value will be increased \n' 'when the merged image is not similar to the reference image.')) self.table_widget.setItem(5, 0, QTableWidgetItem(self.tr('PSNR'))) self.table_widget.setItem( 5, 2, QTableWidgetItem(QIcon('gui/icons/high.svg'), '(+' + u'\u221e' + ')')) self.table_widget.item(5, 0).setToolTip( self. tr('It is widely used metric it is computed by the number of gray levels \n' 'in the image divided by the corresponding pixels in the evidence and \n' 'the reference images. When the value is high, both images are similar.' )) self.table_widget.setItem(6, 0, QTableWidgetItem(self.tr('PSNR-B'))) self.table_widget.setItem( 6, 2, QTableWidgetItem(QIcon('gui/icons/high.svg'), '(+' + u'\u221e' + ')')) self.table_widget.item(6, 0).setToolTip( self.tr('PSNR with Blocking Effect Factor.')) self.table_widget.setItem(7, 0, QTableWidgetItem(self.tr('SSIM'))) self.table_widget.setItem( 7, 2, QTableWidgetItem(QIcon('gui/icons/high.svg'), '(1)')) self.table_widget.item(7, 0).setToolTip( self. tr('SSIM is used to compare the local patterns of pixel intensities between \n' ' the reference and fused images. The range varies between -1 to 1. \n' 'The value 1 indicates the reference and fused images are similar.' )) self.table_widget.setItem(8, 0, QTableWidgetItem(self.tr('MS-SSIM'))) self.table_widget.setItem( 8, 2, QTableWidgetItem(QIcon('gui/icons/high.svg'), '(1)')) self.table_widget.item(8, 0).setToolTip( self.tr('Multiscale version of SSIM.')) self.table_widget.setItem(9, 0, QTableWidgetItem(self.tr('RASE'))) self.table_widget.setItem( 9, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(9, 0).setToolTip( self.tr('Relative average spectral error')) self.table_widget.setItem(10, 0, QTableWidgetItem(self.tr('SCC'))) self.table_widget.setItem( 10, 2, QTableWidgetItem(QIcon('gui/icons/high.svg'), '(1)')) self.table_widget.item(10, 0).setToolTip( self.tr('Spatial Correlation Coefficient')) self.table_widget.setItem(11, 0, QTableWidgetItem(self.tr('UQI'))) self.table_widget.setItem( 11, 2, QTableWidgetItem(QIcon('gui/icons/high.svg'), '(1)')) self.table_widget.item(11, 0).setToolTip( self.tr('Universal Image Quality Index')) self.table_widget.setItem(12, 0, QTableWidgetItem(self.tr('VIF-P'))) self.table_widget.setItem( 12, 2, QTableWidgetItem(QIcon('gui/icons/high.svg'), '(1)')) self.table_widget.item(12, 0).setToolTip( self.tr('Pixel-based Visual Information Fidelity')) self.table_widget.setItem(13, 0, QTableWidgetItem(self.tr('SSIMulacra'))) self.table_widget.setItem( 13, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(13, 0).setToolTip( self.tr('Structural SIMilarity Unveiling Local ' 'And Compression Related Artifacts')) self.table_widget.setItem(14, 0, QTableWidgetItem(self.tr('Butteraugli'))) self.table_widget.setItem( 14, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(14, 0).setToolTip( self.tr('Estimate psychovisual error')) self.table_widget.setItem(15, 0, QTableWidgetItem(self.tr('Correlation'))) self.table_widget.setItem( 15, 2, QTableWidgetItem(QIcon('gui/icons/high.svg'), '(1)')) self.table_widget.item(15, 0).setToolTip(self.tr('Histogram correlation')) self.table_widget.setItem(16, 0, QTableWidgetItem(self.tr('Chi-Square'))) self.table_widget.setItem( 16, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(16, 0).setToolTip(self.tr('Histogram Chi-Square')) self.table_widget.setItem(17, 0, QTableWidgetItem(self.tr('Chi-Square 2'))) self.table_widget.setItem( 17, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(17, 0).setToolTip(self.tr('Alternative Chi-Square')) self.table_widget.setItem(18, 0, QTableWidgetItem(self.tr('Intersection'))) self.table_widget.setItem( 18, 2, QTableWidgetItem(QIcon('gui/icons/high.svg'), '(+' + u'\u221e' + ')')) self.table_widget.item(18, 0).setToolTip(self.tr('Histogram intersection')) self.table_widget.setItem(19, 0, QTableWidgetItem(self.tr('Hellinger'))) self.table_widget.setItem( 19, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(19, 0).setToolTip( self.tr('Histogram Hellinger distance')) self.table_widget.setItem(20, 0, QTableWidgetItem(self.tr('Divergence'))) self.table_widget.setItem( 20, 2, QTableWidgetItem(QIcon('gui/icons/low.svg'), '(0)')) self.table_widget.item(20, 0).setToolTip( self.tr('Kullback-Leibler divergence')) for i in range(self.table_widget.rowCount()): modify_font(self.table_widget.item(i, 0), bold=True) self.table_widget.setSelectionMode(QAbstractItemView.SingleSelection) self.table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table_widget.resizeColumnsToContents() self.table_widget.setMaximumWidth(250) self.table_widget.setAlternatingRowColors(True) self.stopped = False self.comp_label.setEnabled(False) self.normal_radio.setEnabled(False) self.difference_radio.setEnabled(False) self.ssim_radio.setEnabled(False) self.butter_radio.setEnabled(False) self.gray_check.setEnabled(False) self.equalize_check.setEnabled(False) self.metric_button.setEnabled(False) self.table_widget.setEnabled(False) load_button.clicked.connect(self.load) self.normal_radio.clicked.connect(self.change) self.difference_radio.clicked.connect(self.change) self.butter_radio.clicked.connect(self.change) self.gray_check.stateChanged.connect(self.change) self.equalize_check.stateChanged.connect(self.change) self.ssim_radio.clicked.connect(self.change) self.evidence_viewer.viewChanged.connect( self.reference_viewer.changeView) self.reference_viewer.viewChanged.connect( self.evidence_viewer.changeView) self.metric_button.clicked.connect(self.metrics) top_layout = QHBoxLayout() top_layout.addWidget(load_button) top_layout.addStretch() top_layout.addWidget(self.comp_label) top_layout.addWidget(self.normal_radio) top_layout.addWidget(self.difference_radio) top_layout.addWidget(self.ssim_radio) top_layout.addWidget(self.butter_radio) top_layout.addWidget(self.gray_check) top_layout.addWidget(self.equalize_check) metric_layout = QVBoxLayout() index_label = QLabel(self.tr('Image Quality Assessment')) index_label.setAlignment(Qt.AlignCenter) modify_font(index_label, bold=True) metric_layout.addWidget(index_label) metric_layout.addWidget(self.table_widget) metric_layout.addWidget(self.metric_button) center_layout = QHBoxLayout() center_layout.addWidget(self.evidence_viewer) center_layout.addWidget(self.reference_viewer) center_layout.addLayout(metric_layout) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addLayout(center_layout) self.setLayout(main_layout) def load(self): filename, basename, reference = load_image(self) if filename is None: return if reference.shape != self.evidence.shape: QMessageBox.critical( self, self.tr('Error'), self.tr('Evidence and reference must have the same size!')) return self.reference = reference self.reference_viewer.set_title( self.tr('Reference: {}'.format(basename))) self.difference = norm_mat(cv.absdiff(self.evidence, self.reference)) self.comp_label.setEnabled(True) self.normal_radio.setEnabled(True) self.difference_radio.setEnabled(True) self.ssim_radio.setEnabled(False) self.butter_radio.setEnabled(False) self.gray_check.setEnabled(True) self.equalize_check.setEnabled(True) self.metric_button.setEnabled(True) for i in range(self.table_widget.rowCount()): self.table_widget.setItem(i, 1, QTableWidgetItem()) self.normal_radio.setChecked(True) self.table_widget.setEnabled(False) self.change() def change(self): if self.normal_radio.isChecked(): result = self.reference self.gray_check.setEnabled(False) self.equalize_check.setEnabled(False) self.last_radio = self.normal_radio elif self.difference_radio.isChecked(): result = self.difference self.gray_check.setEnabled(True) self.equalize_check.setEnabled(True) self.last_radio = self.difference_radio elif self.ssim_radio.isChecked(): result = self.ssim_map self.gray_check.setEnabled(False) self.equalize_check.setEnabled(True) self.last_radio = self.ssim_radio elif self.butter_radio.isChecked(): result = self.butter_map self.gray_check.setEnabled(True) self.equalize_check.setEnabled(False) self.last_radio = self.butter_radio else: self.last_radio.setChecked(True) return if self.equalize_check.isChecked(): result = equalize_img(result) if self.gray_check.isChecked(): result = desaturate(result) self.reference_viewer.update_original(result) def metrics(self): progress = QProgressDialog(self.tr('Computing metrics...'), self.tr('Cancel'), 1, self.table_widget.rowCount(), self) progress.canceled.connect(self.cancel) progress.setWindowModality(Qt.WindowModal) img1 = cv.cvtColor(self.evidence, cv.COLOR_BGR2GRAY) img2 = cv.cvtColor(self.reference, cv.COLOR_BGR2GRAY) x = img1.astype(np.float64) y = img2.astype(np.float64) rmse = self.rmse(x, y) progress.setValue(1) if self.stopped: return sam = sewar.sam(img1, img2) progress.setValue(2) if self.stopped: return ergas = sewar.ergas(img1, img2) progress.setValue(3) if self.stopped: return mb = self.mb(x, y) progress.setValue(4) if self.stopped: return pfe = self.pfe(x, y) progress.setValue(5) if self.stopped: return psnr = self.psnr(x, y) progress.setValue(6) if self.stopped: return try: psnrb = sewar.psnrb(img1, img2) except NameError: # FIXME: C'\`e un bug in psnrb (https://github.com/andrewekhalel/sewar/issues/17) psnrb = 0 progress.setValue(7) if self.stopped: return ssim, self.ssim_map = self.ssim(x, y) progress.setValue(8) if self.stopped: return mssim = sewar.msssim(img1, img2).real progress.setValue(9) if self.stopped: return rase = sewar.rase(img1, img2) progress.setValue(10) if self.stopped: return scc = sewar.scc(img1, img2) progress.setValue(11) if self.stopped: return uqi = sewar.uqi(img1, img2) progress.setValue(12) if self.stopped: return vifp = sewar.vifp(img1, img2) progress.setValue(13) if self.stopped: return ssimul = self.ssimul(img1, img2) progress.setValue(14) if self.stopped: return butter, self.butter_map = self.butter(img1, img2) progress.setValue(15) if self.stopped: return sizes = [256, 256, 256] ranges = [0, 256] * 3 channels = [0, 1, 2] hist1 = cv.calcHist([self.evidence], channels, None, sizes, ranges) hist2 = cv.calcHist([self.reference], channels, None, sizes, ranges) correlation = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL) progress.setValue(16) if self.stopped: return chi_square = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR) progress.setValue(17) if self.stopped: return chi_square2 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR_ALT) progress.setValue(18) if self.stopped: return intersection = cv.compareHist(hist1, hist2, cv.HISTCMP_INTERSECT) progress.setValue(19) if self.stopped: return hellinger = cv.compareHist(hist1, hist2, cv.HISTCMP_HELLINGER) progress.setValue(20) if self.stopped: return divergence = cv.compareHist(hist1, hist2, cv.HISTCMP_KL_DIV) progress.setValue(21) self.table_widget.setItem(0, 1, QTableWidgetItem('{:.2f}'.format(rmse))) self.table_widget.setItem(1, 1, QTableWidgetItem('{:.4f}'.format(sam))) self.table_widget.setItem(2, 1, QTableWidgetItem('{:.2f}'.format(ergas))) self.table_widget.setItem(3, 1, QTableWidgetItem('{:.4f}'.format(mb))) self.table_widget.setItem(4, 1, QTableWidgetItem('{:.2f}'.format(pfe))) if psnr > 0: self.table_widget.setItem( 5, 1, QTableWidgetItem('{:.2f} dB'.format(psnr))) else: self.table_widget.setItem( 5, 1, QTableWidgetItem('+' + u'\u221e' + ' dB')) self.table_widget.setItem(6, 1, QTableWidgetItem('{:.2f}'.format(psnrb))) self.table_widget.setItem(7, 1, QTableWidgetItem('{:.4f}'.format(ssim))) self.table_widget.setItem(8, 1, QTableWidgetItem('{:.4f}'.format(mssim))) self.table_widget.setItem(9, 1, QTableWidgetItem('{:.2f}'.format(rase))) self.table_widget.setItem(10, 1, QTableWidgetItem('{:.4f}'.format(scc))) self.table_widget.setItem(11, 1, QTableWidgetItem('{:.4f}'.format(uqi))) self.table_widget.setItem(12, 1, QTableWidgetItem('{:.4f}'.format(vifp))) self.table_widget.setItem(13, 1, QTableWidgetItem('{:.4f}'.format(ssimul))) self.table_widget.setItem(14, 1, QTableWidgetItem('{:.2f}'.format(butter))) self.table_widget.setItem( 15, 1, QTableWidgetItem('{:.2f}'.format(correlation))) self.table_widget.setItem( 16, 1, QTableWidgetItem('{:.2f}'.format(chi_square))) self.table_widget.setItem( 17, 1, QTableWidgetItem('{:.2f}'.format(chi_square2))) self.table_widget.setItem( 18, 1, QTableWidgetItem('{:.2f}'.format(intersection))) self.table_widget.setItem(19, 1, QTableWidgetItem('{:.2f}'.format(hellinger))) self.table_widget.setItem( 20, 1, QTableWidgetItem('{:.2f}'.format(divergence))) self.table_widget.resizeColumnsToContents() self.table_widget.setEnabled(True) self.metric_button.setEnabled(False) self.ssim_radio.setEnabled(True) self.butter_radio.setEnabled(True) def cancel(self): self.stopped = True @staticmethod def rmse(x, y): return np.sqrt(np.mean(np.square(x - y))) @staticmethod def mb(x, y): mx = np.mean(x) my = np.mean(y) return (mx - my) / mx @staticmethod def pfe(x, y): return np.linalg.norm(x - y) / np.linalg.norm(x) * 100 @staticmethod def ssim(x, y): c1 = 6.5025 c2 = 58.5225 k = (11, 11) s = 1.5 x2 = x**2 y2 = y**2 xy = x * y mu_x = cv.GaussianBlur(x, k, s) mu_y = cv.GaussianBlur(y, k, s) mu_x2 = mu_x**2 mu_y2 = mu_y**2 mu_xy = mu_x * mu_y s_x2 = cv.GaussianBlur(x2, k, s) - mu_x2 s_y2 = cv.GaussianBlur(y2, k, s) - mu_y2 s_xy = cv.GaussianBlur(xy, k, s) - mu_xy t1 = 2 * mu_xy + c1 t2 = 2 * s_xy + c2 t3 = t1 * t2 t1 = mu_x2 + mu_y2 + c1 t2 = s_x2 + s_y2 + c2 t1 *= t2 ssim_map = cv.divide(t3, t1) ssim = cv.mean(ssim_map)[0] return ssim, 255 - norm_mat(ssim_map, to_bgr=True) @staticmethod def corr(x, y): return np.corrcoef(x, y)[0, 1] @staticmethod def psnr(x, y): k = np.mean(np.square(x - y)) if k == 0: return -1 return 20 * math.log10((255**2) / k) @staticmethod def butter(x, y): try: exe = butter_exe() if exe is None: raise FileNotFoundError temp_dir = QTemporaryDir() if temp_dir.isValid(): filename1 = os.path.join(temp_dir.path(), 'img1.png') cv.imwrite(filename1, x) filename2 = os.path.join(temp_dir.path(), 'img2.png') cv.imwrite(filename2, y) filename3 = os.path.join(temp_dir.path(), 'map.ppm') p = run([exe, filename1, filename2, filename3], stdout=PIPE) value = float(p.stdout) heatmap = cv.imread(filename3, cv.IMREAD_COLOR) return value, heatmap except FileNotFoundError: return -1, cv.cvtColor(np.full_like(x, 127), cv.COLOR_GRAY2BGR) @staticmethod def ssimul(x, y): try: exe = ssimul_exe() if exe is None: raise FileNotFoundError temp_dir = QTemporaryDir() if temp_dir.isValid(): filename1 = os.path.join(temp_dir.path(), 'img1.png') cv.imwrite(filename1, x) filename2 = os.path.join(temp_dir.path(), 'img2.png') cv.imwrite(filename2, y) p = run([exe, filename1, filename2], stdout=PIPE) value = float(p.stdout) return value except FileNotFoundError: return -1
class ComparisonWidget(ToolWidget): def __init__(self, image, parent=None): super(ComparisonWidget, self).__init__(parent) load_button = QPushButton(self.tr('Load reference...')) self.file_label = QLabel() modify_font(self.file_label, bold=True) self.comp_label = QLabel(self.tr('Comparison:')) self.normal_radio = QRadioButton(self.tr('Normal')) self.normal_radio.setChecked(True) self.diff_radio = QRadioButton(self.tr('Difference')) self.gray_check = QCheckBox(self.tr('Grayscale')) self.equal_check = QCheckBox(self.tr('Equalized')) self.map_radio = QRadioButton(self.tr('SSIM Map')) self.last_radio = self.normal_radio self.comp_label.setEnabled(False) self.normal_radio.setEnabled(False) self.diff_radio.setEnabled(False) self.gray_check.setEnabled(False) self.equal_check.setEnabled(False) self.map_radio.setEnabled(False) self.evidence = image self.reference = np.full_like(image, 127) self.difference = np.full_like(image, 127) self.equalized = np.full_like(image, 127) self.indexmap = np.full_like(image, 127) self.evidence_viewer = ImageViewer(self.evidence, None, self.tr('Evidence')) self.reference_viewer = ImageViewer(self.reference, None, self.tr('Reference')) self.table_widget = QTableWidget(5, 2) self.table_widget.setHorizontalHeaderLabels( [self.tr('Index'), self.tr('Value')]) self.table_widget.setItem(0, 0, QTableWidgetItem(self.tr('MSE'))) self.table_widget.setItem(1, 0, QTableWidgetItem(self.tr('COVAR'))) self.table_widget.setItem(2, 0, QTableWidgetItem(self.tr('PSNR'))) self.table_widget.setItem(3, 0, QTableWidgetItem(self.tr('SSIM'))) self.table_widget.setItem(4, 0, QTableWidgetItem(self.tr('CORR'))) for i in range(self.table_widget.rowCount()): modify_font(self.table_widget.item(i, 0), bold=True) self.table_widget.setEnabled(False) load_button.clicked.connect(self.load) self.normal_radio.toggled.connect(self.change) self.diff_radio.toggled.connect(self.change) self.gray_check.stateChanged.connect(self.change) self.equal_check.stateChanged.connect(self.change) self.map_radio.toggled.connect(self.change) self.evidence_viewer.view_changed.connect( self.reference_viewer.change_view) self.reference_viewer.view_changed.connect( self.evidence_viewer.change_view) top_layout = QHBoxLayout() top_layout.addWidget(load_button) top_layout.addWidget(self.file_label) top_layout.addStretch() top_layout.addWidget(self.comp_label) top_layout.addWidget(self.normal_radio) top_layout.addWidget(self.map_radio) top_layout.addWidget(self.diff_radio) top_layout.addWidget(self.gray_check) top_layout.addWidget(self.equal_check) index_layout = QVBoxLayout() index_label = QLabel(self.tr('Image Quality Assessment')) modify_font(index_label, bold=True) index_layout.addWidget(index_label) index_layout.addWidget(self.table_widget) center_layout = QHBoxLayout() center_layout.addWidget(self.evidence_viewer) center_layout.addWidget(self.reference_viewer) center_layout.addLayout(index_layout) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addLayout(center_layout) self.setLayout(main_layout) def load(self): filename, basename, image = load_image(self) if filename is None: return if image.shape != self.evidence.shape: QMessageBox.critical( self, self.tr('Error'), self.tr('Evidence and reference must have the same size!')) return self.file_label.setText(basename) self.reference = image self.difference = normalize_mat( cv.absdiff(self.evidence, self.reference)) self.equalized = cv.merge( [cv.equalizeHist(c) for c in cv.split(self.difference)]) x = cv.cvtColor(self.evidence, cv.COLOR_BGR2GRAY).astype(np.float32) y = cv.cvtColor(self.reference, cv.COLOR_BGR2GRAY).astype(np.float32) mse = self.mse(x, y) covar = self.covar(x, y) psnr = self.psnr(mse) ssim, self.indexmap = self.ssim(x, y) corr = self.corr(x, y) self.table_widget.setItem(0, 1, QTableWidgetItem('{:.4f}'.format(mse))) self.table_widget.setItem(1, 1, QTableWidgetItem('{:.4f}'.format(covar))) if psnr > 0: self.table_widget.setItem( 2, 1, QTableWidgetItem('{:.2f} dB'.format(psnr))) else: self.table_widget.setItem( 2, 1, QTableWidgetItem('+' + u'\u221e' + ' dB')) self.table_widget.setItem(3, 1, QTableWidgetItem('{:.4f}'.format(ssim))) self.table_widget.setItem(4, 1, QTableWidgetItem('{:.4f}'.format(corr))) self.table_widget.setEnabled(True) self.comp_label.setEnabled(True) self.normal_radio.setEnabled(True) self.diff_radio.setEnabled(True) self.gray_check.setEnabled(True) self.equal_check.setEnabled(True) self.map_radio.setEnabled(True) self.change() def change(self): self.gray_check.setEnabled(False) self.equal_check.setEnabled(False) if self.normal_radio.isChecked(): self.reference_viewer.update_original(self.reference) self.last_radio = self.normal_radio elif self.diff_radio.isChecked(): self.gray_check.setEnabled(True) self.equal_check.setEnabled(True) if self.equal_check.isChecked(): result = self.equalized else: result = self.difference if self.gray_check.isChecked(): result = desaturate(result) self.reference_viewer.update_original(result) self.last_radio = self.diff_radio elif self.map_radio.isChecked(): self.reference_viewer.update_original(self.indexmap) self.last_radio = self.map_radio else: self.last_radio.setChecked(True) @staticmethod def ssim(x, y): c1 = 6.5025 c2 = 58.5225 k = (11, 11) s = 1.5 x2 = x**2 y2 = y**2 xy = x * y mu_x = cv.GaussianBlur(x, k, s) mu_y = cv.GaussianBlur(y, k, s) mu_x2 = mu_x**2 mu_y2 = mu_y**2 mu_xy = mu_x * mu_y s_x2 = cv.GaussianBlur(x2, k, s) - mu_x2 s_y2 = cv.GaussianBlur(y2, k, s) - mu_y2 s_xy = cv.GaussianBlur(xy, k, s) - mu_xy t1 = 2 * mu_xy + c1 t2 = 2 * s_xy + c2 t3 = t1 * t2 t1 = mu_x2 + mu_y2 + c1 t2 = s_x2 + s_y2 + c2 t1 *= t2 indexmap = cv.divide(t3, t1) ssim = cv.mean(indexmap)[0] return ssim, 255 - normalize_mat(indexmap, to_bgr=True) @staticmethod def corr(x, y): return np.corrcoef(x, y)[0, 1] @staticmethod def covar(x, y): return np.std(cv.absdiff(x, y)) @staticmethod def mse(x, y): return cv.mean(cv.pow(x - y, 2))[0] @staticmethod def psnr(mse): k = math.sqrt(mse) if k == 0: return -1 return 20 * math.log10((255**2) / k)
class mainWindow(QObject): signalRun = Signal(SpiderThread) signalRunApi = Signal(apiTester) def __init__(self): QObject.__init__(self) # must init parent QObject,if you want to use signal self.widget = QWidget() self.ipLabel = QLabel(self.widget) self.thread = QThread() self.worker = Worker() self.worker.moveToThread(self.thread) self.man = SpiderThread() self.api = apiTester() # 1 2:loop 3: time self.testStatus = [False,1,0,"ip","mac"] # advance config self.findCoreStop = True self.cleanCacheSet = False self.useApiTest = False self.showTestProgress = True self.saveTestLog = False self.saveLogPath = "" self.chromePath = "" self.showChrome = False self.coreDumpPath = "" # ui form self.passwordLabel = QLabel(self.widget) self.ipLineEdit = QLineEdit(self.widget) self.passwordLineEdit = QLineEdit(self.widget) self.startBtn = QPushButton(self.widget) self.stopBtn = QPushButton(self.widget) self.messageBox = QTextEdit(self.widget) self.messageBox.setReadOnly(True) self.userLabel = QLabel(self.widget) self.userLineEdit = QLineEdit(self.widget) self.intervalLabel = QLabel(self.widget) self.intervalSpinBox = QSpinBox(self.widget) self.loopLabel = QLabel(self.widget) self.loopSpinBox = QSpinBox(self.widget) self.intervalSpinBox.setRange(0,9999) self.loopSpinBox.setRange(1,9999) self.radioReboot = QRadioButton(self.widget) self.radioProvision = QRadioButton(self.widget) self.radioFactory = QRadioButton(self.widget) # self.apiCheckBox = QCheckBox(self.widget) self.menu = QMenu() self.gxpAction = QAction("Classic UI") self.grp2602Action = QAction("Ant Design UI") self.gxpAction.setCheckable(True) self.grp2602Action.setCheckable(True) self.menu.addAction(self.gxpAction) self.menu.addAction(self.grp2602Action) self.webLabel = QLabel(self.widget) self.webBtn = QPushButton(self.widget) self.webBtn.setMenu(self.menu) self.clearBtn = QPushButton(self.widget) self.messageList = deque() self.timer = QTimer() self.advanceBtn = QPushButton(self.widget) self.infoLabel = QLabel(self.widget) # provision widget self.provWidget = QWidget(self.widget) self.ver1Label = QLabel(self.provWidget) self.ver2Label = QLabel(self.provWidget) self.ver3Label = QLabel(self.provWidget) self.ver1LineEdit = QLineEdit(self.provWidget) self.ver2LineEdit = QLineEdit(self.provWidget) self.ver3LineEdit = QLineEdit(self.provWidget) self.dir1Label = QLabel(self.provWidget) self.dir2Label = QLabel(self.provWidget) self.dir3Label = QLabel(self.provWidget) self.dir1LineEdit = QLineEdit(self.provWidget) self.dir2LineEdit = QLineEdit(self.provWidget) self.dir3LineEdit = QLineEdit(self.provWidget) self.radioHttp = QRadioButton(self.provWidget) self.radioHttps = QRadioButton(self.provWidget) self.radioTftp = QRadioButton(self.provWidget) self.radioFtp = QRadioButton(self.provWidget) self.radioFtps = QRadioButton(self.provWidget) self.radioWindow = QRadioButton(self.provWidget) # advance widget self.advanceWidget = QWidget() self.checkCoreBox = QCheckBox(self.advanceWidget) self.cleanCache = QCheckBox(self.advanceWidget) self.checkSaveLogBox = QCheckBox(self.advanceWidget) self.selectDirBtn = QPushButton(self.advanceWidget) self.saveDirLabel = QLabel(self.advanceWidget) self.saveDirLabel.setStyleSheet("background:white") self.checkProgressBox = QCheckBox(self.advanceWidget) self.advanceOkBtn = QPushButton(self.advanceWidget) self.selectChromeBtn = QPushButton(self.advanceWidget) self.chromePathLabel = QLabel(self.advanceWidget) self.chromePathLabel.setStyleSheet("background:white") self.checkShowChromeBox = QCheckBox(self.advanceWidget) self.chromeLabel = QLabel(self.advanceWidget) self.pcapLabel = QLabel(self.advanceWidget) self.apiCheckBox = QCheckBox(self.advanceWidget) self.corePathLabel = QLabel(self.advanceWidget) self.corePathLabel.setStyleSheet("background:white") self.corePathBtn = QPushButton(self.advanceWidget) self.interfaceMenu = QComboBox(self.advanceWidget) self.interfaceMenu.addItem('Default') self.aiOptionBox= QCheckBox(self.advanceWidget) a = IFACES print(a) for i in a.keys(): print(a[i].description) self.interfaceMenu.addItem(a[i].description) # connect singal and slot self.startBtn.clicked.connect(self.clickedStarBtn) self.radioProvision.clicked.connect(self.clickedProvision) self.radioReboot.clicked.connect(self.clickedOthers) self.radioFactory.clicked.connect(self.clickedOthers) self.stopBtn.clicked.connect(self.clickedStopBtn) self.grp2602Action.triggered.connect(self.clickedGrp2602) self.gxpAction.triggered.connect(self.clickedGxpType) self.timer.timeout.connect(self.updateMessage) self.apiCheckBox.stateChanged.connect(self.apiTestBoxCheck) self.clearBtn.clicked.connect(self.clickedClearBtn) self.advanceBtn.clicked.connect(self.clickedAdvanceBtn) self.advanceOkBtn.clicked.connect(self.clickedAdvanceOkBtn) self.checkSaveLogBox.stateChanged.connect(self.saveLogBoxCheck) self.selectChromeBtn.clicked.connect(self.clickedSelectChromeBtn) self.selectDirBtn.clicked.connect(self.clickedSelectDirBtn) self.corePathBtn.clicked.connect(self.clickedCorePathBtn) self.worker.signalJobEnd.connect(self.slotTestStoped) self.worker.apiTestFinished.connect(self.slotTestStoped) self.signalRun.connect(self.worker.dowork) self.signalRunApi.connect(self.worker.doworkApi) # self.man.signalUpdateMessage.connect(self.pushMessage) def setupUI(self): # set text content /value self.widget.setWindowTitle("自动重启升降级测试工具") self.ipLabel.setText("初始IP:") self.passwordLabel.setText("密码:") self.startBtn.setText("开始测试") self.stopBtn.setText("停止测试") self.userLabel.setText("用户名:") self.intervalLabel.setText("间隔时间:") self.loopLabel.setText("测试次数:") self.intervalSpinBox.setValue(130) self.radioFactory.setText("恢复出厂") self.radioProvision.setText("升降级") self.radioReboot.setText("重启") self.ver1Label.setText("版本 1:") self.ver2Label.setText("版本 2:") self.ver3Label.setText("版本 3:") self.dir1Label.setText("路径 1:") self.dir2Label.setText("路径 2:") self.dir3Label.setText("路径 3:") self.radioHttp.setText("Http") self.radioHttps.setText("Https") self.radioTftp.setText("Tftp") self.radioFtp.setText("Ftp") self.radioFtps.setText("Ftps") self.apiCheckBox.setText("使用API测试,配置CoreDump下载路径") self.webLabel.setText("网页类型:") self.webBtn.setText("请选择UI类型") self.clearBtn.setText("清空输入") self.advanceWidget.setWindowTitle("高级设置") self.advanceBtn.setText("高级设置") self.checkCoreBox.setText("发现Core Dump时停止测试") self.cleanCache.setText("清除页面cache") self.checkSaveLogBox.setText("保存测试日志") self.selectDirBtn.setText("浏览") self.checkProgressBox.setText("显示底部状态条") self.advanceOkBtn.setText("OK") self.checkShowChromeBox.setText("测试时显示Chrome浏览器") self.selectChromeBtn.setText("浏览") self.chromeLabel.setText("Chrome浏览器路径") self.infoLabel.setText("未开始测试") self.pcapLabel.setText("Net Interface") self.corePathBtn.setText("浏览") self.radioWindow.setText("网页拖拽文件") # self.aiOptionBox.setText("AI") #init value self.saveDirLabel.hide() self.selectDirBtn.hide() self.gxpAction.setChecked(True) self.radioReboot.click() self.radioHttp.click() self.stopBtn.setEnabled(False) self.passwordLineEdit.setEchoMode(QLineEdit.PasswordEchoOnEdit) # set position------------------------------- xPos = 20 yPos = 30 colum2 = xPos +200 # line 1 self.ipLabel.move(xPos,yPos) self.intervalLabel.move(colum2,yPos) self.intervalSpinBox.move(colum2+60,yPos-2) self.ipLineEdit.move(xPos+50,yPos-2) # line 2 line2 = yPos +40 self.passwordLabel.move(xPos,line2) self.passwordLineEdit.move(xPos+50,line2-2) self.loopLabel.move(colum2,line2) self.loopSpinBox.move(colum2+60,line2-2) # line3 line3 = yPos +80 self.userLabel.move(xPos,line3) self.userLineEdit.move(xPos+50,line3-2) self.radioReboot.move(colum2,line3) self.radioFactory.move(colum2+60,line3) self.radioProvision.move(colum2,line3+30) self.webLabel.move(xPos,line3+40) self.webBtn.move(xPos+60,line3+35) # provWidget self.provWidget.resize(400,130) self.provWidget.move(xPos,line3+70) spaceY = 30 x = 0 y = 0 cl = 200 self.ver1Label.move(x,y) self.ver1LineEdit.move(x+50,y) self.ver2Label.move(x,y+spaceY) self.ver2LineEdit.move(x+50,y+spaceY) self.ver3Label.move(x,y+spaceY*2) self.ver3LineEdit.move(x+50,y+spaceY*2) self.dir1Label.move(cl,y) self.dir1LineEdit.move(cl+50,y) self.dir2Label.move(cl,y+spaceY) self.dir2LineEdit.move(cl+50,y+spaceY) self.dir3Label.move(cl,y+spaceY*2) self.dir3LineEdit.move(cl+50,y+spaceY*2) self.radioHttp.move(x,y+spaceY*3) self.radioHttps.move(x+50,y+spaceY*3) self.radioTftp.move(x+110,y+spaceY*3) self.radioFtp.move(x+160,y+spaceY*3) self.radioFtps.move(x+210,y+spaceY*3) self.radioWindow.move(x+265,y+spaceY*3) # advance widget self.advanceWidget.resize(300,400) x = 20 y = 20 space = 30 self.checkCoreBox.move(x,y) self.cleanCache.move(x,y+space) self.checkProgressBox.move(x,y+space*2) self.checkShowChromeBox.move(x,y+space*3) self.apiCheckBox.move(x,y+space*4) self.corePathBtn.move(x-2,y+space*5-8) self.corePathLabel.move(x+35,y+space*5-8) y += 40 self.chromeLabel.move(x,y+space*4+10) self.selectChromeBtn.move(x-2,y+space*5) self.chromePathLabel.move(x+35,y+space*5+2) self.checkSaveLogBox.move(x,y+space*6+10) self.selectDirBtn.move(x-2,y+space*7) self.saveDirLabel.move(x+35,y+space*7+2) self.advanceOkBtn.move(x+170,y+space*10+10) self.interfaceMenu.move(x-5,y+space*8+10) self.pcapLabel.move(x,y+space*8-2) # self.aiOptionBox.move(x, y+space*9+8) # set size self.messageBox.resize(373,155) # self.widget.resize(410,400) self.loopSpinBox.resize(60,25) self.intervalSpinBox.resize(60,25) self.webBtn.resize(100,25) self.saveDirLabel.resize(185,22) self.selectDirBtn.resize(32,24) self.selectChromeBtn.resize(32,24) self.chromePathLabel.resize(185,22) self.infoLabel.resize(400, 25) self.corePathBtn.resize(32,24) self.corePathLabel.resize(185,22) # self.provWidget.hide() self.changePosition(True) self.widget.show() self.loadCache() # ----------------end of setupUI --------------------- def changePosition(self,hide): xPos = 20 if hide: buttonLine = 200 self.widget.resize(420,415) else: buttonLine = 310 self.widget.resize(420,524) self.startBtn.move(xPos,buttonLine) self.stopBtn.move(xPos+90,buttonLine) self.clearBtn.move(xPos+180,buttonLine) self.advanceBtn.move(xPos+270,buttonLine) self.messageBox.move(xPos,buttonLine+30) boxH = self.messageBox.height() self.infoLabel.move(xPos,buttonLine+boxH+35) def setItemEnable(self,enable): self.provWidget.setEnabled(enable) self.ipLineEdit.setEnabled(enable) self.passwordLineEdit.setEnabled(enable) self.userLineEdit.setEnabled(enable) self.intervalSpinBox.setEnabled(enable) self.loopSpinBox.setEnabled(enable) self.radioFactory.setEnabled(enable) self.radioReboot.setEnabled(enable) self.radioProvision.setEnabled(enable) self.advanceBtn.setEnabled(enable) self.startBtn.setEnabled(enable) self.clearBtn.setEnabled(enable) if self.useApiTest: self.webBtn.setEnabled(False) else: self.webBtn.setEnabled(enable) self.stopBtn.setEnabled(not enable) def outputError(self,str): appstr = "<span style=\"color:red\">" appstr += str + "</span>" self.messageBox.append(appstr) def outputWarning(self,str): appstr = "<span style=\"color:orange\">" appstr += str + "</span>" self.messageBox.append(appstr) def loadCache(self): file = QFile("cache") if not file.open(QIODevice.ReadOnly | QIODevice.Text): return inStream = QTextStream(file) # ip self.ipLineEdit.setText(inStream.readLine()) # passwordLabel self.passwordLineEdit.setText(inStream.readLine()) # user self.userLineEdit.setText(inStream.readLine()) # ver1 self.ver1LineEdit.setText(inStream.readLine()) self.dir1LineEdit.setText(inStream.readLine()) # ver2 self.ver2LineEdit.setText(inStream.readLine()) self.dir2LineEdit.setText(inStream.readLine()) # ver3 self.ver3LineEdit.setText(inStream.readLine()) self.dir3LineEdit.setText(inStream.readLine()) self.intervalSpinBox.setValue(int(inStream.readLine())) self.loopSpinBox.setValue(int(inStream.readLine())) # web type button webType = inStream.readLine() if webType == "gxpAction": self.grp2602Action.setChecked(False) self.gxpAction.setChecked(True) self.webBtn.setText(self.gxpAction.text()) else: self.grp2602Action.setChecked(True) self.gxpAction.setChecked(False) self.webBtn.setText(self.grp2602Action.text()) testType = inStream.readLine() if testType == "reboot": self.radioReboot.setChecked(True) elif testType == "provision": self.radioProvision.setChecked(True) self.changePosition(False) self.provWidget.show() else: self.radioFactory.setChecked(True) serverType = inStream.readLine() if serverType == "Http": self.radioHttp.setChecked(True) elif serverType == "Https": self.radioHttps.setChecked(True) elif serverType == "Tftp": self.radioTftp.setChecked(True) elif serverType == "Ftp": self.radioFtp.setChecked(True) elif serverType == "Ftps": self.radioFtps.setChecked(True) else: self.radioWindow.setChecked(True) if inStream.readLine() == "True": self.findCoreStop = True else: self.findCoreStop = False if inStream.readLine() == "True": self.cleanCacheSet = True else: self.cleanCacheSet = False if inStream.readLine() == "True": self.useApiTest = True self.webBtn.setEnabled(False) else: self.useApiTest = False self.corePathBtn.hide() self.corePathLabel.hide() if inStream.readLine() == "True": self.showTestProgress = True else: self.showTestProgress = False self.infoLabel.hide() if inStream.readLine() == "True": self.showChrome = True else: self.showChrome = False self.chromePath = inStream.readLine() if inStream.readLine() == "True": self.saveTestLog = True else: self.saveTestLog = False self.saveLogPath = inStream.readLine() self.coreDumpPath = inStream.readLine() file.close() def saveCache(self): file = QFile("cache") if not file.open(QIODevice.WriteOnly): return content = self.ipLineEdit.text() + "\n" content += self.passwordLineEdit.text() + "\n" content += self.userLineEdit.text() + "\n" content += self.ver1LineEdit.text() + "\n" content += self.dir1LineEdit.text() + "\n" content += self.ver2LineEdit.text() + "\n" content += self.dir2LineEdit.text() + "\n" content += self.ver3LineEdit.text() + "\n" content += self.dir3LineEdit.text() + "\n" content += str(self.intervalSpinBox.value()) + "\n" content += str(self.loopSpinBox.value()) + "\n" if self.gxpAction.isChecked(): content += "gxpAction\n" else: content += "grp2602Action\n" if self.radioReboot.isChecked(): content += "reboot\n" elif self.radioProvision.isChecked(): content += "provision\n" else: content += "factory\n" if self.radioHttp.isChecked(): content += "Http\n" elif self.radioHttps.isChecked(): content += "Https\n" elif self.radioTftp.isChecked(): content += "Tftp\n" elif self.radioFtp.isChecked(): content += "Ftp\n" elif self.radioFtps.isChecked(): content += "Ftps\n" else : content += "Window\n" content += str(self.findCoreStop) + "\n" content += str(self.cleanCacheSet) + "\n" content += str(self.useApiTest) + "\n" content += str(self.showTestProgress) + "\n" content += str(self.showChrome) + "\n" content += self.chromePath +"\n" content += str(self.saveTestLog) +"\n" content += self.saveLogPath +"\n" content += self.coreDumpPath +"\n" byteArr = bytes(content,"utf-8") file.write(QByteArray(byteArr)) file.close() def checkBeforeRun(self): containError = False #---------check Ip address-------------- if self.ipLineEdit.text() == "": containError = True self.outputError("IP地址不能为空!") else: pattern = re.compile("^((1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)|([1-9][0-9]\.)|([0-9]\.)){3}((1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])|([1-9][0-9])|([0-9]))$") if not pattern.search(self.ipLineEdit.text()): containError = True self.outputError("IP地址格式错误,检查是否含有多余空格!(仅支持IPV4)") #------------------------ if self.passwordLineEdit.text() == "": containError = True self.outputError("密码不能为空!") if self.userLineEdit.text() == "": containError = True self.outputError("用户名不能为空!") if self.intervalSpinBox.value() <= 40: self.outputWarning("间隔时间过短,可能对测试造成影响") if not self.radioProvision.isChecked() and not self.radioReboot.isChecked() and \ not self.radioFactory.isChecked(): containError = True self.outputError("必须选择测试方式(重启,升降级,恢复出厂)") # check provision ---------- if self.radioProvision.isChecked(): if self.ver1LineEdit.text() == "" or self.ver2LineEdit.text() == "" or \ self.dir1LineEdit.text() == "" or self.dir2LineEdit.text() == "": containError = True self.outputError("升降级测试至少填上前两个版本及其路径") bin_name = "" if os.path.exists(os.path.abspath("config.ini") ): f = open(os.path.abspath("config.ini") , "r") line = f.readline() while line: option = line.split("=") if option[0] == "firmbinname": if option[1].strip('"') != "": filenamebin = option[1].strip() bin_name = filenamebin.strip('"') pass line = f.readline() f.close() filename = os.path.join(self.dir1LineEdit.text(), bin_name) if not os.path.exists(filename) and self.radioWindow.isChecked(): containError = True self.outputError("firmware1 文件不存在!" + filename) filename = os.path.join(self.dir2LineEdit.text(), bin_name) if not os.path.exists(filename) and self.radioWindow.isChecked(): containError = True self.outputError("firmware2 文件不存在!" + filename) filename = os.path.join(self.dir3LineEdit.text(), bin_name) if self.ver3LineEdit.text() != "" and self.dir3LineEdit.text() == "": containError = True self.outputError("填写了版本3,但对应路径为空!") if self.dir3LineEdit.text() != "" and self.ver3LineEdit.text() == "": containError = True self.outputError("填写了路径3,但对应版本为空!") elif self.dir3LineEdit.text() != "" and self.radioWindow.isChecked() and not os.path.exists(filename): containError = True self.outputError("firmware3 文件不存在!" + filename) if not self.radioFtp.isChecked() and not self.radioFtps.isChecked() and \ not self.radioHttp.isChecked() and not self.radioHttps.isChecked() and \ not self.radioTftp.isChecked() and not self.radioWindow.isChecked(): containError = True self.outputError("升降级测试必须选择服务器类型(Tftp,Ftp,Ftps,Http,Https)") return containError def startTest(self): ip = self.ipLineEdit.text() passwd = self.passwordLineEdit.text() username = self.userLineEdit.text() ptime = self.intervalSpinBox.value() loop = self.loopSpinBox.value() modelType = self.webBtn.text() if self.gxpAction.isChecked(): device_type = "GXP21XX" elif self.grp2602Action.isChecked(): device_type = "GRP260X" if self.radioReboot.isChecked(): task_type = "reboot" elif self.radioProvision.isChecked(): task_type = "provision" text_ver1 = self.ver1LineEdit.text() text_ver2 = self.ver2LineEdit.text() text_ver3 = self.ver3LineEdit.text() text_dir1 = self.dir1LineEdit.text() text_dir2 = self.dir2LineEdit.text() text_dir3 = self.dir3LineEdit.text() prov_dict = {"ver1": text_ver1.strip(), "dir1": text_dir1.strip(), "ver2": text_ver2.strip(), "dir2": text_dir2.strip(), "ver3": text_ver3.strip(), "dir3": text_dir3.strip()} if self.radioHttp.isChecked(): self.man.update_prov_setting("HTTP", prov_dict) elif self.radioHttps.isChecked(): self.man.update_prov_setting("HTTPS", prov_dict) elif self.radioTftp.isChecked(): self.man.update_prov_setting("TFTP", prov_dict) elif self.radioFtp.isChecked(): self.man.update_prov_setting("FTP", prov_dict) elif self.radioFtps.isChecked(): self.man.update_prov_setting("FTPS", prov_dict) elif self.radioWindow.isChecked(): self.man.update_prov_setting("browser", prov_dict) else: task_type = "reset" coredump_stop = True headless_flag = False clean_cache = False if self.checkCoreBox.isChecked() == False: self.messageBox.append("Find core dump will not stop") coredump_stop = False if self.cleanCache.isChecked() == True: clean_cache = True if self.checkShowChromeBox.isChecked() == True or self.radioWindow.isChecked() == True: headless_flag = False else: headless_flag = True # ai_mode = False # if self.aiOptionBox.isChecked() == True: # ai_mode = True browser_path = "" if self.chromePathLabel.text() != "": browser_path = self.chromePathLabel.text() self.testStatus = [True,1,0,"ip",""] print(self.interfaceMenu.currentText()) self.man.setStatus(self.testStatus) self.man.setMessageList(self.messageList) self.man.update_setting(ip.strip(), username.strip(), passwd.strip(), device_type, \ task_type, loop, ptime, coredump_stop, headless_flag, browser_path, \ clean_cache, self.interfaceMenu.currentText(), False) def startApiTest(self): ip = self.ipLineEdit.text() passwd = self.passwordLineEdit.text() username = self.userLineEdit.text() ptime = self.intervalSpinBox.value() loop = self.loopSpinBox.value() testType = "Reboot" if self.radioProvision.isChecked(): testType = "Provision" self.api.setValue(ip,username,passwd,ptime,loop,testType) v1 = self.ver1LineEdit.text() v2 = self.ver2LineEdit.text() v3 = self.ver3LineEdit.text() d1 = self.dir1LineEdit.text() d2 = self.dir2LineEdit.text() d3 = self.dir3LineEdit.text() self.api.setVersion(v1,v2,v3,d1,d2,d3) self.api.setTestStatus(self.testStatus,self.messageList,self.coreDumpPath) if self.radioHttp.isChecked(): self.api.setServerType("http") elif self.radioHttps.isChecked(): self.api.setServerType("https") elif self.radioTftp.isChecked(): self.api.setServerType("tftp") elif self.radioFtp.isChecked(): self.api.setServerType("ftp") else: #self.radioFtps.isChecked() self.api.setServerType("ftps") self.api.setFoundCoreStop(self.findCoreStop) # slot --------------------------------- def apiTestBoxCheck(self,state): if state == 2: self.corePathBtn.show() self.corePathLabel.show() else: self.corePathBtn.hide() self.corePathLabel.hide() def clickedCorePathBtn(self): dir = QFileDialog.getExistingDirectory(self.advanceWidget,"选择Core Dump存放路径","/home") if dir != "": self.corePathLabel.setText(dir) self.coreDumpPath = dir def clickedSelectDirBtn(self): dir = QFileDialog.getExistingDirectory(self.advanceWidget,"选择日志存放路径","/home") if dir != "": self.saveDirLabel.setText(dir) self.saveLogPath = dir def clickedSelectChromeBtn(self): fileName = QFileDialog.getOpenFileName(self.advanceWidget,"选择谷歌浏览器","/home","Chrome (*.exe)") if fileName != "": self.chromePathLabel.setText(fileName[0]) self.chromePath = fileName[0] def saveLogBoxCheck(self,state): if state == 2: # checked self.selectDirBtn.show() self.saveDirLabel.show() else: self.selectDirBtn.hide() self.saveDirLabel.hide() def clickedAdvanceOkBtn(self): self.findCoreStop = self.checkCoreBox.isChecked() self.cleanCacheSet = self.cleanCache.isChecked() self.useApiTest = self.apiCheckBox.isChecked() self.showTestProgress = self.checkProgressBox.isChecked() self.saveTestLog = self.checkSaveLogBox.isChecked() self.saveLogPath = self.saveDirLabel.text() self.showChrome = self.checkShowChromeBox.isChecked() self.chromePath = self.chromePathLabel.text() self.coreDumpPath = self.corePathLabel.text() if self.useApiTest: self.webBtn.setEnabled(False) self.corePathBtn.show() self.corePathLabel.show() else: self.webBtn.setEnabled(True) self.corePathBtn.hide() self.corePathLabel.hide() if self.showTestProgress: self.infoLabel.show() else: self.infoLabel.hide() self.saveCache() self.advanceWidget.hide() def clickedAdvanceBtn(self): self.advanceWidget.hide() self.checkCoreBox.setChecked(self.findCoreStop) self.cleanCache.setChecked(self.cleanCacheSet) self.apiCheckBox.setChecked(self.useApiTest) self.checkProgressBox.setChecked(self.showTestProgress) self.checkSaveLogBox.setChecked(self.saveTestLog) self.saveDirLabel.setText(self.saveLogPath) self.checkShowChromeBox.setChecked(self.showChrome) self.chromePathLabel.setText(self.chromePath) self.corePathLabel.setText(self.coreDumpPath) self.advanceWidget.show() def slotTestStoped(self): self.testStatus[0] = False self.setItemEnable(True) self.timer.stop() self.updateMessage() self.thread.quit() # save Test log if self.saveTestLog: fileName = time.strftime("%Y_%m_%d.%H_%M_%S.",time.localtime()) if self.radioReboot.isChecked(): fileName += "reboot" elif self.radioProvision: fileName += "provision" else: fileName += "factoryReset" fileName += ".htm" if self.saveLogPath == "": self.outputWarning("日志地址没有设置,无法保存") else: fileName = self.saveLogPath + "\\" + fileName print(fileName) file = QFile(fileName) if not file.open(QIODevice.WriteOnly): self.outputError("打开文件错误,保存日志失败") return byteArr = bytes(self.messageBox.toHtml(),"utf-8") file.write(QByteArray(byteArr)) file.close() def clickedClearBtn(self): self.ipLineEdit.setText("") self.passwordLineEdit.setText("") self.userLineEdit.setText("") self.ver1LineEdit.setText("") self.dir1LineEdit.setText("") self.ver2LineEdit.setText("") self.dir2LineEdit.setText("") self.ver3LineEdit.setText("") self.dir3LineEdit.setText("") def clickedStarBtn(self): if self.checkBeforeRun(): return self.messageBox.clear() self.saveCache() self.messageBox.append("Init Setting...") self.setItemEnable(False) self.timer.start(500) self.thread.start() # deside use what to test if self.useApiTest: if self.radioFactory.isChecked(): self.outputWarning("Api not support Factory Reset, will test as Gxp type web driver") self.clickedGxpType() self.startTest() self.signalRun.emit(self.man) else: self.startApiTest() self.signalRunApi.emit(self.api) else: self.startTest() self.signalRun.emit(self.man) def clickedStopBtn(self): self.stopBtn.setEnabled(False) self.testStatus[0] = False self.man.quit() self.outputWarning("正在停止...") def clickedProvision(self): self.provWidget.show() self.changePosition(False) def clickedOthers(self): self.provWidget.hide() self.changePosition(True) def clickedGxpType(self): self.gxpAction.setChecked(True) self.grp2602Action.setChecked(False) self.webBtn.setText(self.gxpAction.text()) def clickedGrp2602(self): self.gxpAction.setChecked(False) self.grp2602Action.setChecked(True) self.webBtn.setText(self.grp2602Action.text()) def updateMessage(self): while len(self.messageList) >0: info = self.messageList.popleft() self.messageBox.append(info) if self.testStatus[0] == False: self.infoLabel.setText("未开始测试") else: info = "第" + str(self.testStatus[1]) + "次测试 " if self.testStatus[2] > 0: info += "等待:{} 秒".format( self.testStatus[2] ) else: info += "运行中" info += " " + self.testStatus[3] info += " " + self.testStatus[4] self.infoLabel.setText(info)