From fe9ba528ff63c44f0990a9b549f45912e630fa1c Mon Sep 17 00:00:00 2001 From: Aleksandra Jonas Date: Wed, 31 Mar 2021 00:10:28 +0200 Subject: [PATCH] =?UTF-8?q?Prze=C5=9Blij=20pliki=20do=20'03/do=5Fsprawdzen?= =?UTF-8?q?ia'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 03/do_sprawdzenia/histogramy.py | 506 ++++++++++++++++++++++++++++++++ 1 file changed, 506 insertions(+) create mode 100644 03/do_sprawdzenia/histogramy.py diff --git a/03/do_sprawdzenia/histogramy.py b/03/do_sprawdzenia/histogramy.py new file mode 100644 index 0000000..efe8d1d --- /dev/null +++ b/03/do_sprawdzenia/histogramy.py @@ -0,0 +1,506 @@ +from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt5.QtWidgets import QPushButton +import numpy as np +import math +import re +import matplotlib.pyplot as plt +from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox + + + +#from imageio import imread + + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + + MainWindow.setObjectName("MainWindow") + MainWindow.resize(1032, 847) + self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.image = QtWidgets.QLabel(self.centralwidget) + self.image.setGeometry(QtCore.QRect(0, 0, MainWindow.width(), MainWindow.height())) + self.image.setText("") + self.image.setScaledContents(False) + self.image.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.image.setWordWrap(False) + self.image.setObjectName("image") + MainWindow.setCentralWidget(self.centralwidget) + + self.menubar = QtWidgets.QMenuBar(MainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1032, 22)) + self.menubar.setObjectName("menubar") + + self.menuFile = QtWidgets.QMenu(self.menubar) + self.menuFile.setObjectName("menuFile") + self.menuEdit = QtWidgets.QMenu(self.menubar) + self.menuEdit.setObjectName("menuEdit") + self.menuView = QtWidgets.QMenu(self.menubar) + self.menuView.setObjectName("menuView") + + self.menuFilters = QtWidgets.QMenu(self.menubar) + self.menuFilters.setObjectName("menuFilters") + + self.menuDesaturation = QtWidgets.QMenu(self.menubar) + self.menuDesaturation.setObjectName("menuDesaturation") + + self.menuHist = QtWidgets.QMenu(self.menubar) + self.menuHist.setObjectName("menuHist") + + self.menuHistGenerate = QtWidgets.QMenu(self.menubar) + self.menuHistGenerate.setObjectName("menuHistGenerate") + + MainWindow.setMenuBar(self.menubar) + + self.statusbar = QtWidgets.QStatusBar(MainWindow) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.actionOpen = QtWidgets.QAction(MainWindow) + self.actionOpen.setObjectName("actionOpen") + self.actionSave_As = QtWidgets.QAction(MainWindow) + self.actionSave_As.setObjectName("actionSave_As") + self.actionExit = QtWidgets.QAction(MainWindow) + self.actionExit.setObjectName("actionExit") + self.actionCopy = QtWidgets.QAction(MainWindow) + self.actionCopy.setObjectName("actionCopy") + self.actionPaste = QtWidgets.QAction(MainWindow) + self.actionPaste.setObjectName("actionPaste") + self.actionZoom_In_25 = QtWidgets.QAction(MainWindow) + self.actionZoom_In_25.setObjectName("actionZoom_In_25") + self.actionZoom_Out_25 = QtWidgets.QAction(MainWindow) + self.actionZoom_Out_25.setObjectName("actionZoom_Out_25") + self.actionNormal_Size = QtWidgets.QAction(MainWindow) + self.actionNormal_Size.setObjectName("actionNormal_Size") + self.actionFit_to_Window = QtWidgets.QAction(MainWindow) + self.actionFit_to_Window.setObjectName("actionFit_to_Window") + + self.actionDesatHSV = QtWidgets.QAction(MainWindow) + self.actionDesatHSV.setObjectName("actionDesatHSV") + + self.actionDesatSimplified = QtWidgets.QAction(MainWindow) + self.actionDesatSimplified.setObjectName("actionDesatSimplified") + + self.actionDesatCCIR = QtWidgets.QAction(MainWindow) + self.actionDesatCCIR.setObjectName("actionDesatCCIR") + + self.actionHistGenLumine = QtWidgets.QAction(MainWindow) + self.actionHistGenLumine.setObjectName("actionHistGenLumine") + self.actionHistGenR = QtWidgets.QAction(MainWindow) + self.actionHistGenR.setObjectName("actionHistGenR") + self.actionHistGenG = QtWidgets.QAction(MainWindow) + self.actionHistGenG.setObjectName("actionHistGenG") + self.actionHistGenB = QtWidgets.QAction(MainWindow) + self.actionHistGenB.setObjectName("actionHistGenB") + self.actionHistRoz = QtWidgets.QAction(MainWindow) + self.actionHistRoz.setObjectName("actionHistRoz") + self.actionHistWyr = QtWidgets.QAction(MainWindow) + self.actionHistWyr.setObjectName("actionHistWyr") + + self.menubar.addAction(self.menuFile.menuAction()) + self.menuFile.addAction(self.actionOpen) + self.menuFile.addAction(self.actionSave_As) + self.menuFile.addSeparator() + self.menuFile.addAction(self.actionExit) + self.menubar.addAction(self.menuEdit.menuAction()) + self.menuEdit.addAction(self.actionCopy) + self.menuEdit.addAction(self.actionPaste) + self.menubar.addAction(self.menuView.menuAction()) + self.menuView.addAction(self.actionZoom_In_25) + self.menuView.addAction(self.actionZoom_Out_25) + self.menuView.addAction(self.actionNormal_Size) + self.menuView.addAction(self.actionFit_to_Window) + + + self.menubar.addAction(self.menuFilters.menuAction()) + + self.menuFilters.addAction(self.menuDesaturation.menuAction()) + self.menuDesaturation.addAction(self.actionDesatHSV) + self.menuDesaturation.addAction(self.actionDesatSimplified) + self.menuDesaturation.addAction(self.actionDesatCCIR) + + self.menubar.addAction(self.menuHist.menuAction()) + self.menuHist.addAction(self.menuHistGenerate.menuAction()) + self.menuHistGenerate.addAction(self.actionHistGenLumine) + self.menuHistGenerate.addAction(self.actionHistGenR) + self.menuHistGenerate.addAction(self.actionHistGenG) + self.menuHistGenerate.addAction(self.actionHistGenB) + self.menuHist.addAction(self.actionHistRoz) + self.menuHist.addAction(self.actionHistWyr) + + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + self.actionOpen.triggered.connect(lambda: self.loadImageFromFile()) + self.actionSave_As.triggered.connect(lambda: self.saveAs()) + self.actionZoom_In_25.triggered.connect(lambda: self.zoomInBy25()) + self.actionZoom_Out_25.triggered.connect(lambda: self.zoomOutBy25()) + self.actionNormal_Size.triggered.connect(lambda: self.normalSize()) + self.actionFit_to_Window.triggered.connect(lambda: self.fitToWindow()) + + self.actionDesatHSV.triggered.connect(lambda: self.desaturation('hsv')) + self.actionDesatSimplified.triggered.connect(lambda: self.desaturation('simplified')) + self.actionDesatCCIR.triggered.connect(lambda: self.desaturation('CCIR')) + + self.actionHistGenLumine.triggered.connect(lambda: self.generateHistogram(-1, 'show')) + self.actionHistGenR.triggered.connect(lambda: self.generateHistogram(0, 'show')) + self.actionHistGenG.triggered.connect(lambda: self.generateHistogram(1, 'show')) + self.actionHistGenB.triggered.connect(lambda: self.generateHistogram(2, 'show')) + self.actionHistRoz.triggered.connect(lambda: self.manipulateHistogram('stretch')) + self.actionHistWyr.triggered.connect(lambda: self.manipulateHistogram('eq')) + + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) + self.menuFile.setTitle(_translate("MainWindow", "File")) + self.menuEdit.setTitle(_translate("MainWindow", "Edit")) + self.menuView.setTitle(_translate("MainWindow", "View")) + self.menuFilters.setTitle(_translate("MainWindow", "Filters")) + self.actionOpen.setText(_translate("MainWindow", "Open ...")) + self.actionSave_As.setText(_translate("MainWindow", "Save As ...")) + self.actionExit.setText(_translate("MainWindow", "Exit")) + self.actionCopy.setText(_translate("MainWindow", "Copy")) + self.actionPaste.setText(_translate("MainWindow", "Paste")) + self.actionZoom_In_25.setText(_translate("MainWindow", "Zoom In (25%)")) + self.actionZoom_Out_25.setText(_translate("MainWindow", "Zoom Out (25%)")) + self.actionNormal_Size.setText(_translate("MainWindow", "Normal Size")) + self.actionFit_to_Window.setText(_translate("MainWindow", "Fit to Window")) + + self.menuDesaturation.setTitle(_translate("MainWindow", "Desaturation")) + self.actionDesatHSV.setText(_translate("MainWindow", "Based on HSV")) + self.actionDesatSimplified.setText(_translate("MainWindow", "Simplified")) + self.actionDesatCCIR.setText(_translate("MainWindow", "CCIR 601")) + + self.menuHist.setTitle(_translate("MainWindow", "Histogram")) + self.menuHistGenerate.setTitle(_translate("MainWindow", "Generate Histogram")) + self.actionHistGenLumine.setText(_translate("MainWindow", "Luminancy")) + self.actionHistGenR.setText(_translate("MainWindow", "R")) + self.actionHistGenG.setText(_translate("MainWindow", "G")) + self.actionHistGenB.setText(_translate("MainWindow", "B")) + self.actionHistRoz.setText(_translate("MainWindow", "Histogram Stretching")) + self.actionHistWyr.setText(_translate("MainWindow", "Histogram equalization")) + + + def loadImageFromFile(self): + fname = QtWidgets.QFileDialog.getOpenFileName(self.centralwidget, 'Open file', './', "Image files (*.pgm *.pbm *.ppm)") + reader = QtGui.QImageReader(fname[0]) + reader.setAutoTransform(True) + new_image = reader.read() + + self.width = new_image.width() + self.height = new_image.height() + self.nb_chanels = int(new_image.depth() / 8) if new_image.depth() > 1 else 1 + self.nb_real_channels = int(new_image.bitPlaneCount() / 8) if new_image.bitPlaneCount() > 1 else 1 + self.img_format = new_image.format() + self.image_object = new_image + self.data = [] + + for i in range(self.height): + row = [] + + for j in range(self.width): + impix = new_image.pixel(j, i) + pixel = [] + + if self.nb_chanels == 1: + pixel = [QtGui.qRed(impix)] + + elif self.nb_chanels == 3: + pixel = [QtGui.qRed(impix), QtGui.qGreen(impix), QtGui.qBlue(impix)] + + elif self.nb_chanels == 4: + pixel = [QtGui.qRed(impix), QtGui.qGreen(impix), QtGui.qBlue(impix), QtGui.qAlpha(impix)] + + row.append(pixel) + + self.data.append(row) + + self.pixmap = QtGui.QPixmap.fromImage(new_image) + self.loadImage() + + def saveAs(self): + name = QtWidgets.QFileDialog.getSaveFileName(self.centralwidget, 'Save file', './', "Image files (*.pgm *.pbm *.ppm)") + if name: + m = re.match(r'.*\/(.*\.(ppm|pgm|pbm))$', name[0]) + if m: + self.pixmap.save(m.group(1), m.group(2)) + + def loadImage(self): + self.image.setPixmap(self.pixmap) + + def zoomInBy25(self): + self.pixmap = self.pixmap.scaled(int(self.pixmap.width()*1.25), + int(self.pixmap.height()*1.25)) + self.loadImage() + + def zoomOutBy25(self): + self.pixmap = self.pixmap.scaled(int(self.pixmap.width()*0.75), + int(self.pixmap.height()*0.75)) + self.loadImage() + + def normalSize(self): + self.pixmap = QtGui.QPixmap.fromImage(self.image_object) + + self.loadImage() + + def fitToWindow(self): + self.image.resize(MainWindow.width(), MainWindow.height()) + self.pixmap = self.pixmap.scaled(MainWindow.width(), + MainWindow.height()) + self.loadImage() + + + def desaturation(self, standard): + if self.nb_chanels > 1: + data_result = [] + + for i in range(self.height): + row = [] + for j in range(self.width): + pixel = [] + + for k in range(self.nb_real_channels): + pixel.append(self.data[i][j][k]) + + if self.nb_real_channels < self.nb_chanels: + pixel.append(255) + + row.append(pixel) + + data_result.append(row) + + image_result = QtGui.QImage(self.width, self.height, self.img_format) + + if standard == 'hsv': + for i in range(self.height): + for j in range(self.width): + color = QtGui.QColor(data_result[i][j][0], + data_result[i][j][1], + data_result[i][j][2], + data_result[i][j][3]) + + + color.convertTo(2) + color.setHsv(color.hue(), 0, color.value()) + + image_result.setPixelColor(j, i, color) + elif standard == 'simplified': + for i in range(self.height): + for j in range(self.width): + R = data_result[i][j][0] + G = data_result[i][j][1] + B = data_result[i][j][2] + + gray = (max(R,G,B) + min(R,G,B))/3 + + image_result.setPixel(j, i, QtGui.qRgba(gray, + gray, + gray, + data_result[i][j][3])) + + else: #CCIR + for i in range(self.height): + for j in range(self.width): + R = data_result[i][j][0] + G = data_result[i][j][1] + B = data_result[i][j][2] + + gray = 0.299 * R + 0.587 * G + 0.114 * B + + image_result.setPixel(j, i, QtGui.qRgba(gray, + gray, + gray, + data_result[i][j][3])) + + + self.pixmap = QtGui.QPixmap.fromImage(image_result) + self.image.setPixmap(self.pixmap) + self.data = data_result + + def showDialog(self): + msgBox = QMessageBox() + msgBox.setIcon(QMessageBox.Information) + msgBox.setText("This is mono, click the Luminancy to see the histogram") + msgBox.setWindowTitle("woah woah wait a second please") + msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) + returnValue = msgBox.exec() + if returnValue == QMessageBox.Ok: + print('OK clicked') + + + def generateHistogram(self, channel, after): + + # tablica reprezentująca histogram naszego obrazu; + h = [0] * 256 + + exists = False + + if channel == -1: + if self.image_object.bitPlaneCount() == 8: + k = 0 + else: + + # histogram na luminancy dla obrazów kolorów wyliczamy na + # podstawie monochromatycznej wersji tego obrazu, dlatego + # wpierw poddajemy jego kolory desaturacji + + for i in range(self.height): + for j in range(self.width): + color = QtGui.QColor(self.data[i][j][0], + self.data[i][j][1], + self.data[i][j][2], + self.data[i][j][3]) + + + color.convertTo(2) + color.setHsv(color.hue(), 0, color.value()) + + # kolor po desaturacji ma takie same wartości na + # każdym z jego kanałów, dlatego do histogramu bierzemy + # przykładowo wartości z kanału Red + h[color.red()] += 1 + + exists = True + else: + k = channel + + # wyświetlenie komunikatu, kiedy wybieramy opcje R,G,B dla obrazów + # mono + if k in [0,1,2] and after == 'show' and self.image_object.bitPlaneCount() == 8: + self.showDialog() + exists = True + + if not exists: + for i in range(self.height): + for j in range(self.width): + h[min(255, self.data[i][j][k])] += 1 + + if after == 'show': + plt.plot(h) + plt.show(block=False) + else: + return h + + + + def manipulateHistogram(self, operation): + + image_result = QtGui.QImage(self.width, self.height, self.img_format) + + if self.nb_chanels > 1: + + for k in [0,1,2]: + if operation == 'stretch': + self.stretchHistogramOneChannel(k) + else: #wyrównanie + self.equalizeHistogramOneChannel(k) + for i in range(self.height): + for j in range(self.width): + image_result.setPixel(j, i, QtGui.qRgba(self.data[i][j][0], + self.data[i][j][1], + self.data[i][j][2], + self.data[i][j][3])) + elif self.image_object.bitPlaneCount() == 8: + if operation == 'stretch': + self.stretchHistogramOneChannel(0) + else: #wyrównanie + self.equalizeHistogramOneChannel(0) + + for i in range(self.height): + for j in range(self.width): + image_result.setPixel(j, i, QtGui.qRgba(self.data[i][j][0], + self.data[i][j][0], + self.data[i][j][0], + 255)) + self.pixmap = QtGui.QPixmap.fromImage(image_result) + self.image.setPixmap(self.pixmap) + self.generateHistogram(-1, 'show') + + + def stretchHistogramOneChannel(self, channel): + + h = self.generateHistogram(channel, 'r') + + # szukamy najmniejszej niezerowej wartości naszego histogramu i + # odczytujemy odpowiadającą mu wartość piksela + for a in range(256): + if h[a] > 0: + A = a + break + + # szukamy największej niezerowej wartości naszego histogramu i + # odczytujemy odpowiadającą mu wartość piksela + B = 0 + for a in range(256): + if h[a] > B: + B = a + + # przygotowujemy tablicę LUT + LUT = [0] * 256 + for i in range(256): + LUT[i] = int(((255/(B-A)) * (i - A))) + + + # podmieniamy wartosci pikseli korzystajac z wyzej przygotowanej + # tablicy LUT + for i in range(self.height): + for j in range(self.width): + self.data[i][j][channel] = LUT[self.data[i][j][channel]] + + + + def dystrybuanta(self, channel): + h = self.generateHistogram(channel, 'r') + + # liczba wszystkich pikseli w naszym obrazie + s = self.width * self.height + + # tablica z wartosciami dystrybuanty dla kolejnych pikseli + dys = [0] * 256 + + temp = 0 + + for i in range(256): + temp += h[i] + dys[i] = temp/s + + return dys + + + def equalizeHistogramOneChannel(self, channel): + + dys = self.dystrybuanta(channel) + + # szukamy pierwszej niezerowej wartosci dystrybuanty + i = 0 + while dys[i] == 0: + i = i + 1 + Dmin = dys[i] + + + # przygotowujemy tablicę LUT w oparciu o wzór wykorzystujący + # dystrybuantę, a następnie podmieniamy odpowiednio pikselki + + LUT = [0]*256 + + for i in range(256): + LUT[i] = round(((dys[i] - Dmin) / (1 - Dmin)) * 255) + + for i in range(self.height): + for j in range(self.width): + self.data[i][j][0] = int(LUT[self.data[i][j][0]]) + + + +if __name__ == "__main__": + import sys + + app = QtWidgets.QApplication(sys.argv) + MainWindow = QtWidgets.QMainWindow() + ui = Ui_MainWindow() + ui.setupUi(MainWindow) + MainWindow.show() + sys.exit(app.exec_()) + \ No newline at end of file