Αναζήτηση σχημάτων σε μια εικόνα με Python3 και OpenCV4
Η αναγνώριση προσώπων ή αντικειμένων μέσω υπολογιστή είναι μια ολοένα και διευρυνόμενη τεχνολογία με πολύ βάθος και ατελείωτες δυνατότητες και εφαρμογές. Ας αρχίσουμε όμως με τα βασικά, προσπαθώντας να ανιχνεύσουμε κάποια βασικά σχήματα σε μια στατική εικόνα.
Πριν ξεκινήσουμε με αυτόν τον οδηγό, θα υποθέσουμε ότι έχετε ήδη εγκαταστήσει την 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/.