PO-1-Adrianna-Hornicka/03/do_sprawdzenia/histogramy.py

506 lines
21 KiB
Python

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_())