# -*- coding: utf-8 -*-

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox

# Tyto importy jsou dulezite pro pouziti TensorFlow, v tomto pripade bylo nasledne optimalizovano na TensorFlow Lite, proto jiz nejsou treba
#from keras.preprocessing.image import ImageDataGenerator
#from keras.models import Sequential
#from keras.layers import Dense, Dropout, Activation, Flatten
#from keras.layers import Conv2D, MaxPooling2D
#from tensorflow.keras.models import load_model



class Ui_MainWindow(object):

    def __init__(self):                     # Definice a inicializace promennych v potomkovi
        GPIO.setmode(GPIO.BCM)              # Nastaveni typu pristupu k GPIO pinum
        GPIO.setup(zelena, GPIO.OUT)        # Nastaveni pinu pro ovladani signalizacnich led jako Vystupni
        GPIO.setup(cervena, GPIO.OUT)

        self.porizen_snimek = False         
        self.vyhodnocen = False

        self.height_of_image = 340 #355     # Velikost snimku jedne otacky

        self.img_rgb = []                   # Zatim prazdne promenne typu list, do kterych bude pozdeji vlozen obrazek
        self.img_mono = []
        #self.img_mono_komp = np.zeros(5)
        self.img_mono_cut = []
        self.img_rectangular = []

        self.height = 0                     # Pomocne promenne
        self.width = 0
        self.height_cut = 0
        self.width_cut = 0

        #self.best_spectrum = 5


        self.img_text = []                  # List pro ukladani nalezenych vyrezu textu
        self.img_text_state = []            # List pro ukladani stavu klasifikace jednotlivych log
        self.fixa = "Hi, I'm a fix."        # String pro informaci o druhu potisku fixy

        self.saved_w = False                # Kazdy obrazek lze ukladat pouze jednou - informace o ulozeni celeho snimku
        self.saved_c = []                   # List pro informaci o ulozeni jednotlivych vyrezu

        self.zkouskacomba = False

    

    def setupUi(self, MainWindow):

        MainWindow.setObjectName("MainWindow")                                         # Vytvoreni hlavniho okna, o zvolene velikosti
        MainWindow.resize(816, 570) 
        MainWindow.setWindowIcon(QtGui.QIcon('Detekce/ikony/VisionGroup.ico'))          # Pridani ikony VUT Vision Group :-)


        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")


        # Velky RGB obrazek vlevo
        self.label_1 = QtWidgets.QLabel(self.centralwidget)
        self.label_1.setGeometry(QtCore.QRect(10, 10, 391, 401))
        self.label_1.setText("")
        self.label_1.setPixmap(QtGui.QPixmap("Detekce/ikony/white.png"))
        self.label_1.setScaledContents(True)
        self.label_1.setObjectName("label_1")
        
        
        self.groupBox1 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox1.setGeometry(QtCore.QRect(10, 420, 391, 130))
        self.groupBox1.setObjectName("groupBox")

        # Tlacitko Acquire Image
        self.tlacitko = QtWidgets.QPushButton(self.groupBox1)
        self.tlacitko.setGeometry(QtCore.QRect(5, 5, 200, 60))
        self.tlacitko.setObjectName("tlacitko")

        # Tlacitko Evaluate Imge
        self.tlacitko2 = QtWidgets.QPushButton(self.groupBox1)
        self.tlacitko2.setGeometry(QtCore.QRect(5, 65, 200, 60))
        self.tlacitko2.setObjectName("tlacitko2")
        self.tlacitko2.setEnabled(False)
        
        # Tlacitko Save whole gray-scale image
        self.tlacitko_savewhole = QtWidgets.QPushButton(self.groupBox1)
        self.tlacitko_savewhole.setGeometry(QtCore.QRect(205, 5, 181, 60)) 
        self.tlacitko_savewhole.setObjectName("tlacitko_savewhole")
        self.tlacitko_savewhole.setEnabled(False)

        # Tlacitko Save image of text:
        self.tlacitko_save = QtWidgets.QPushButton(self.groupBox1)
        self.tlacitko_save.setGeometry(QtCore.QRect(205, 65, 120, 60))
        self.tlacitko_save.setObjectName("tlacitko_save")
        self.tlacitko_save.setEnabled(False)

        # Roleta pro vyber ukladaneho vyrezu
        self.comboBox = QtWidgets.QComboBox(self.groupBox1)
        self.comboBox.setGeometry(QtCore.QRect(326, 66, 59, 58)) #(250, 520, 100, 40)
        self.comboBox.setObjectName("comboBox")
        self.comboBox.setEnabled(False)
    





        
        # velky sedotonovy obrazek vpravo
        pravybox = (415, 200, 391, 350)

        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(415, 10, 391, 180))
        self.label_2.setText("")
        self.label_2.setPixmap(QtGui.QPixmap("Detekce/ikony/white.png"))
        self.label_2.setScaledContents(True)
        self.label_2.setObjectName("label_2")

        self.groupBox2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox2.setGeometry(QtCore.QRect(pravybox[0], pravybox[1], pravybox[2], pravybox[3]))
        self.groupBox2.setObjectName("groupBox")

        # Finalni celkova klasifikace zobrazena obrazkem v pravem dolnim rohu
        final_rozmer = 130
        self.final = QtWidgets.QLabel(self.groupBox2)
        self.final.setScaledContents(True)
        self.final.setGeometry(QtCore.QRect(pravybox[2]-final_rozmer-8, pravybox[3]-final_rozmer-8, final_rozmer, final_rozmer))
        self.final.setText("")
        self.final.setPixmap(QtGui.QPixmap("Detekce/ikony/white.png"))

        # Stitek pro pomocny napis Selected channel
        label_rozmery = 70, 30
        self.label = QtWidgets.QLabel(self.groupBox2)
        self.label.setGeometry(QtCore.QRect(pravybox[2]-label_rozmery[0], 5, label_rozmery[0], label_rozmery[1]))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label.setFont(font)
        self.label.setObjectName("label")

        # Obrazek barvy osvetleni pouziteho k vyhodnocovacim algoritmum
        spektrum_rozmer = 70
        self.spektrum = QtWidgets.QLabel(self.groupBox2)
        self.spektrum.setGeometry(QtCore.QRect(pravybox[2]-spektrum_rozmer-8, 10+label_rozmery[1], spektrum_rozmer, spektrum_rozmer))
        self.spektrum.setText("")
        self.spektrum.setPixmap(QtGui.QPixmap("Detekce/ikony/white.png"))
        self.spektrum.setScaledContents(True)
        self.spektrum.setObjectName("spektrum")
        


        # Jednotlive obrazky vyrezu
        self.label_7 = QtWidgets.QLabel(self.groupBox2)
        self.label_7.setScaledContents(True)

        self.label_8 = QtWidgets.QLabel(self.groupBox2)
        self.label_8.setScaledContents(True)

        self.label_9 = QtWidgets.QLabel(self.groupBox2)
        self.label_9.setScaledContents(True)

        self.label_10 = QtWidgets.QLabel(self.groupBox2)
        self.label_10.setScaledContents(True)

        self.polelabelu = [self.label_7, self.label_8, self.label_9, self.label_10]
        

        # Jenotlive obrazky vysledku klasifikaci vyrezu
        self.label_11 = QtWidgets.QLabel(self.groupBox2)
        self.label_11.setScaledContents(True)

        self.label_12 = QtWidgets.QLabel(self.groupBox2)
        self.label_12.setScaledContents(True)

        self.label_13 = QtWidgets.QLabel(self.groupBox2)
        self.label_13.setScaledContents(True)

        self.label_14 = QtWidgets.QLabel(self.groupBox2)
        self.label_14.setScaledContents(True)

        self.polelabelu2 = [self.label_11, self.label_12, self.label_13, self.label_14]

        
        
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 877, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)



        # Zamapovani rutin pri zmacknuti jednotlivych tlacitek
        self.tlacitko.clicked.connect(self.pressed)
        self.tlacitko2.clicked.connect(self.vyhodnot)
        self.tlacitko_save.clicked.connect(self.save_founded)
        self.tlacitko_savewhole.clicked.connect(self.save_wholeimg)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)


    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Printing Defect Detector"))
        self.tlacitko.setText(_translate("MainWindow", "Acquire Image"))
        self.tlacitko2.setText(_translate("MainWindow", "Evaluate Image"))
        self.tlacitko_save.setText(_translate("MainWindow", "Save image \n of text:"))
        self.tlacitko_savewhole.setText(_translate("MainWindow", "Save whole \n gray-scale image"))
        self.label.setText(_translate("MainWindow", "Selected\nchannel"))

        self.comboBox.setItemText(0, _translate("MainWindow", "1"))
        self.comboBox.setItemText(1, _translate("MainWindow", "2"))
        self.comboBox.setItemText(2, _translate("MainWindow", "3"))


    def save_founded(self):                 # Ukladani obrazku vyrezu
        if self.vyhodnocen == True:

            if len(self.img_text) < self.comboBox.currentIndex():
                msg = QMessageBox()
                msg.setWindowTitle("Error Message")
                msg.setText("The text does not exist, choose another!")
                x = msg.exec_()

            else:
                if not self.saved_c[self.comboBox.currentIndex()]:
                    self.saved_c[self.comboBox.currentIndex()] = True
                    

                    os.chdir("./Detekce/ulozene_snimky/cut")
                    with open('./../cut_idx.txt', 'r+') as f:
                        cislo = int(f.read())
                        f.seek(0)
                        f.truncate()
                        cislo = str(cislo+1)
                        f.write(cislo)

                    nazev_cut = 'img_cu_' + str(cislo.zfill(4)) + ".png"

                    ulozit = np.uint8(self.img_text[self.comboBox.currentIndex()])
                    ulozit = Image.fromarray(ulozit)
                    ulozit.save(nazev_cut)

                    os.chdir("./../../..")

        else:
            msg = QMessageBox()
            msg.setWindowTitle("Error Message")
            msg.setText("The image have not been acquitted!")
            x = msg.exec_()



    def save_wholeimg(self):                # Funkce pro ukladani celych sedotonovych snimku
        #self.tlacitko_savewhole.setEnabled(False)
        if not self.saved_w:
            #self.tlacitko_savewhole.setEnabled(False)
            os.chdir("./Detekce/ulozene_snimky/whole")
            with open('./../whole_idx.txt', 'r+') as f:
                cislo = int(f.read())
                f.seek(0)
                f.truncate()
                cislo = str(cislo+1)
                f.write(cislo)

            nazev_whole = 'img_wh_' + str(cislo.zfill(4)) + ".png"

            ulozit = np.uint8(self.img_mono_cut)
            ulozit = Image.fromarray(ulozit)
            ulozit.save(nazev_whole)

            os.chdir("./../../..")
            self.saved_w = True
        
            


        
    def vyhodnot(self):                         # Hlavni metoda vyhodnoceni, jeji spusteni je pri stisku tlacitka Evaluate Image
        if self.porizen_snimek:                 # Pouze pokud je porizen snimek
            self.najditext(copy.deepcopy(self.img_mono_cut))    # Nalezeni jednotlivych log v obrazku

            # Zobrazeni sedotonoveho snimku i s pridanymi ramecky oznacujicimi nalezena loga
            qi = QtGui.QImage(self.img_rectangular.data, self.img_rectangular.shape[1], self.img_rectangular.shape[0], self.img_rectangular.shape[1], QtGui.QImage.Format_Indexed8)
            qp = QtGui.QPixmap.fromImage(qi)
            self.label_2.setPixmap(QtGui.QPixmap(qp))
            
            self.klasifikuj()                   # Volani metody pro klasifikaci kvality jednotlivych log


            xminrozmer = 10000                  
            ymaxrozmer = 0
            for i in self.img_text:             # Cyklus pro nalezeni nejmensiho vertikalniho a nejvetsiho horizontalniho rozmeru nalezeneho loga
                if i.shape[0] < xminrozmer:
                    xminrozmer = i.shape[0]
                if i.shape[1] > ymaxrozmer:
                    ymaxrozmer = i.shape[1]


            vert_koor = 8
            hori_koor = 8
            for i, (im, state) in enumerate(zip(self.img_text,self.img_text_state)):            # Cyklus tisku jednotlivych nalezenych log a jejich vysledku


                qi = QtGui.QImage(im.data, im.shape[1], im.shape[0], im.shape[1], QtGui.QImage.Format_Indexed8)
                qp = QtGui.QPixmap.fromImage(qi)
                self.polelabelu[i].setGeometry(QtCore.QRect(hori_koor, vert_koor, im.shape[1], im.shape[0]))
                self.polelabelu[i].setPixmap(QtGui.QPixmap(qp))

                self.polelabelu2[i].setGeometry(QtCore.QRect(hori_koor+ymaxrozmer+10, vert_koor, xminrozmer, xminrozmer))
                if self.img_text_state[i] == True:
                    self.polelabelu2[i].setPixmap(QtGui.QPixmap("Detekce/ikony/ok.png"))
                else:
                    self.polelabelu2[i].setPixmap(QtGui.QPixmap("Detekce/ikony/nok.png"))

                vert_koor = vert_koor+im.shape[0]+10



            
            final = True
            for i in self.img_text_state:                                                     # Cyklus zjisteni celkoveho stavu potisku fixy na zaklade klasifikace jednotlivych log
                final = final and i

            #self.final.setGeometry(QtCore.QRect(681, 250, 100, 100))
            if final == True:                                                                 # Nasledne zobrazeni prislusneho informacniho obrazku
                self.final.setPixmap(QtGui.QPixmap("Detekce/ikony/ok.png"))
                GPIO.output(zelena, GPIO.HIGH)
                GPIO.output(cervena, GPIO.LOW)
            else:
                self.final.setPixmap(QtGui.QPixmap("Detekce/ikony/nok.png"))
                GPIO.output(cervena, GPIO.HIGH)
                GPIO.output(zelena, GPIO.LOW)

            ''' prototyp printovani bez nutonosti ukladat - funguje u sedotonoveho obrazku
            im = self.img_text[0]
            qi = QtGui.QImage(im.data, im.shape[1], im.shape[0], im.shape[1], QtGui.QImage.Format_Indexed8)
            qp = QtGui.QPixmap.fromImage(qi)
            self.label_7.setGeometry(QtCore.QRect(420, 250, im.shape[1], im.shape[0]))
            self.label_7.setPixmap(QtGui.QPixmap(qp))
            '''

            self.porizen_snimek = False                                                        # Nastaveni pomocnych promennych
            self.vyhodnocen = True
            self.tlacitko2.setEnabled(False)
            self.tlacitko_save.setEnabled(True)
            self.saved_c = list(False for x in range(len(self.img_text)))
            self.comboBox.setEnabled(True)


            #generovani moznosti ulozeni obrazku
            self.comboBox.clear() #vymaze, aby se tam nekumulovaly možnosti
            for i in range(len(self.img_text)):
                self.comboBox.addItem(str(i+1))



        else:
            pass


    def pressed(self):                                                      # Metoda pro obsluhu akvizice, zavola se pro stisku tlacitka Acquire Image

        # Vymaz data k minulemu snimku
        self.vyhodnocen = False
        self.img_text = []
        self.img_text_state = []
        #self.final.setGeometry(QtCore.QRect(0, 0, 0, 0))
        self.final.setPixmap(QtGui.QPixmap("Detekce/ikony/white.png"))
        for i in range(len(self.polelabelu)):
            #print(i)
            self.polelabelu[i].setGeometry(QtCore.QRect(0, 0, 0, 0))
            self.polelabelu2[i].setGeometry(QtCore.QRect(0, 0, 0, 0))
        self.saved_w = False
        self.tlacitko_save.setEnabled(False)
        self.comboBox.setEnabled(False)
        GPIO.output(zelena,GPIO.LOW)
        GPIO.output(cervena,GPIO.LOW)

        # Nastaveni cesty k akvizicnimu c++ skriptu, jeho spusteni a navrat zpet do puvodniho adresare
        os.chdir("./Akvizice")
        subprocess.call("./Akvizice")
        os.chdir("./..")

        self.img_rgb = self.nacti()                     # Nacteni porizeneho snimku

        [nejlepsi, svetly] = self.vyberkanalu()         # Vyber nejkontrastnejsiho kanalu pro nasledne algoritmy
        #print('svetly?',svetly)

        self.img_mono = self.img_rgb[:,:,nejlepsi]      # Ulozeni nejlepsiho kanalu
        [self.height,self.width] = self.img_mono.shape  # Ulozeni rozmeru

        #self.img_mono = self.kompenzace(self.img_mono, svetly)         # Kompenzace nerovnomernosti osvetleni - ted vypnuta, zpomaluje a funguje i bez
        
        self.label_1.setPixmap(QtGui.QPixmap("RGBobrazek.png"))         # Zobrazeni RGB obrazku

        if nejlepsi == 0:                                               # Zobrazeni obrazku nejlepsiho spektra osvetleni pro tento snimek
            self.spektrum.setPixmap(QtGui.QPixmap("Detekce/ikony/red.png"))
        if nejlepsi == 1:
            self.spektrum.setPixmap(QtGui.QPixmap("Detekce/ikony/green.png"))
        if nejlepsi == 2:
            self.spektrum.setPixmap(QtGui.QPixmap("Detekce/ikony/blue.png"))


        self.img_mono_cut = np.uint8(self.take_the_rigt_space(self.img_mono))   # Vyriznuti jedne otacky
        

        # Zobrazeni obrazku jedne otacky
        qi = QtGui.QImage(self.img_mono_cut.data, self.img_mono_cut.shape[1], self.img_mono_cut.shape[0], self.img_mono_cut.shape[1], QtGui.QImage.Format_Indexed8)
        qp = QtGui.QPixmap.fromImage(qi)
        self.label_2.setPixmap(QtGui.QPixmap(qp))

        # Nastaveni pomocnych promennych
        self.porizen_snimek = True
        self.tlacitko2.setEnabled(True)
        self.tlacitko_savewhole.setEnabled(True)








    def nacti(self):                                                            # Metoda pro nacteni a parsovani suroveho snimku
        #puv0 = cv2.imread('PUVODNI.png',0)
        #puv0 = cv2.imread('../im6_bin3.png',0)
        #puv0 = cv2.imread('../tucnak.png',0)
        #puv0 = cv2.imread('../im7_bin3.png',0)
        #puv0 = cv2.imread('../im4_bin3.png',0)
        #puv0 = cv2.imread('../im_vada.png',0)
        #puv0 = mpimg.imread('C:/Users/tosuj/Desktop/dip/vystup_0005.png')

        puv0 = cv2.imread('./Akvizice/rawsnimek.png',0)                         # Nacteni suroveho snimku
        
        # Tento orez zalezi zda se zpracovavaji nove porizene snimky, nebo jiz oriznute ulozene
        puv = puv0[:,49:650]   # binning 3 
        #puv = puv0              # resp. pro jiz upravene

        size = puv.shape

        #----------------------------------- Rozdeleni do tri kanalu------------------------------

        img = np.zeros((int(size[0]/3),size[1],3), dtype=int)
        img = np.uint(img)
        radek = 0;
        for i in range(1,size[0],3):
            img[radek,:,0] = puv[i-1,:]
            img[radek,:,1] = puv[i,:]
            img[radek,:,2] = puv[i+1,:]
            radek = radek+1

        #BestOne = img[:,:,1]
        
        img = np.rot90(img,2)

        ulozit = np.uint8(img)                          # Ulozeni RGB snimku
        ulozit = Image.fromarray(ulozit, 'RGB')
        ulozit.save('RGBobrazek.png')
        return img










    def vyberkanalu(self):                              # Metoda pro vyber nejkontrastnejsiho kanalu pro dany snimek, vyhodnoceni na zaklade dvou nejvetsich peaku v histogramu kanalu

        h = np.zeros((3,256),dtype=int)
        h = np.uint(h)

        #kanal = 0
        idxmax = np.zeros((3), dtype=int)
        idxmax = np.uint(idxmax)

        idxmax2 = np.zeros((3), dtype=int)
        idxmax2 = np.uint(idxmax2)

        hyst = 40                                       # Hystereze pro urceni, kdy se uz jedna o druhy peak 

        for vyska in range(self.img_rgb.shape[2]):
            a = np.histogram(self.img_rgb[:,:,vyska].ravel(), 256, [0, 256])
            h[vyska,:] = a[0]



            idxmax[vyska] = np.argmax(h[vyska,:])

            if idxmax[vyska]+hyst > 255:
                h[vyska,(idxmax[vyska]-hyst):] = 0
            elif (idxmax[vyska]-hyst)<0:
                h[vyska,:idxmax[vyska]+hyst] = 0
            else:
                h[vyska, idxmax[vyska]-hyst:idxmax[vyska]+hyst] = 0

            idxmax2[vyska] = np.argmax(h[vyska,:])
            

        idxmax = np.int16(idxmax)
        idxmax2 = np.int16(idxmax2)

        ratio = abs(idxmax-idxmax2)

        Best = np.argmax(ratio)

        svetly = idxmax[Best] > 128
        return [Best,svetly]



    def kompenzace(self, BestOne, LightOne):                        # Kompenzace nerovnomernosti osvetleni

        size = BestOne.shape
        hist = np.zeros((size[1],256), dtype=int)
        #print("Hist shape:",hist.shape)

        hist = np.uint(hist)                                    
        #print(BestOne.shape)
        for i in range(size[1]):                                    # Pocitani histogramu sloupcu
            a = np.histogram(BestOne[:,i].ravel(), 256, [0, 256])
            hist[i,:] = a[0]

        cumulhist = hist
        cumulhist = np.uint32(cumulhist)
        for i in range(1,256):                                      # Vypocet kumulovaneho histogramu
            cumulhist[:,i] = hist[:,i] + cumulhist[:,i-1]

        
        if LightOne == True:                                        # Urceni 0.9 resp. 0.2 kvantilu podle toho zda je snimek tmavy nebo svetly - zjisteno dle hlavniho peaku histogramu
            kv = int(0.9*size[0])
        else: 
            kv = int(0.2*size[0])
        #print(kv)

        mez = np.zeros((1,size[1]), dtype=int)

        for i in range(size[1]):                                    # Vypocet intenzity osvetleni sloupcu dle daneho kvantilu
            j = 1
            while cumulhist[i,j]<kv:
                j = j+1
            mez[0,i] = j

        BestOne = np.uint(BestOne)

        if LightOne == True:                                         # Aplikace vytvorene kompenzacni funkce na obrazek
            for i in range(int(size[0])):
                BestOne[i,:] = np.clip((BestOne[i,:])/mez*230, a_min = 0, a_max = 255)
        else:
            for i in range(int(size[0])):
                BestOne[i,:] = np.clip((BestOne[i,:])/mez*30, a_min = 0, a_max = 255)

        ########################### UKLADANI ##########################
        '''
        plt.figure()
        plt.imshow(BestOne,cmap='gray', vmin=0, vmax=255)
        plt.title('Kompenzovane osvetleni - jeden kanal')
        plt.show()
        '''


        ulozit = np.uint8(BestOne)                                     # Ulozeni
        ulozit = Image.fromarray(ulozit)
        ulozit.save('VYBRANYobrazek.png')

        return BestOne






    def take_the_rigt_space(self, Obrazek):                             # Metoda slouzi k vyrezu jedne otacky z obrazku a to tak aby nebyl predel v oblastech loga
        #BestOne = Obrazek
        height_of_img = self.height_of_image
        [msize,nsize] = Obrazek.shape
        msize = np.uint(np.round(msize/2)) # budu prohledavat volny pruh jen do poloviny obrazku,
        # aby pak bylo z ceho ten obrazek vyriznout

        hist_vyb = np.zeros((msize,256),dtype=int)
        hist_vyb = np.uint(hist_vyb)

        jenulovy = np.zeros((msize,1), dtype=bool)

        for i in range(msize):                                          # Vypocet histogramu radku obrazku
        	a = np.histogram(Obrazek[i,:].ravel(), 256, [0, 256])
        	hist_vyb[i,:] = a[0]

        
        for i in range(msize):                                          # Zjistuje se maximalni peak histogramu, pokud v druhe polovine hodnot histogramu nez je peak nelezi zadny pixel, je nalezen prazdny radek
        	pozice = np.argmax(hist_vyb[i,:])
        	if pozice > 128:
        		jenulovy[i] = not np.any(hist_vyb[i,0:128])
        	if pozice <= 128:
        		jenulovy[i] = not np.any(hist_vyb[i,128:])
        

        if (not np.any(jenulovy)) or np.all(jenulovy):                  # Muze se stat, ze zminene nalezeni radku nefunguje spravne a nic nenajde. V takovem pripade je prazdny radek nalezen, pokud mimo oblast max peaku s hysterezi neni zadny pixel 
            pasmo = 60                                                  # hystereze
            for i in range(msize):
                pozice = np.argmax(hist_vyb[i,:])
                if (np.any(hist_vyb[i,:(pozice-pasmo)]) or np.any(hist_vyb[i,(pozice+pasmo):])):
                    jenulovy[i] = False
                else:
                    jenulovy[i] = True

                
        nejtlustsi_idx = 0
        pocet = 0
        nejtlustsi_pocet = 0
        idx = 0

        for i in jenulovy:                                              # vyrez vystupniho obrazku je veden polovinou prazdnych radku vstupniho obrazku

        	if i:
        		pocet = pocet + 1
        		if pocet > nejtlustsi_pocet:
        			nejtlustsi_pocet = pocet
        			nejtlustsi_idx = idx
        	else:
        		pocet = 0
        	idx = idx+1


        nejtlustsi_idx = nejtlustsi_idx - np.round(nejtlustsi_pocet/2)

        nejtlustsi_idx = np.uint(nejtlustsi_idx)




        cut = Obrazek[nejtlustsi_idx:nejtlustsi_idx+height_of_img,:]

        #ulozit = np.uint8(cut)
        #ulozit = Image.fromarray(ulozit)
        #ulozit.save('CUT_obr.png')

        return cut








    def najditext(self,img):                                            # Metoda nalezeni potisku loga v porizenem snimku
        # Nacteni referencnich vzoru, z kazdeho z moznych druhu potisku jeden zastupce
        template_power = cv2.imread('Detekce/ref/ref_power.png',0)
        template_trio = cv2.imread('Detekce/ref/ref_trio.png',0)
        template_cina = cv2.imread('Detekce/ref/ref_cina.png',0)
        template_tucnak = cv2.imread('Detekce/ref/ref_tucnak.png',0)

        # Je provdeno srovnani se vzorem obrazku a referencniho vzoru
        res_power = cv2.matchTemplate(img, template_power, cv2.TM_CCOEFF_NORMED)
        res_trio = cv2.matchTemplate(img, template_trio, cv2.TM_CCOEFF_NORMED)
        res_cina = cv2.matchTemplate(img, template_cina, cv2.TM_CCOEFF_NORMED)
        res_tucnak = cv2.matchTemplate(img, template_tucnak, cv2.TM_CCOEFF_NORMED)

        # Je vytvoren slovnik, kde identifikatorem je nazev druhu potisku fixy, jeho hodnotou je maximalni hodnota srovnani se vzorem prislusneho zastupce
        # Dle maximalni hodnoty tohoto slovniku je nasledne urceno o jaky druh fixy, resp. potisku fixy se jedna. Podle toho se pak voli srovnavane vzory
        srovnani = {'power':np.max(res_power), 'trio':np.max(res_trio), 'cina':np.max(res_cina), 'tucnak':np.max(res_tucnak)}
        fixa = max(srovnani.items(), key=operator.itemgetter(1))[0]       


        
        if fixa == 'power':
            h_power,w_power = template_power.shape
            
            loc_power = np.where(res_power==np.max(res_power))
            pt_power = loc_power[::-1]

            #stabilo
            template_powerstabilo = cv2.imread('Detekce/ref/ref_powerstabilo.png',0)
            h_powerstabilo,w_powerstabilo = template_powerstabilo.shape
            res_powerstabilo = cv2.matchTemplate(img, template_powerstabilo, cv2.TM_CCOEFF_NORMED)
            loc_powerstabilo = np.where(res_powerstabilo==np.max(res_powerstabilo))
            pt_powerstabilo = loc_powerstabilo[::-1]

            #CE
            template_power_CE = cv2.imread('Detekce/ref/ref_power_CE.png',0)
            h_power_CE,w_power_CE = template_power_CE.shape
            res_power_CE = cv2.matchTemplate(img, template_power_CE, cv2.TM_CCOEFF_NORMED)
            loc_power_CE = np.where(res_power_CE==np.max(res_power_CE))
            pt_power_CE = loc_power_CE[::-1]

            self.img_text.append(copy.deepcopy(img[pt_powerstabilo[1][0]:pt_powerstabilo[1][0]+h_powerstabilo,pt_powerstabilo[0][0]:pt_powerstabilo[0][0]+w_powerstabilo]))
            self.img_text.append(copy.deepcopy(img[pt_power[1][0]:pt_power[1][0]+h_power,pt_power[0][0]:pt_power[0][0]+w_power]))
            self.img_text.append(copy.deepcopy(img[pt_power_CE[1][0]:pt_power_CE[1][0]+h_power_CE,pt_power_CE[0][0]:pt_power_CE[0][0]+w_power_CE]))
            
            # Vykresleni ramecku oznacujiciho nalezene logo
            cv2.rectangle(img,pt_power, (pt_power[0]+w_power, pt_power[1]+h_power), (255), 2)
            cv2.rectangle(img,pt_powerstabilo, (pt_powerstabilo[0]+w_powerstabilo, pt_powerstabilo[1]+h_powerstabilo), (255), 2)
            cv2.rectangle(img,pt_power_CE, (pt_power_CE[0]+w_power_CE, pt_power_CE[1]+h_power_CE), (255), 2)


        elif fixa == 'trio':
            h_trio,w_trio = template_trio.shape

            loc_trio = np.where(res_trio==np.max(res_trio))
            pt_trio = loc_trio[::-1]
            
            
            # stabilo
            template_triostabilo = cv2.imread('Detekce/ref/ref_triostabilo.png',0)
            h_triostabilo,w_triostabilo = template_triostabilo.shape
            res_triostabilo = cv2.matchTemplate(img, template_triostabilo, cv2.TM_CCOEFF_NORMED)
            loc_triostabilo = np.where(res_triostabilo==np.max(res_triostabilo))
            pt_triostabilo = loc_triostabilo[::-1]

            # CE
            template_trio_CE = cv2.imread('Detekce/ref/ref_trio_CE.png',0)
            h_trio_CE,w_trio_CE = template_trio_CE.shape
            res_trio_CE = cv2.matchTemplate(img, template_trio_CE, cv2.TM_CCOEFF_NORMED)
            loc_trio_CE = np.where(res_trio_CE==np.max(res_trio_CE))
            pt_trio_CE = loc_trio_CE[::-1]

            self.img_text.append(copy.deepcopy(img[pt_triostabilo[1][0]:pt_triostabilo[1][0]+h_triostabilo,pt_triostabilo[0][0]:pt_triostabilo[0][0]+w_triostabilo]))
            self.img_text.append(copy.deepcopy(img[pt_trio[1][0]:pt_trio[1][0]+h_trio,pt_trio[0][0]:pt_trio[0][0]+w_trio]))
            self.img_text.append(copy.deepcopy(img[pt_trio_CE[1][0]:pt_trio_CE[1][0]+h_trio_CE,pt_trio_CE[0][0]:pt_trio_CE[0][0]+w_trio_CE]))
            
            cv2.rectangle(img,pt_triostabilo, (pt_triostabilo[0]+w_triostabilo, pt_triostabilo[1]+h_triostabilo), (255), 2)
            cv2.rectangle(img,pt_trio, (pt_trio[0]+w_trio, pt_trio[1]+h_trio), (255), 2)
            cv2.rectangle(img,pt_trio_CE, (pt_trio_CE[0]+w_trio_CE, pt_trio_CE[1]+h_trio_CE), (255), 2)



        elif fixa == 'cina':

            h_cina,w_cina = template_cina.shape
            
            loc_cina = np.where(res_cina==np.max(res_cina))

            pt_cina = loc_cina[::-1]

            template_czech = cv2.imread('Detekce/ref/ref_czech.png',0)
            h_czech,w_czech = template_czech.shape
            
            res_czech = cv2.matchTemplate(img, template_czech, cv2.TM_CCOEFF_NORMED)
            loc_czech = np.where(res_czech==np.max(res_czech))

            pt_czech = loc_czech[::-1]

            template_company = cv2.imread('Detekce/ref/ref_company.png',0)
            h_company,w_company = template_company.shape
            
            res_company = cv2.matchTemplate(img, template_company, cv2.TM_CCOEFF_NORMED)
            loc_company = np.where(res_company==np.max(res_company))

            pt_company = loc_company[::-1]

            self.img_text.append(copy.deepcopy(img[pt_cina[1][0]:pt_cina[1][0]+h_cina,pt_cina[0][0]:pt_cina[0][0]+w_cina]))
            self.img_text.append(copy.deepcopy(img[pt_czech[1][0]:pt_czech[1][0]+h_czech,pt_czech[0][0]:pt_czech[0][0]+w_czech]))
            self.img_text.append(copy.deepcopy(img[pt_company[1][0]:pt_company[1][0]+h_company,pt_company[0][0]:pt_company[0][0]+w_company]))
            
            cv2.rectangle(img,pt_cina, (pt_cina[0]+w_cina, pt_cina[1]+h_cina), (0), 2)
            cv2.rectangle(img,pt_czech, (pt_czech[0]+w_czech, pt_czech[1]+h_czech), (0), 2)
            cv2.rectangle(img,pt_company, (pt_company[0]+w_company, pt_company[1]+h_company), (0,), 2)


        elif fixa == 'tucnak':
            h_tucnak,w_tucnak = template_tucnak.shape

            loc_tucnak = np.where(res_tucnak==np.max(res_tucnak))

            pt_tucnak = loc_tucnak[::-1]

            template_czech = cv2.imread('Detekce/ref/ref_czech.png',0)
            h_czech,w_czech = template_czech.shape
            
            res_czech = cv2.matchTemplate(img, template_czech, cv2.TM_CCOEFF_NORMED)
            loc_czech = np.where(res_czech==np.max(res_czech))

            pt_czech = loc_czech[::-1]

            self.img_text.append(copy.deepcopy(img[pt_tucnak[1][0]:pt_tucnak[1][0]+h_tucnak,pt_tucnak[0][0]:pt_tucnak[0][0]+w_tucnak]))
            self.img_text.append(copy.deepcopy(img[pt_czech[1][0]:pt_czech[1][0]+h_czech,pt_czech[0][0]:pt_czech[0][0]+w_czech]))
            
            cv2.rectangle(img,pt_tucnak, (pt_tucnak[0]+w_tucnak, pt_tucnak[1]+h_tucnak), (0), 2)
            cv2.rectangle(img,pt_czech, (pt_czech[0]+w_czech, pt_czech[1]+h_czech), (0), 2)

        self.img_rectangular = img
        self.fixa = fixa
        #return [fixa, 1]
        


    def klasifikuj(self):                                       # Metoda pro klasifikaci nalezenych oblasti loga

        img_text = copy.deepcopy(self.img_text)                 # Hluboka kopie jednotlivych nalezenych vzoru

        # Dle typu potisku fixy je vybrana spravna sada klasifikatoru na kazde logo
        if self.fixa == "power":
            modely = ['stabilo_powerklas', 'powerklas', 'ce_powerklas']    # musí být ve správném pořadí, jako bylo uloženo, aby byl na daný obrázek použit správný klasifikátor
        
        if self.fixa == "trio":
            modely = ['stabilo_trioklas', 'trioklas', 'ce_trioklas']

        if self.fixa == "cina":
            modely = ['washableklas', 'czechklas', 'companyklas']

        if self.fixa == "tucnak":
            modely = ['tucnakklas', 'czechklas']
            
        
        #idx = 0
        for idx, i in enumerate(modely):                        # V cyklu se upravi velikost klasifikovaneho snimku, dle reference klasifikatoru, normalizuje se, a zavola se funkce pro klasifikaci
            interpreter = tflite.Interpreter(model_path="Detekce/klasifikatory_lite/"+i+".tflite")
            interpreter.allocate_tensors()

            input_details = interpreter.get_input_details()
            output_details = interpreter.get_output_details()

            input_size = input_details[0]['shape']                                     #resize dle vstupu klasifikatoru, ten by mel byt podle templatu
            img_text[idx] =  cv2.resize(img_text[idx], (input_size[2], input_size[1]))      #resize ma rozmery prehozene naopak - nevim proc, zvlastni

            img_text[idx] = img_text[idx]/255.0
            img_text[idx] = img_text[idx][np.newaxis,:]
            img_text[idx] = np.expand_dims(img_text[idx], axis=3)
            img_text[idx] = np.float32(img_text[idx])
            
            self.img_text_state.append(self.urcitridu(interpreter, img_text[idx], input_details, output_details))   # volani funkce pro klasifikaci, vysledek se prida do stavoveho listu
            #idx = idx+1

    
    def urcitridu(self, interpreter, obr, input_details, output_details):               # Funkce pro klasifikaci
        interpreter.set_tensor(input_details[0]['index'], obr)
        interpreter.invoke()
        output_data = interpreter.get_tensor(output_details[0]['index'])
        
        '''
        if vyst > 0.5:
            return False
        if vyst <= 0.5:
            return True
        '''
        print(output_data)
        if np.argmax(output_data) == 0: #One Hot Encoding, nultý výstupní neuron značí hodnotu ok, první nok
            return True
        else:
            return False









if __name__ == "__main__":                      # Main funkce
    # Import nezbytnych modulu
    import sys
    import os
    import subprocess

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.image as mpimg
    import cv2
    from PIL import Image
    import copy
    import operator
    import tflite_runtime.interpreter as tflite
    import RPi.GPIO as GPIO

    cervena = 4                                 # Cisla GPIO pinu, na kterych jsou signalizacni kontrolky
    zelena = 16

    # Volani jednotlivych trid a metod
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())
