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

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


opencv

Βλέπετε μια παλαιότερη έκδοση της σελίδας!


Μια μικρή εισαγωγή στην OpenCV ξεκινάει πάντα από ένα νέο λήμμα σε γουίκι… τον σύγχρονο τρόπο να μοιράζεσαι γνώση.

Όσοι οι πιστοί προσέλθετε :-)

Εισαγωγή στην OpenCV

Τι είναι η OpenCV

Η OpenCV(Open-source Computer Vision) είναι μία βιβλιοθήκη που περιέχει συναρτήσεις, οι οποίες στοχεύουν στη δημιουργία εφαρμογών όρασης υπολογιστών σε πραγματικό χρόνο. Αρχικά αναπτύχθηκε από την Intel, αλλά στη συνέχεια υποστηρήχθηκε από την Willow Garage. Η βιβλιοθήκη μπορεί να χρησιμοποιηθεί σε όλα τα λειτουργικά συστήματα (Windows, Linux, Mac) και μπορεί να χρησιμοποιηθεί δωρεάν, έχοντας άδεια τύπου BSD.

Επίσης η OpenCV υποστηρίζει συστήματα Deep Learning, όπως είναι το TensorFlow, Torch/Pytorch και Caffe.

Βασικές εφαρμογές της OpenCV

Όπως και με κάθε άλλη γλώσσα προγραμματισμού, έτσι και με τις βιβλιοθήκες, η διαδικασία εκμάθησης πρέπει να ακολουθεί κάποια στάδια. Το κλασικό Hello World που μαθαίνει κανείς σε μία γλώσσα προγραμματισμού, στην OpenCV θεωρείται η διαδικασία Ανοίγματος Εκόνας - Μικρή Επεξεργασία - Εξαγωγή Εικόνας. Όλα τα παραδείγματα της ενότητας αυτής, θα ακολουθήσουν αυτή τη δομή. Η επεξεργασία μπορεί να είναι από την αλλαγή φωτεινότητας της εικόνας, μέχρι την επεξεργασία της εικόνας χρησιμοποιώντας κάποιο φίλτρο.

Ας ξεκινήσουμε λοιπόν.

Αλλαγή Αντίθεσης - Φωτεινότητας Εικόνας

Ο υπολογιστής, αντιμετωπίζει την εικόνα ως έναν πίνακα. Μία εικόνα με τόνους του γκρίζου αποτελείται από έναν πίνακα με τιμές 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(image, alpha=contrastVal, beta=brightnessVal)
  
      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 μεταβήτές που δημιουργήθηκαν, καθώς και οι βοηθητικές συναρτήσεις. Στα επόμενα παραδείγματα θα εμφανίζεται μόνο η συνάρτηση που εκτελεί τη διαδικασία της ενότητας. Σε περίπτωση όπου χρησιμοποιηθεί κάποια άλλη βιβλιοθήκη ή χρειαστεί να δημιουργηθεί κάποια επιμέρους συνάρτηση, τότε θα εμφανίζονται και αυτές στον κώδικα.

Ας εξηγηθεί όμως, τι γίνεται παραπάνω:

  1. Αρχικά εισάγονται οι απαραίτητες βιβλιοθήκες. Η βιβλιοθήκη os εισάγεται για τη διαχείρηση των path των εικόνων, η numpy αποτελεί την πρότυπη βιβλιοθήκη δημιουργίας πινάκων και είναι συμβατή με την OpenCV, η datetime χρησιμοποιείται για να γίνει η ζωή του developer πιο εύκολη κάνοντας print διάφορα αναγνωριστικά μηνυματάκια πριν από κάθε κρίσιμη διαδικασία εμφανίζοντας και την ώρα που ξεκινάει η διαδικασία. Τέλος η βιβλιοθήκη cv2 επεξεργάζεται τις εικόνες.
  2. Η συνάρτηση checkImgFileType() δημιουργήθηκε για να μπορεί το πρόγραμμα να γίνει πιο αυτοματοποιημένο. Η συνάρτηση αυτή χρησιμοποιείται για να αναγνωρίσει συγκεκριμένους τύπους αρχείων εικόνων, που υποστηρίζει η εφαρμογή. Οι υποστηριζόμενοι τύποι της εφαρμογής βρίσκονται στη global λίστα imgFileFormats κι έτσι εάν αργότερα χρειαστεί να γίνει προσθήκη κάποιου ακόμη τύπου αρχείου εικόνας, να χρειαστεί απλά να προστεθεί στη λίστα το όνομα της προέκτασης και να γραφεί μόνο το απαραίτητο τμήμα κώδικα που επεξεργάζεται εκείνο το φορματ, χωρίς να χρειάζεται να τροποποιηθεί όλο το πρόγραμμα.
  3. Η βασική συνάρτηση είναι η brightnessContrastChange, η οποία χρειάζεται υποχρεωτικά μόνο την εισαγωγή του path της εικόνας για να χρησιμοποιηθεί. Εάν δε δοθεί καμία άλλη μεταβλητή, τότε θα επιστραφεί η ίδια εικόνα. Εάν δοθεί μόνο η τιμή της αντίθεσης, τότε θα αλλάξει μόνο η αντίθεση της εικόνας. Αντίστοιχα εάν δοθεί μόνο η τιμή της φωτεινότητας θα αλλάξει μόνο η φωτεινότητα της εικόνας. Εάν δοθούν και οι δύο τιμές, τότε θα αλλάξει και η αντίθεση και η φωτεινότητα. Ακόμη η συνάρτηση αυτή λαμβάνει το path του φακέλου εξαγωγής του νέου αρχείου (εάν δε δοθεί δε θα αποθηκευτεί η νέα εικόνα σε κάποιο αρχείο), καθώς επίσης και το όνομα με την προέκταση. Εάν δε δοθεί κάποιο όνομα η νέα εικόνα θα αποθηκευτεί με ως ΟνομαΕικονας_brightnessContrastChange και τύπο αρχείου ίδιο με αυτό της εικόνας εισαγωγής.
  4. Το άνοιγμα της εικόνας πραγματοποιείται με τη συνάρτηση cv.imread(src, flag). Η συνάρτηση αυτή χρειάζεται μόνο το path της εικόνας για να εκτελεστεί, όμως μπορεί να δοθεί και μία επιπλέον παράμετρος, η οποία διαβάζει την εικόνα είτε ως BGR, είτε ως BGRA, είτε ως GRAYSCALE. Σε αυτό τη σημείο χρειάζεται να αναφερθεί πως η OpenCV, αποθηκεύει το χρώμα της εικόνας σε σύστημα BGR(blue, green, red) και όχι ως RGB. Αυτό πρέπει να λαμβάνεται υπόψην όταν γράφεται κώδικας που επεξεργασίας χρωμάτων, ή όταν χρησιμοποιείται βιβλιοθήκη για επεξεργασία χρωμάτων και χρησιμοποιεί σύστημα RGB. Σε επόμενα παραδείγματα θα γίνει αναφορά και στις τιμές της μεταβλητής flag.
  5. Με ίδια λογική για την εξαγωγή εικόνας χρησιμοποιείται η συνάρτηση cv.imwrite(filename, img). Η συνάρτηση αποθηκεύει την εικόνα img στο μονοπάτι της μεταβλητής filename.
  6. Για την επεξεργασία της εικόνας στο παραπάνω παράδειγμα χρησιμοποιήθηκε ένα nested for loop. Στη θέση των for loop, θα μπορούσε να χρησιμοποιηθεί απευθείας η συνάρτηση cv.convertScaleAbs(image, alpha=contrastVal, beta=brightnessVal) που εκτελεί ακριβώς την ίδια διαδικασία.
opencv.1582464767.txt.gz · Τελευταία τροποποίηση: 2020/11/21 09:52 (εξωτερική τροποποίηση)