Αναζήτηση σχημάτων σε μια εικόνα με Python3 και OpenCV4

Η αναγνώριση προσώπων ή αντικειμένων μέσω υπολογιστή είναι μια ολοένα και διευρυνόμενη τεχνολογία με πολύ βάθος και ατελείωτες δυνατότητες και εφαρμογές. Ας αρχίσουμε όμως με τα βασικά, προσπαθώντας να ανιχνεύσουμε κάποια βασικά σχήματα σε μια στατική εικόνα.


shapes result screenshot

Πριν ξεκινήσουμε με αυτόν τον οδηγό, θα υποθέσουμε ότι έχετε ήδη εγκαταστήσει την python και μπορείτε να τρέξετε τις εντολές python3 και pip3. Θα χρειαστεί επίσης να βάλετε τo πακέτo opencv-python εκτελώντας την εντολή pip3 install opencv-python. Το αρχείο εικόνας shapes.png που χρησιμοποιήθηκε μπορείτε να το βρείτε στο τέλος του άρθρου.

Περνώντας στον κώδικα, θα δημιουργήσουμε ένα αρχείο shapes.py και θα εισάγουμε το opencv module. Κατόπιν, θα διαβάσουμε την εικόνα στην οποία θέλουμε να ανιχνεύσουμε τα διάφορα σχήματα, ως ασπρόμαυρη:

import cv2 as cv

img = cv.imread("shapes.png", cv.IMREAD_GRAYSCALE)

* Παρόλο που είμαστε στην έκδοση 4 του OpenCV εισάγουμε το module πάντα σαν cv2.

Προχωρώντας, θα πρέπει να επιλέξουμε ένα όριο (threshold) και να βρούμε τα περιγράμματα (contours), χρησιμοποιώντας τις κάτω παύλες για τις παραμέτρους που δεν μας ενδιαφέρουν:

_, threshold = cv.threshold(img, 240, 255, cv.THRESH_BINARY)
contours, _ = cv.findContours(threshold, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

Ας ορίσουμε μια λειτουργία για να εκτυπώνουμε το όνομα του εκάστοτε σχήματος στην εικόνα:

def drawText(name, coords):
  # Pass the image, text, position, font, scale, color
  cv.putText(img, name, coords, cv.FONT_HERSHEY_DUPLEX, 1, (0))

Τώρα, μπορούμε να περάσουμε στο επόμενο βήμα που είναι να υπολογίσουμε τα σημεία του κάθε σχήματος και να ζωγραφίσουμε τα περιγράμματα, καθώς και να βρούμε την θέση στην οποία θέλουμε να εμφανίζεται το κείμενο:

for cnt in contours:
  # Calculates a contour perimeter or a curve length.
  peri = cv.arcLength(cnt, True) # True for closing the curve
  # Approximates a polygonal curve(s) with the specified precision
  approx = cv.approxPolyDP(cnt, 0.01 * peri, True) # True for closing the curve

  cv.drawContours(img, [approx], 0, (0), 5) # Last two are color and thickness

  # ravel returns a contiguous flattened array.
  pos = (approx.ravel()[0], approx.ravel()[1])

Σ’ αυτό το σημείο, ελέγχουμε την ποσότητα των σημείων του σχήματος και εκτυπώνουμε ανάλογα:

  if len(approx) == 3:
    drawText("Triangle", pos)
  elif len(approx) == 4:
    # compute the aspect ratio by using the bounding box of the contour
    (x, y, w, h) = cv.boundingRect(approx)
    ar = w / float(h)
    # a square has an aspect ratio that is almost equal to one
    shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"
    drawText(shape, pos)
  elif len(approx) == 5:
    drawText("Pentagon", pos)
  elif len(approx) == 6:
    drawText("Hexagon", pos)
  elif len(approx) > 10:
    drawText("Circle", pos)

Όπως βλέπουμε η μόνη περίπτωση που χρειάζεται ένας παραπάνω υπολογισμός είναι όταν έχουμε 4 σημεία και πρέπει να καθορίσουμε αν είναι ορθογώνιο ή τετράγωνο, συγκρίνοντας τις πλευρές του.

Τέλος, θα γράψουμε την αλλαγμένη εικόνα μας σε ένα καινούργιο αρχείο:

cv.imwrite('shapes-detected.png', img)

Και αυτό ήταν! Μέσα σε λίγες γραμμές κώδικα μπορέσαμε να βρούμε τα σχήματα μιας (πολύ απλουστευμένης) εικόνας. Μπορείτε να κατεβάστε τα αρχεία εδώ: shapes.py και shapes.png και να το τρέξετε με την εντολή: python3 shapes.py.


Για περισσότερα tutorials και αναλυτικές οδηγίες, επισκεφτείτε τον επίσημη σελίδα documentation του OpenCV: https://docs.opencv.org/.

Χρησιμοποιούμε cookies & παρόμοιες τεχνολογίες

Αυτός ο ιστότοπος χρησιμοποιεί μονάδες αποθήκευσης και συλλέγει στατιστικά για την βέλτιστη εμπειρία του χρήστη.
Αν συνεχίσετε να χρησιμοποιείτε τις υπηρεσίες μας, συμφωνείτε σε αυτό.

Περισσότερα