Χρησιμοποιήστε αυτήν την τεχνική για να εφαρμόσετε μερικά έξυπνα μαθηματικά στα βίντεό σας και να μειώσετε το κούνημα.

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

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

Ρύθμιση του περιβάλλοντος σας

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

pip εγκατάσταση opencv-python numpy

Αυτή η εντολή εγκαθιστά τις βιβλιοθήκες NumPy και OpenCV.

instagram viewer
Το NumPy παρέχει εργαλεία για αριθμητικές εργασίες ενώ το OpenCV ασχολείται με εργασίες όρασης υπολογιστή.

Ο πλήρης πηγαίος κώδικας είναι διαθέσιμος σε α Αποθετήριο GitHub.

Εισαγωγή των απαιτούμενων βιβλιοθηκών και καθορισμός τριών κρίσιμων λειτουργιών

Δημιουργήστε ένα νέο αρχείο Python και δώστε του ένα όνομα της αρεσκείας σας. Εισαγάγετε βιβλιοθήκες NumPy και OpenCV στην αρχή του σεναρίου.

εισαγωγή μουδιασμένος όπως και np
εισαγωγή cv2

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

Στη συνέχεια, ορίστε τρεις λειτουργίες που θα είναι κρίσιμες για τη διαδικασία σταθεροποίησης.

Η συνάρτηση υπολογισμός_μετακίνησης_μέσου

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

defυπολογισμός_κινούμενος_μέσος όρος(καμπύλη, ακτίνα):
# Υπολογίστε τον κινητό μέσο όρο μιας καμπύλης χρησιμοποιώντας μια δεδομένη ακτίνα
Μέγεθος_παραθύρου = 2 * ακτίνα + 1
πυρήνας = np.ones (μέγεθος_παραθύρου) /μέγεθος_παραθύρου
curve_padded = np.lib.pad (καμπύλη, (ακτίνα, ακτίνα), 'άκρη')
smoothed_curve = np.convolve (curve_padded, kernel, mode='ίδιο')
smoothed_curve = εξομαλυνόμενη_καμπύλη[ακτίνα:-ακτίνα]
ΕΠΙΣΤΡΟΦΗ λειασμένη_καμπύλη

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

Η συνάρτηση smooth_trajectory

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

defλεία_τροχιά(τροχιά):
# Εξομαλύνετε την τροχιά χρησιμοποιώντας κινούμενο μέσο όρο σε κάθε διάσταση
smoothed_trajectory = np.copy (τροχιά)

Για Εγώ σε εύρος(3):
ομαλοποιημένη_τροχιά[:, i] = υπολογισμός_κινούμενος_μέσος όρος(
τροχιά[:, i],
ακτίνα=SMOOTHING_RADIUS
)

ΕΠΙΣΤΡΟΦΗ ομαλοποιημένη_τροχιά

ο λεία_τροχιά η συνάρτηση επιστρέφει μια ομαλοποιημένη τροχιά.

Η συνάρτηση fix_border

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

deffix_border(πλαίσιο):
# Διορθώστε το περίγραμμα του πλαισίου εφαρμόζοντας περιστροφή και μετασχηματισμό κλιμάκωσης
πλαίσιο_σχήμα = πλαίσιο.σχήμα

matrix = cv2.getRotationMatrix2D(
(σχήμα_πλαισίου[1] / 2, σχήμα_πλαισίου[0] / 2),
0,
1.04
)

frame = cv2.warpAffine (frame, matrix, (frame_shape[1], σχήμα_πλαισίου[0]))
ΕΠΙΣΤΡΟΦΗ πλαίσιο

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

Εκκίνηση της σταθεροποίησης βίντεο και λήψη της εισόδου

Ξεκινήστε ρυθμίζοντας την ακτίνα που θα χρησιμοποιήσει η λειτουργία εξομάλυνσης τροχιάς.

SMOOTHING_RADIUS = 50

Στη συνέχεια, περάστε στη διαδρομή βίντεο του ασταθούς βίντεο που θέλετε να σταθεροποιήσετε.

# Ανοίξτε το αρχείο εισόδου βίντεο
# Αντικαταστήστε τη διαδρομή με 0 για να χρησιμοποιήσετε την κάμερα web
cap = cv2.VideoCapture('inputvid.mp4')

Αποκτήστε τις ιδιότητες του ασταθούς βίντεο:

num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
πλάτος = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
ύψος = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)

Ορίστε τη μορφή εξόδου. Αυτή είναι η μορφή με την οποία το πρόγραμμα θα αποθηκεύσει το σταθεροποιημένο βίντεο. Μπορείτε να χρησιμοποιήσετε οποιοδήποτε κοινή μορφή βίντεο σου αρέσει.

fourcc = cv2.VideoWriter_fourcc(*'mp4v')

Τέλος, αρχικοποιήστε το πρόγραμμα εγγραφής βίντεο:

out = cv2.VideoWriter('video_out.mp4', τέσσερα cc, fps, (2 * πλάτος ύψος))

Η επέκταση του ονόματος αρχείου που μεταβιβάζετε στο πρόγραμμα εγγραφής βίντεο θα πρέπει να είναι η ίδια με αυτή που έχετε ορίσει στη μορφή εξόδου.

Πλαίσια ανάγνωσης και επεξεργασίας

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

Ξεκινήστε διαβάζοντας το πρώτο πλαίσιο.

_, prev_frame = cap.read()
prev_gray = cv2.cvtColor (prev_frame, cv2.COLOR_BGR2GRAY)

Στη συνέχεια, αρχικοποιήστε τον πίνακα μετασχηματισμού. Θα αποθηκεύσει πληροφορίες για κάθε πλαίσιο.

transforms = np.zeros((αριθμός_πλαισίων - 1, 3), np.float32)

Τέλος, πρέπει να υπολογίσετε την οπτική ροή μεταξύ διαδοχικών πλαισίων. Στη συνέχεια, υπολογίστε τον μετασχηματισμό συγγένειας μεταξύ των σημείων.

Για Εγώ σε εύρος (αριθμός_πλαισίων - 2):
# Υπολογίστε την οπτική ροή μεταξύ διαδοχικών καρέ
prev_points = cv2.goodFeaturesToTrack(
prev_grey,
maxCorners=200,
Ποιότητα Επίπεδο=0.01,
MinDistance=30,
blockSize=3
)

επιτυχία, curr_frame = cap.read()

ανδεν επιτυχία:
Διακοπή

curr_gray = cv2.cvtColor (curr_frame, cv2.COLOR_BGR2GRAY)

curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_grey,
curr_gray,
prev_points,
Κανένας
)

διεκδικώ prev_points.shape == curr_points.shape
idx = np.where (κατάσταση == 1)[0]
prev_points = prev_points[idx]
curr_points = curr_points[idx]

# Υπολογίστε τον συγγενικό μετασχηματισμό μεταξύ των σημείων
matrix, _ = cv2.estimateAffine2D(prev_points, curr_points)
μετάφραση_χ = μήτρα[0, 2]
μετάφραση_υ = μήτρα[1, 2]
rotation_angle = np.arctan2(matrix[1, 0], μήτρα[0, 0])
μετασχηματισμοί[i] = [translation_x, translation_y, rotation_angle]
prev_gray = curr_gray

Ο βρόχος επαναλαμβάνεται σε κάθε πλαίσιο (εκτός από το τελευταίο πλαίσιο) για τον υπολογισμό των μετασχηματισμών. Υπολογίζει την οπτική ροή μεταξύ διαδοχικών καρέ χρησιμοποιώντας τη μέθοδο Lucas-Kanade. cv2.goodFeaturesToTrack ανιχνεύει σημεία χαρακτηριστικών στο προηγούμενο πλαίσιο prev_grey. Επειτα, cv2.calcOpticalFlowPyrLK παρακολουθεί αυτά τα σημεία στο τρέχον πλαίσιο curr_gray.

Μόνο τα σημεία με κατάσταση 1 (που υποδηλώνει επιτυχή παρακολούθηση) βοηθούν στην εκτίμηση ενός πίνακα μετασχηματισμού συγγενών. Ο κώδικας ενημερώνει το prev_grey μεταβλητή με το τρέχον πλαίσιο κλίμακας του γκρι για την επόμενη επανάληψη.

Εξομάλυνση της τροχιάς

Πρέπει να εξομαλύνετε την τροχιά που προκύπτει από τους μετασχηματισμούς για να επιτύχετε ένα σταθερό αποτέλεσμα.

# Υπολογίστε την τροχιά αθροίζοντας τους μετασχηματισμούς
τροχιά = np.cumsum (μετασχηματίζεται, άξονας=0)

# Εξομαλύνετε την τροχιά χρησιμοποιώντας κινούμενο μέσο όρο
smoothed_trajectory = λεία_τροχιά (τροχιά)

# Υπολογίστε τη διαφορά μεταξύ της ομαλοποιημένης και της αρχικής τροχιάς
διαφορά = ομαλοποιημένη_τροχιά - τροχιά

# Προσθέστε τη διαφορά πίσω στους αρχικούς μετασχηματισμούς για να αποκτήσετε ομαλές
# μεταμορφώσεις
transforms_smooth = μετασχηματισμοί + διαφορά

Ο παραπάνω κωδικός υπολογίζει την τροχιά της κίνησης της κάμερας και την εξομαλύνει.

Πλαίσια σταθεροποίησης και γραφής

Το τελευταίο βήμα είναι να σταθεροποιήσετε τα καρέ και να γράψετε το σταθεροποιημένο βίντεο σε ένα αρχείο εξόδου.

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

cap.set (cv2.CAP_PROP_POS_FRAMES, 0)

Στη συνέχεια, σταθεροποιήστε το βίντεο επεξεργάζοντας κάθε καρέ.

# Επεξεργαστείτε κάθε καρέ και σταθεροποιήστε το βίντεο
Για Εγώ σε εύρος (αριθμός_πλαισίων - 2):
επιτυχία, πλαίσιο = cap.read()

ανδεν επιτυχία:
Διακοπή

translation_x = transforms_smooth[i, 0]
translation_y = μετασχηματίζει_ομαλός[i, 1]
περιστροφή_γωνία = μετασχηματισμοί_ομαλός[i, 2]

# Δημιουργήστε τη μήτρα μετασχηματισμού για σταθεροποίηση
transformation_matrix = np.zeros((2, 3), np.float32)
μήτρα_μετασχηματισμού[0, 0] = np.cos (γωνία_περιστροφής)
μήτρα_μετασχηματισμού[0, 1] = -np.sin (περιστροφή_γωνία)
μήτρα_μετασχηματισμού[1, 0] = np.sin (γωνία_περιστροφής)
μήτρα_μετασχηματισμού[1, 1] = np.cos (γωνία_περιστροφής)
μήτρα_μετασχηματισμού[0, 2] = μετάφραση_χ
μήτρα_μετασχηματισμού[1, 2] = μετάφραση_υ

# Εφαρμόστε τη μεταμόρφωση για να σταθεροποιήσετε το πλαίσιο
frame_stabilized = cv2.warpAffine(
πλαίσιο,
transformation_matrix,
(πλάτος ύψος)
)

# Στερεώστε το περίγραμμα του σταθεροποιημένου πλαισίου
frame_stabilized = fix_border (frame_stabilized)

# Συνδέστε το αρχικό και το σταθεροποιημένο πλαίσιο δίπλα-δίπλα
frame_out = cv2.hconcat([frame, frame_stabilized])

# Αλλάξτε το μέγεθος του πλαισίου εάν το πλάτος του υπερβαίνει τα 1920 pixel
αν frame_out.shape[1] > 1920:
frame_out = cv2.resize(
πλαίσιο_έξω,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)

# Εμφάνιση των καρέ πριν και μετά
cv2.imshow("Πριν και μετά", frame_out)
cv2.waitKey(10)

# Γράψτε το πλαίσιο στο αρχείο βίντεο εξόδου
out.write (frame_out)

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

Αποδέσμευση του Video Capture and Writer

Ολοκληρώστε το πρόγραμμα απελευθερώνοντας τα αντικείμενα λήψης βίντεο και εγγραφής.

# Απελευθερώστε τη λήψη και το πρόγραμμα εγγραφής βίντεο και κλείστε τυχόν ανοιχτά παράθυρα
cap.release()
out.release()
cv2.destroyAllWindows()

Αυτός ο κωδικός κλείνει επίσης τυχόν ανοιχτά παράθυρα.

Τελική έξοδος προγράμματος

Η έξοδος του προγράμματος θα μοιάζει κάπως έτσι:

Και εδώ είναι ένα παράδειγμα του σταθεροποιημένου βίντεο:

Η έξοδος δείχνει τη σύγκριση μεταξύ του ασταθούς βίντεο και του σταθεροποιημένου.

Εξερευνήστε τις δυνατότητες OpenCV

Μπορείτε να εφαρμόσετε το OpenCV σε πολλά πεδία που αφορούν την όραση υπολογιστή. Αυτό συμβαίνει γιατί προσφέρει ένα ευρύ φάσμα λειτουργιών. Θα πρέπει να εξερευνήσετε τις δυνατότητές του δουλεύοντας σε περισσότερα έργα που περιλαμβάνουν όραση υπολογιστή. Αυτό θα σας εισάγει σε νέες έννοιες και θα σας δώσει νέους τομείς για έρευνα.