Εργαλεία Χρήστη

Εργαλεία ιστότοπου


opencv

Σύγκριση εκδόσεων

Εδώ βλέπετε τις διαφορές μεταξύ της επιλεγμένης έκδοσης και της τρέχουσας έκδοσης της σελίδας.

Σύνδεσμος σε αυτή την προβολή διαφορών.

Προηγούμενος έλεγχος και από τις δύο πλευρές Προηγούμενη αναθεώρηση
Επόμενη αναθεώρηση
Προηγούμενη αναθεώρηση
opencv [2020/02/23 11:28]
John_Crabs
opencv [2020/11/21 09:52] (τρέχουσα)
Γραμμή 5: Γραμμή 5:
 ====== Εισαγωγή στην OpenCV ====== ====== Εισαγωγή στην OpenCV ======
  
-====Τι είναι η OpenCV====+ 
 +=====Τι είναι η OpenCV=====
  
 Η OpenCV(Open-source Computer Vision) είναι μία βιβλιοθήκη που περιέχει συναρτήσεις, οι οποίες στοχεύουν στη δημιουργία εφαρμογών όρασης υπολογιστών σε πραγματικό χρόνο. Αρχικά αναπτύχθηκε από την Intel, αλλά στη συνέχεια υποστηρήχθηκε από την Willow Garage. Η βιβλιοθήκη μπορεί να χρησιμοποιηθεί σε όλα τα λειτουργικά συστήματα (Windows, Linux, Mac) και μπορεί να χρησιμοποιηθεί δωρεάν, έχοντας άδεια τύπου BSD. Η OpenCV(Open-source Computer Vision) είναι μία βιβλιοθήκη που περιέχει συναρτήσεις, οι οποίες στοχεύουν στη δημιουργία εφαρμογών όρασης υπολογιστών σε πραγματικό χρόνο. Αρχικά αναπτύχθηκε από την Intel, αλλά στη συνέχεια υποστηρήχθηκε από την Willow Garage. Η βιβλιοθήκη μπορεί να χρησιμοποιηθεί σε όλα τα λειτουργικά συστήματα (Windows, Linux, Mac) και μπορεί να χρησιμοποιηθεί δωρεάν, έχοντας άδεια τύπου BSD.
Γραμμή 11: Γραμμή 12:
 Επίσης η OpenCV υποστηρίζει συστήματα Deep Learning, όπως είναι το TensorFlow, Torch/Pytorch και Caffe.  Επίσης η OpenCV υποστηρίζει συστήματα Deep Learning, όπως είναι το TensorFlow, Torch/Pytorch και Caffe. 
  
-====Βασικές εφαρμογές της OpenCV====+ 
 + 
 + 
 + 
 + 
 + 
 + 
 +=====Βασικές εφαρμογές της OpenCV=====
  
 Όπως και με κάθε άλλη γλώσσα προγραμματισμού, έτσι και με τις βιβλιοθήκες, η διαδικασία εκμάθησης πρέπει να ακολουθεί κάποια στάδια. Το κλασικό Hello World που μαθαίνει κανείς σε μία γλώσσα προγραμματισμού, στην OpenCV θεωρείται η διαδικασία **Ανοίγματος Εκόνας - Μικρή Επεξεργασία - Εξαγωγή Εικόνας**. Όλα τα παραδείγματα της ενότητας αυτής, θα ακολουθήσουν αυτή τη δομή. Η επεξεργασία μπορεί να είναι από την αλλαγή φωτεινότητας της εικόνας, μέχρι την επεξεργασία της εικόνας χρησιμοποιώντας κάποιο φίλτρο. Όπως και με κάθε άλλη γλώσσα προγραμματισμού, έτσι και με τις βιβλιοθήκες, η διαδικασία εκμάθησης πρέπει να ακολουθεί κάποια στάδια. Το κλασικό Hello World που μαθαίνει κανείς σε μία γλώσσα προγραμματισμού, στην OpenCV θεωρείται η διαδικασία **Ανοίγματος Εκόνας - Μικρή Επεξεργασία - Εξαγωγή Εικόνας**. Όλα τα παραδείγματα της ενότητας αυτής, θα ακολουθήσουν αυτή τη δομή. Η επεξεργασία μπορεί να είναι από την αλλαγή φωτεινότητας της εικόνας, μέχρι την επεξεργασία της εικόνας χρησιμοποιώντας κάποιο φίλτρο.
Γραμμή 17: Γραμμή 25:
 Ας ξεκινήσουμε λοιπόν. Ας ξεκινήσουμε λοιπόν.
  
-===Αλλαγή φωτεινότητας===+====Αλλαγή Αντίθεσης - Φωτεινότητας Εικόνας==== 
 + 
 +Ο υπολογιστής, αντιμετωπίζει την εικόνα ως έναν πίνακα. Μία εικόνα με τόνους του γκρίζου αποτελείται από έναν πίνακα με τιμές 0 έως 255, ενώ μία έγχρωμή εικόνα αποτελείται από τρεις τέτοιους πίνακες, έναν για κάθε ένα κανάλι (κόκκινο, πράσινο, μπλε). Η εξίσωση που χρησιμοποιείται για την αλλαγή της αντίθεσης και φωτεινότητας μίας εικόνας είναι η εξής: 
 + 
 +    Νεα_Εικόνα = Τιμή_Αντίθεσης * Αρχική_Εικόνα + Τιμή_Φωτεινότητας 
 + 
 +Συνεπώς, όπως προκύπτει από την παραπάνω εξίσωση, η αντίθεση μπορεί να μεταφραστεί σαν μία αλλαγή ΚΛΙΜΑΚΑΣ των τιμών του κάθε pixel, ενώ η φωτεινότητα σαν ΜΕΤΑΤΟΠΙΣΗ των τιμών του κάθε pixel. Προσοχή, δε μετατοπίζουμε τα pixel, αλλά τις τιμές αυτών στο εύρος 0-255. Εάν ένα pixel λάβει τιμή μικρότερη από 0, τότε για να βρίσκεται εντός του αποδεχτού εύρους θα θεωρηθεί η τιμή του 0 (μαύρο). Αντίστοιχα εάν ένα pixel πάρει τιμή μεγαλύτερη από 255, η τελική τιμή του θα ληφθεί ως 255 (λευκό). Ο πλήρης κώδικας που επιτυγχάνεται αυτή η διαδικασία παρατίθεται παρακάτω: 
 + 
 +    import os 
 +    import cv2 as cv 
 +    import numpy as np 
 +    import datetime as dt 
 +     
 +    imgFileFormats = (".jpg", ".jpeg", ".png", ".tif", ".tiff"
 +     
 +    def checkImgFileType(src: str): 
 +        typeIMG = None 
 +        for f in imgFileFormats: 
 +            if f in src: 
 +                typeIMG = f 
 +        return typeIMG 
 +     
 +    def brightnessContrastChange(src: str, contrastVal=1.0, brightnessVal=0.0, exportFolderPath=None, exportImageName=None): 
 +        print("\n\n"
 +        print(str(dt.datetime.now()) + " : Read image file at %s" % src) 
 +        img = cv.imread(src)  # Read the image file at path src 
 +     
 +        # Check if image was opened correctly 
 +        if img is None: 
 +            print(str(dt.datetime.now()) + "  : Error: Cannot read image at path %s" % src) 
 +            return False, None 
 +     
 +        newImg = np.zeros(img.shape, img.dtype)  # Create a new image to store the new values 
 +     
 +        # Do the operation newImg(i,j) = contrastVal * img(i,j) + brightnessVal 
 +        # Instead of these 'for' loops we could have used simply: 
 +        # newImg = cv.convertScaleAbs(image, alpha=contrastVal, beta=brightnessVal) 
 +        # I prefer this method, cause it shows how to access the points of the image directly. This method can be used 
 +        # if someone wants to write his own image manipulate functions 
 +        for y in range(img.shape[0]): 
 +            for x in range(img.shape[1]): 
 +                for c in range(img.shape[2]): 
 +                    newImg[y, x, c] = np.clip(contrastVal * img[y, x, c] + brightnessVal, 0, 255) 
 +     
 +        # newImg = cv.convertScaleAbs(img, alpha=contrastVal, beta=brightnessVal) # Much faster than using nested for loops 
 +     
 +        if exportFolderPath is not None:  # Check if an export path has need set 
 +            if exportImageName is None:  # Check if user has not specify a name 
 +                exportImageName = os.path.splitext(os.path.basename(src))[0]  # Take the name of original image 
 +                exportImageName = exportImageName + "_brightnessContrastChange"  # Set new name 
 +                imgTypeFormat = checkImgFileType(src) # Take original image format 
 +                if imgTypeFormat is None:  # If user hasn't specify a type then export image as JPG 
 +                    imgTypeFormat = ".jpg" 
 +            else: 
 +                imgTypeFormat = checkImgFileType(exportImageName)  # Find the input format first 
 +                exportImageName = os.path.splitext(os.path.basename(exportImageName))[0]  # Take new name 
 +                if imgTypeFormat is None:  # If user hasn't specify a type then export image as JPG 
 +                    imgTypeFormat = ".jpg" 
 +            exportAt = exportFolderPath+exportImageName+imgTypeFormat 
 +            print(str(dt.datetime.now()) + " : Write image file at %s" % exportAt) 
 +            cv.imwrite(exportAt, newImg)  # Export image 
 +     
 +        return True, newImg  # Return True for success and the newImg 
 + 
 +Επειδή είναι το πρώτο παράδειγμα, εμφανίζονται και οι βιβλιοθήκες που χρησιμοποιούνται, καθώς και οι global μεταβήτές που δημιουργήθηκαν, καθώς και οι βοηθητικές συναρτήσεις. Στα επόμενα παραδείγματα θα εμφανίζεται μόνο η συνάρτηση που εκτελεί τη διαδικασία της ενότητας. Σε περίπτωση όπου χρησιμοποιηθεί κάποια άλλη βιβλιοθήκη ή χρειαστεί να δημιουργηθεί κάποια επιμέρους συνάρτηση, τότε θα εμφανίζονται και αυτές στον κώδικα. 
 + 
 +Ας εξηγηθεί όμως, τι γίνεται παραπάνω: 
 + 
 +  - Αρχικά εισάγονται οι απαραίτητες βιβλιοθήκες. Η βιβλιοθήκη **os** εισάγεται για τη διαχείρηση των path των εικόνων, η **numpy** αποτελεί την πρότυπη βιβλιοθήκη δημιουργίας πινάκων και είναι συμβατή με την OpenCV, η **datetime** χρησιμοποιείται για να γίνει η ζωή του developer πιο εύκολη κάνοντας print διάφορα αναγνωριστικά μηνυματάκια πριν από κάθε κρίσιμη διαδικασία εμφανίζοντας και την ώρα που ξεκινάει η διαδικασία. Τέλος η βιβλιοθήκη **cv2** επεξεργάζεται τις εικόνες. 
 +  - Η συνάρτηση checkImgFileType() δημιουργήθηκε για να μπορεί το πρόγραμμα να γίνει πιο αυτοματοποιημένο. Η συνάρτηση αυτή χρησιμοποιείται για να αναγνωρίσει συγκεκριμένους τύπους αρχείων εικόνων, που υποστηρίζει η εφαρμογή. Οι υποστηριζόμενοι τύποι της εφαρμογής βρίσκονται στη global λίστα imgFileFormats κι έτσι εάν αργότερα χρειαστεί να γίνει προσθήκη κάποιου ακόμη τύπου αρχείου εικόνας, να χρειαστεί απλά να προστεθεί στη λίστα το όνομα της προέκτασης και να γραφεί μόνο το απαραίτητο τμήμα κώδικα που επεξεργάζεται εκείνο το φορματ, χωρίς να χρειάζεται να τροποποιηθεί όλο το πρόγραμμα. 
 +  - Η βασική συνάρτηση είναι η brightnessContrastChange, η οποία χρειάζεται υποχρεωτικά μόνο την εισαγωγή του path της εικόνας για να χρησιμοποιηθεί. Εάν δε δοθεί καμία άλλη μεταβλητή, τότε θα επιστραφεί η ίδια εικόνα. Εάν δοθεί μόνο η τιμή της αντίθεσης, τότε θα αλλάξει μόνο η αντίθεση της εικόνας. Αντίστοιχα εάν δοθεί μόνο η τιμή της φωτεινότητας θα αλλάξει μόνο η φωτεινότητα της εικόνας. Εάν δοθούν και οι δύο τιμές, τότε θα αλλάξει και η αντίθεση και η φωτεινότητα. Ακόμη η συνάρτηση αυτή λαμβάνει το path του φακέλου εξαγωγής του νέου αρχείου (εάν δε δοθεί δε θα αποθηκευτεί η νέα εικόνα σε κάποιο αρχείο), καθώς επίσης και το όνομα με την προέκταση. Εάν δε δοθεί κάποιο όνομα η νέα εικόνα θα αποθηκευτεί με ως ΟνομαΕικονας_brightnessContrastChange και τύπο αρχείου ίδιο με αυτό της εικόνας εισαγωγής. 
 +  - Το άνοιγμα της εικόνας πραγματοποιείται με τη συνάρτηση **cv.imread(src, flag)**. Η συνάρτηση αυτή χρειάζεται μόνο το path της εικόνας για να εκτελεστεί, όμως μπορεί να δοθεί και μία επιπλέον παράμετρος, η οποία διαβάζει την εικόνα είτε ως BGR, είτε ως BGRA, είτε ως GRAYSCALE. Σε αυτό τη σημείο χρειάζεται να αναφερθεί πως η OpenCV, αποθηκεύει το χρώμα της εικόνας σε σύστημα BGR(blue, green, red) και όχι ως RGB. Αυτό πρέπει να λαμβάνεται υπόψην όταν γράφεται κώδικας που επεξεργασίας χρωμάτων, ή όταν χρησιμοποιείται βιβλιοθήκη για επεξεργασία χρωμάτων και χρησιμοποιεί σύστημα RGB. Σε επόμενα παραδείγματα θα γίνει αναφορά και στις τιμές της μεταβλητής flag. 
 +   - Με ίδια λογική για την εξαγωγή εικόνας χρησιμοποιείται η συνάρτηση **cv.imwrite(filename, img)**. Η συνάρτηση αποθηκεύει την εικόνα img στο μονοπάτι της μεταβλητής filename. 
 +   - Για την επεξεργασία της εικόνας στο παραπάνω παράδειγμα χρησιμοποιήθηκε ένα nested for loop. Στη θέση των for loop, θα μπορούσε να χρησιμοποιηθεί απευθείας η συνάρτηση **cv.convertScaleAbs(image, alpha=contrastVal, beta=brightnessVal)** που εκτελεί ακριβώς την ίδια διαδικασία. 
 + 
 + 
 +====Φιλτράρισμα Εικόνας==== 
 + 
 +Για τη χρήση φίλτρων στην OpenCV χρησιμοποιείται η συνάρτηση cv.filter2D(src, ddepth, kernel), όπου src είναι η εικόνα (υπό μορφή πίνακα), το επιθυμητό βάθος της εικόνας εξόδου (συνιστάται η τιμή να είναι -1, το οποίο αντιστοιχεί στο ίδιο βάθος με την εικόνα εισαγωγής) και το kernel είναι ο πίνακας που αντιστοιχεί στο φίλτο. 
 + 
 +Παρακάτω παρατίθεται κώδικας για τη χρήση μερικών βασικών φίλτρων. 
 + 
 +===Φίλτρο Δέλτα=== 
 + 
 +    def deltaFiltering(src: str, exportFolderPath=None, exportImageName=None): 
 +        print("\n"
 +        print(str(dt.datetime.now()) + " : Read image file at %s" % src) 
 +        img = cv.imread(src)  # Read the image file at path src 
 +     
 +        # Check if image was opened correctly 
 +        if img is None: 
 +            print(str(dt.datetime.now()) + "  : Error: Cannot read image at path %s" % src) 
 +            return False, None 
 +     
 +        # Set the filter 
 +        kernel = np.array(([0, 0, 0], 
 +                           [0, 1, 0], 
 +                           [0, 0, 0]), np.float32) 
 +     
 +        print(str(dt.datetime.now()) + " : Image filtering:\n kerner = ") 
 +        print(kernel) 
 +        newImg = cv.filter2D(src=img, ddepth=-1, kernel=kernel) 
 +     
 +        if exportFolderPath is not None:  # Check if an export path has need set 
 +            if exportImageName is None:  # Check if user has not specify a name 
 +                exportImageName = os.path.splitext(os.path.basename(src))[0]  # Take the name of original image 
 +                exportImageName = exportImageName + "_deltaFiltering"  # Set new name 
 +                imgTypeFormat = checkImgFileType(src)  # Find the input format first 
 +                if imgTypeFormat is None:  # If user hasn't specify a type then export image as JPG 
 +                    imgTypeFormat = ".jpg" 
 +            else: 
 +                imgTypeFormat = checkImgFileType(exportImageName)  # Find the input format first 
 +                exportImageName = os.path.splitext(os.path.basename(exportImageName))[0]  # Take new name 
 +                if imgTypeFormat is None:  # If user hasn't specify a type then export image as JPG 
 +                    imgTypeFormat = ".jpg" 
 +            exportAt = exportFolderPath + exportImageName + imgTypeFormat 
 +            print(str(dt.datetime.now()) + " : Write image file at %s" % exportAt) 
 +            cv.imwrite(exportAt, newImg)  # Export image 
 +     
 +        return True, newImg  # Return True for success and the newImg 
 +     
 +===Φίλτρο Παραγώγου=== 
 +     
 +    def shiftAndSubtractFilter(src: str, topLeft=False, topMiddle=False, topRight=False, 
 +                               centerLeft=False, centerMiddle=False, centerRight=False, 
 +                               bottomLeft=False, bottomMiddle=False, bottomRight=False, 
 +                               exportFolderPath=None, exportImageName=None): 
 +        print("\n"
 +        print(str(dt.datetime.now()) + " : Read image file at %s" % src) 
 +        img = cv.imread(src)  # Read the image file at path src 
 +     
 +        # Check if image was opened correctly 
 +        if img is None: 
 +            print(str(dt.datetime.now()) + "  : Error: Cannot read image at path %s" % src) 
 +            return False, None 
 +     
 +        # Set the filter 
 +        kernel = np.array(([0, 0, 0], 
 +                           [0, 0, 0], 
 +                           [0, 0, 0]), np.float32) 
 +        if topLeft: 
 +            kernel = kernel + np.array(([-1, 0, 0], 
 +                                        [0, 1, 0], 
 +                                        [0, 0, 0]), np.float32) 
 +        if topMiddle: 
 +            kernel = kernel + np.array(([0, -1, 0], 
 +                                        [0, 1, 0], 
 +                                        [0, 0, 0]), np.float32) 
 +        if topRight: 
 +            kernel = kernel + np.array(([0, 0, -1], 
 +                                        [0, 1, 0], 
 +                                        [0, 0, 0]), np.float32) 
 +        if centerLeft: 
 +            kernel = kernel + np.array(([0, 0, 0], 
 +                                        [-1, 1, 0], 
 +                                        [0, 0, 0]), np.float32) 
 +        if centerMiddle: 
 +            kernel = kernel + np.array(([0, 0, 0], 
 +                                        [0, 1, 0], 
 +                                        [0, 0, 0]), np.float32) 
 +        if centerRight: 
 +            kernel = kernel + np.array(([0, 0, 0], 
 +                                        [0, 1, -1], 
 +                                        [0, 0, 0]), np.float32) 
 +        if bottomLeft: 
 +            kernel = kernel + np.array(([0, 0, 0], 
 +                                        [0, 1, 0], 
 +                                        [-1, 0, 0]), np.float32) 
 +        if bottomMiddle: 
 +            kernel = kernel + np.array(([0, 0, 0], 
 +                                        [0, 1, 0], 
 +                                        [0, -1, 0]), np.float32) 
 +        if bottomRight: 
 +            kernel = kernel + np.array(([0, 0, 0], 
 +                                        [0, 1, 0], 
 +                                        [0, 0, -1]), np.float32) 
 +     
 +        print(str(dt.datetime.now()) + " : Image filtering:\n kerner = ") 
 +        print(kernel) 
 +        newImg = cv.filter2D(src=img, ddepth=-1, kernel=kernel) 
 +     
 +        if exportFolderPath is not None:  # Check if an export path has need set 
 +            if exportImageName is None:  # Check if user has not specify a name 
 +                exportImageName = os.path.splitext(os.path.basename(src))[0]  # Take the name of original image 
 +                exportImageName = exportImageName + "_shiftAndSubtractFilter"  # Set new name 
 +                imgTypeFormat = checkImgFileType(src)  # Find the input format first 
 +                if imgTypeFormat is None:  # If user hasn't specify a type then export image as JPG 
 +                    imgTypeFormat = ".jpg" 
 +            else: 
 +                imgTypeFormat = checkImgFileType(exportImageName)  # Find the input format first 
 +                exportImageName = os.path.splitext(os.path.basename(exportImageName))[0]  # Take new name 
 +                if imgTypeFormat is None:  # If user hasn't specify a type then export image as JPG 
 +                    imgTypeFormat = ".jpg" 
 +            exportAt = exportFolderPath + exportImageName + imgTypeFormat 
 +            print(str(dt.datetime.now()) + " : Write image file at %s" % exportAt) 
 +            cv.imwrite(exportAt, newImg)  # Export image 
 +     
 +        return True, newImg  # Return True for success and the newImg 
 +     
 +===Ανίχνευση Ακμών=== 
 +     
 +    def edgeDetection(src: str, centerMiddle=False, exportFolderPath=None, exportImageName=None): 
 +        print("\n"
 +        print(str(dt.datetime.now()) + " : Read image file at %s" % src) 
 +        img = cv.imread(src)  # Read the image file at path src 
 +     
 +        # Check if image was opened correctly 
 +        if img is None: 
 +            print(str(dt.datetime.now()) + "  : Error: Cannot read image at path %s" % src) 
 +            return False, None 
 +     
 +        # Set the filter 
 +        kernel = np.array(([1 / 8, 1 / 8, 1 / 8], 
 +                           [1 / 8, 1, 1 / 8], 
 +                           [1 / 8, 1 / 8, 1 / 8]), np.float32) 
 +     
 +        if centerMiddle: 
 +            kernel = kernel + np.array(([0, 0, 0], 
 +                                        [0, -1, 0], 
 +                                        [0, 0, 0]), np.float32) 
 +     
 +        print(str(dt.datetime.now()) + " : Image filtering:\n kerner = ") 
 +        print(kernel) 
 +        newImg = cv.filter2D(src=img, ddepth=-1, kernel=kernel) 
 +     
 +        if exportFolderPath is not None:  # Check if an export path has need set 
 +            if exportImageName is None:  # Check if user has not specify a name 
 +                exportImageName = os.path.splitext(os.path.basename(src))[0]  # Take the name of original image 
 +                exportImageName = exportImageName + "_edgeDetection"  # Set new name 
 +                imgTypeFormat = checkImgFileType(src)  # Find the input format first 
 +                if imgTypeFormat is None:  # If user hasn't specify a type then export image as JPG 
 +                    imgTypeFormat = ".jpg" 
 +            else: 
 +                imgTypeFormat = checkImgFileType(exportImageName)  # Find the input format first 
 +                exportImageName = os.path.splitext(os.path.basename(exportImageName))[0]  # Take new name 
 +                if imgTypeFormat is None:  # If user hasn't specify a type then export image as JPG 
 +                    imgTypeFormat = ".jpg" 
 +            exportAt = exportFolderPath + exportImageName + imgTypeFormat 
 +            print(str(dt.datetime.now()) + " : Write image file at %s" % exportAt) 
 +            cv.imwrite(exportAt, newImg)  # Export image 
 +     
 +        return True, newImg  # Return True for success and the newImg 
 +     
 +===Ενίσχυση Ακμών=== 
 + 
 +    def edgeEnhancement(src: str, kappa=1, centerMiddle=False, exportFolderPath=None, exportImageName=None): 
 +        print("\n"
 +        print(str(dt.datetime.now()) + " : Read image file at %s" % src) 
 +        img = cv.imread(src)  # Read the image file at path src 
 +     
 +        # Check if image was opened correctly 
 +        if img is None: 
 +            print(str(dt.datetime.now()) + "  : Error: Cannot read image at path %s" % src) 
 +            return False, None 
 +     
 +        # Set the filter 
 +        if kappa > 8: 
 +            kappa = 8 
 +        elif kappa < -8: 
 +            kappa = -8 
 +     
 +        kernel = np.array(([-kappa / 8, -kappa / 8, -kappa / 8], 
 +                           [-kappa / 8,  kappa + 1, -kappa / 8], 
 +                           [-kappa / 8, -kappa / 8, -kappa / 8]), np.float32) 
 +     
 +        if centerMiddle: 
 +            kernel = kernel + np.array(([0,  0, 0], 
 +                                        [0, -1, 0], 
 +                                        [0,  0, 0]), np.float32) 
 +     
 +        print(str(dt.datetime.now()) + " : Image filtering:\n kerner = ") 
 +        print(kernel) 
 +        newImg = cv.filter2D(src=img, ddepth=-1, kernel=kernel) 
 +     
 +        if exportFolderPath is not None:  # Check if an export path has need set 
 +            if exportImageName is None:  # Check if user has not specify a name 
 +                exportImageName = os.path.splitext(os.path.basename(src))[0]  # Take the name of original image 
 +                exportImageName = exportImageName + "_edgeEnhancement"  # Set new name 
 +                imgTypeFormat = checkImgFileType(src)  # Find the input format first 
 +                if imgTypeFormat is None:  # If user hasn't specify a type then export image as JPG 
 +                    imgTypeFormat = ".jpg" 
 +            else: 
 +                imgTypeFormat = checkImgFileType(exportImageName)  # Find the input format first 
 +                exportImageName = os.path.splitext(os.path.basename(exportImageName))[0]  # Take new name 
 +                if imgTypeFormat is None:  # If user hasn't specify a type then export image as JPG 
 +                    imgTypeFormat = ".jpg" 
 +            exportAt = exportFolderPath + exportImageName + imgTypeFormat 
 +            print(str(dt.datetime.now()) + " : Write image file at %s" % exportAt) 
 +            cv.imwrite(exportAt, newImg)  # Export image 
 +     
 +        return True, newImg  # Return True for success and the newImg 
 + 
 + 
 +====Χρήση της OpenCV για προβολή εικόνας σε GUI==== 
 + 
 +Η OpenCV παρέχει τις δικές της εντολές για τη δημιουργία γραφικού περιβάλλοντος. Σε αυτή την ενότητα θα γίνει σύντομη περιγραφή του περιβάλλοντος αυτού. 
 + 
 +===Άνοιγμα Παραθύρου για Προβολή Εικόνας=== 
 + 
 +Για τη δημιουργία παραθύρου χρησιμοποιείται η συνάρτηση **cv.namesWindow(winname, flags)**, η οποία δέχεται σαν μεταβλητές το όνομα του παραθύρου και κάποιες ειδικές μεταβλητές (flags) - Συνιστάται η χρήση του cv.WINDOW_AUTOSIZE, η οποία δημιουργεί παράθυρο ίσο με τις διαστάσεις τις εικόνας. Εάν η εικόνα είναι μεγαλύτερη από την ανάλυση της οθόνης, η συνάρτηση δεν κάνει rescale (για αυτό συνιστάται η χρήση πυραμίδων, για προβολή μεγάλων εικόνων). 
 + 
 +Στη συνέχεια για την προβολή της εικόνας στο παράθυρο χρησιμοποιούνται η συνάρτηση **cv.imshow(winname, mat)**, η οποία δέχεται σαν μεταβλητές το όνομα του παραθύρου που θα προβάλει την εικόνα και τον πίνακα που αντιστοιχεί στην εικόνα. Ωστόσο η συνάρτηση αυτή εκτελείται ακαριαία και για αυτό χρειάζεται να δημιουργηθεί κάποιος χρονομετρητής, ο οποίος θα ελέγχει το πόση ώρα θα μείνει ανοιχτό το παράθυρο. Τη δουλειά αυτή την κάνει η συνάρτηση **cv.waitKey(ms)**. Η συνάρτηση αυτή χρησιμοποιείται επίσης και να ελεγχθεί εάν ο χρήστης πάτησε κάποιο πλήκτρο. Σαν μεταβλητή δέχεται τα milli-second που το παράθυρο θα μείνει ανοιχτό. Εάν δοθεί η τιμή 0, τότε το παράθυρο μένει ανοιχτό μέχρι να το κλείσει ο χρήστης. 
 + 
 +Αφού τερματιστεί με κάποιο τρόπο η προβολή της εικόνας, τότε πρέπει να διαγραφεί το παράθυρο από τη μνήμη (αποδέσμευση προσωρινής μνήμης). Αυτό επιτυγχάνεται με την συνάρτηση **cv.destroyAllWindows()**, η οποία διαγράφει όλα τα παράθυρα που έχουν δημιουργηθεί και για αυτό η χρήση της συνιστάται στις περιπτώσεις όπου όλη η εφαρμογή είναι ένα παράθυρο η εάν το υπάρχουν πολλά, η συνάρτηση αυτή πρέπει να καλείται μετά το κλείσιμο του κύριου παραθύρου (τερματισμός της εφαρμογής). Στην περίπτωση που χρειάζεται να κλείσει κάποιο συγκεκριμένο παράθυρο χρησιμοποιείται η συνάρτηση cv.destroyWindow(). 
 + 
 +    def openImageInWindow(src: str): 
 +        print("\n"
 +        print(str(dt.datetime.now()) + " : Read image file at %s" % src) 
 +        img = cv.imread(src)  # Read the image file at path src 
 +     
 +        # Check if image was opened correctly 
 +        if img is None: 
 +            print(str(dt.datetime.now()) + "  : Error: Cannot read image at path %s" % src) 
 +            return False 
 +     
 +        windowName = os.path.basename(src)  # Read the image name and add it to var windowName 
 +        cv.namedWindow(winname=windowName, flags=cv.WINDOW_AUTOSIZE)  # Create window 
 +        cv.imshow(winname=windowName, mat=img)  # Show the image 
 +        cv.waitKey(0)  # Without the delay the window would pop up instantly. Use 0 for infinite delay, else use milli sec. 
 +        cv.destroyAllWindows()  # If the window is the main window, use this rather than cv.destroyWindow() 
 +     
 +        return True 
 + 
 +===Χρήση Πυραμίδων για Προβολή Μεγάλων Εικόνων=== 
 + 
 +Όπως αναφέρθηκε παραπάνω όταν μία εικόνα είναι πολύ μεγάλη, για την προβολή της συνιστάται να μειωθούν αναλογικά οι διαστάσεις της, ώστε να μπορεί να προβληθεί στην οθόνη. Η σωστή προγραμματιστική λογική είναι το πρόγραμμα να λαμβάνει τις διαστάσεις της οθόνης και να εκτελεί την επαναληπτική διαδικασία μείωσης της ανάλυσης της εικόνας όσο χρειάζεται. Για λόγους απλότητας θεωρείται ότι μία εικόνα διαστάσεων μικρότερων 1024x720 χωράει σε μία μέση οθόνη. 
 + 
 +**Προσοχή:** Η διαδικασία αυτή πρέπει να γίνεται μόνο για την προβολή της εικόνας στην οθόνη. Εάν πρόκειται να γίνει περεταίρω επεξεργασία στην εικόνα αφότου κλείσει το παράθυρο (πχ προβάλεται μία εικόνα για έλεγχο), τότε καλό είναι η αρχική εικόνα να αντιγράφεται σε μία άλλη μεταβλητή και η παρακάτω διαδικασία να γίνεται στη νέα μεταβλητή. 
 + 
 +Η για τη δημιουργία πυραμίδα εικόνας χρησιμοποιείται η συνάρτηση cv.pyrDown(src, dstsize) ή cv.pyrUp(src, dstsize), για μείωση ή αύξηση επιπέδου πυραμίδας (ανάλυση εικόνας). Η αύξηση της ανάλυσης εικόνας καλό είναι να μην ξεπερνά την ανάλυση της αρχικής εικόνας. Δε μπορεί να γεννηθεί περισσότερη πληροφορία από αυτή που έχει καταγραφεί στην αρχική εικόνα. 
 +     
 +    def openImageInWindowPyramidVersion(src: str): 
 +        print("\n"
 +        print(str(dt.datetime.now()) + " : Read image file at %s" % src) 
 +        img = cv.imread(src)  # Read the image file at path src 
 +     
 +        # Check if image was opened correctly 
 +        if img is None: 
 +            print(str(dt.datetime.now()) + "  : Error: Cannot read image at path %s" % src) 
 +            return False 
 +     
 +        h, w, _channels = map(int, img.shape)  # Find the size of the image 
 +        while w > 1024 or h > 720:  # We want the image to fit the screen (this values ensures that) 
 +            img = cv.pyrDown(src=img, dstsize=(w // 2, h // 2))  # Go down a pyramid 
 +                                                                 # (there is also cv.pyrUp(src=img, dstsize=(w ** 2, h ** 2) 
 +            h, w, _channels = map(int, img.shape)  # Find the new size of the image 
 +            print("(w x h) = (", w, " x ", h, ")" # Print the new size 
 +     
 +        windowName = os.path.basename(src)  # Read the image name and add it to var windowName 
 +        cv.namedWindow(winname=windowName, flags=cv.WINDOW_AUTOSIZE)  # Create window 
 +        cv.imshow(winname=windowName, mat=img)  # Show the image 
 +        cv.waitKey(0)  # Without the delay the window would pop up instantly. Use 0 for infinite delay, else use milli sec. 
 +        cv.destroyAllWindows()  # If the window is the main window, use this rather than cv.destroyWindow() 
 +     
 +        return True 
 + 
 +===Προβολή Βίντεο=== 
 + 
 +Με αντίστοιχο γίνεται και η προβολή ενός βίντεο. Το βίντεο αποτελείται από μία σειρά εικόνων που η μία διαδέχεται την άλλη με κάποια συγκεκριμένη ταχύτητα που μετριέται σε καρέ/δευτερόλεπτο (fps). Η διαφορά με τα παραπάνω παραδείγματα είναι ότι η αρχική παράμετρος θα πρέπει να διαβάσει πρώτα το βίντεο και στη συνέχεια να δημιουργηθεί ένας επαναλληπτικός βρόγχος, ο οποίος θα δημιουργεί κάθε φορά το παράθυρο εμφανίζοντας σε αυτό ένα διαφορετικό καρέ. Αυτό συνεπάγεται ότι στην αρχή του επαναληπτικού βρόγχου θα δημιουργείται μία μεταβλητή η οποία θα αντιστοιχεί στην εικόνα του επόμενου καρέ. 
 + 
 +Για το άνοιγμα ενός βίντεο η OpenCV έχει δημιουργήσει τη συνάρτηση **cv.VideoCapture(src)**, η οποία σαν παράμετρο δέχεται την τοποθεσία του βίντεο. Η ανάγνωση κάθε καρέ πραγματοποιείται καλώντας τη συνάρτηση **read()** εντός του αντικειμένου που δημιουργήθηκε χρησιμοποιώντας τη συνάρτηση VideoCapture(). 
 +Αυτό στην πράξη μεταφράζεται ως **success, frame = videoFile.read()**. Η συνάρτηση **read()** επιστρέφει σαν πρώτη παράμετρο την επιτυχία ή αποτυχία ανάγνωσης του καρέ (για αυτό και θα πρέπει να γίνεται πάντα έλεγχος εάν διαβάστηκε το καρέ ή όχι) και σαν δέυτερη παράμετρο επιστροφής είναι το καρέ. Εάν δεν γίνει έλεγχος, τότε όταν τελειώσει το βίντεο, θα δημιουργηθούν σφάλματα, αφότου η μεταβλητή frame δεν θα έχει την πληροφορία της εικόνας, αλλά κάτι "άχρηστο"
 + 
 +==Απλή Προσπέλαση-Προβολή Βίντεο== 
 + 
 +    def openVideoInWindow(src: str): 
 +        print("\n"
 +        print(str(dt.datetime.now()) + " : Read video file at %s" % src) 
 +        videoFile = cv.VideoCapture(src)  # Read the image file at path src 
 +     
 +        # Check if video was opened correctly 
 +        if not videoFile.isOpened(): 
 +            print(str(dt.datetime.now()) + "  : Error: Cannot read video at path %s" % src) 
 +            return False 
 +     
 +        windowName = os.path.basename(src)  # Read the image name and add it to var windowName 
 +        cv.namedWindow(winname=windowName, flags=cv.WINDOW_AUTOSIZE)  # Create window 
 +     
 +        videoPlay = True 
 +        while videoPlay: 
 +            success, frame = np.array(videoFile.read()) 
 +            if not success: 
 +                break 
 +            cv.imshow(winname=windowName, mat=frame)  # Show the image 
 +            press_ESC = cv.waitKey(33)  # Wait 33ms and check if user will press ESC key 
 +            if press_ESC is 27: 
 +                break 
 +        cv.destroyAllWindows()  # If the window is the main window, use this rather than cv.destroyWindow() 
 + 
 + 
 +==Προβολή Βίντεο Με Χρήση Πυραμίδων== 
 + 
 +Εάν η ανάλυση του βίντεο είναι πολύ μεγάλη, θα δημιουργηθεί το ίδιο πρόβλημα με τις εικόνες (το παράθυρο θα είναι μεγαλύτερο από την οθόνη). Για αυτό τον 
 +λόγο συνιστάται η χρήση πυραμίδων για μείωση της ανάλυσης στα επιθυμητά όρια. 
 + 
 +    def openVideoInWindowPyramidVersion(src: str): 
 +        print("\n"
 +        print(str(dt.datetime.now()) + " : Read video file at %s" % src) 
 +        videoFile = cv.VideoCapture(src)  # Read the image file at path src 
 +     
 +        # Check if video was opened correctly 
 +        if not videoFile.isOpened(): 
 +            print(str(dt.datetime.now()) + "  : Error: Cannot read video at path %s" % src) 
 +            return False 
 +     
 +        windowName = os.path.basename(src)  # Read the image name and add it to var windowName 
 +        cv.namedWindow(winname=windowName, flags=cv.WINDOW_AUTOSIZE)  # Create window 
 +     
 +        videoPlay = True 
 +        while videoPlay: 
 +            success, frame = videoFile.read() 
 +            if not success: 
 +                break 
 +     
 +            h, w, _channels = map(int, frame.shape)  # Find the size of the image 
 +            while w > 1024 or h > 720:  # We want the image to fit the screen (this values ensures that) 
 +                frame = cv.pyrDown(src=frame, dstsize=(w // 2, h // 2))  # Go down a pyramid 
 +                # (there is also cv.pyrUp(src=img, dstsize=(w ** 2, h ** 2) 
 +                h, w, _channels = map(int, frame.shape)  # Find the new size of the image 
 +     
 +            cv.imshow(winname=windowName, mat=frame)  # Show the image 
 +            press_ESC cv.waitKey(33)  # Wait 33ms and check if user will press ESC key 
 +            if press_ESC is 27: 
 +                break 
 +        cv.destroyAllWindows()  # If the window is the main window, use this rather than cv.destroyWindow() 
 + 
opencv.1582457280.txt.gz · Τελευταία τροποποίηση: 2020/11/21 09:52 (εξωτερική τροποποίηση)