
Setelah saya perlu menganalisis informasi dari gambar dan pada output untuk memiliki jenis objek, jenisnya, dan juga, menganalisis set bingkai, saya perlu memberikan pengidentifikasi objek dan waktu yang dihabiskan dalam bingkai, perlu untuk menentukan bagaimana objek bergerak dan kamera mana yang terlihat. Mari kita mulai, mungkin, dengan dua yang pertama, analisis personil secara agregat akan dibahas di bagian selanjutnya.
Baiklah, kami akan menjelaskan secara lebih rinci tugas kami:
- Perbaiki orang dan mobil - pilih mereka di gambar dan hasilkan instance kelas yang sesuai dengan bidang yang diperlukan.
- Tentukan jumlah mobil, jika jatuh ke bingkai kamera tertentu
- Bandingkan frame saat ini dengan yang sebelumnya untuk persamaan objek, sehingga kita bisa mengetahuinya
Oke, saya pikir, dan mengambil ular yang tebal, python, artinya. Diputuskan untuk menggunakan jaringan saraf Mask R-Cnn sehubungan dengan kesederhanaan dan fitur-fiturnya modern . Juga, tentu saja, kita akan menggunakan OpenCV untuk manipulasi gambar.
Pengaturan lingkungan
Kami akan menggunakan Windows 10, karena Anda kemungkinan besar akan menggunakannya.
Dipahami bahwa Anda sudah memiliki 64 bit Python. Jika tidak, maka Anda dapat mengunduh paket, misalnya, dari sini
Instalasi Paket
git clone https://github.com/matterport/Mask_RCNN cd Mask_RCNN pip3 install -r requirements.txt python3 setup.py install
Jika karena alasan tertentu tidak dapat dikompilasi dari sumber, ada versi dari pip:
pip3 install mrcnn --user
Paket, tentu saja, dilengkapi dengan semua dependensi .
Tahap 1. Membuat pengenal sederhana.
Kami akan melakukan impor yang diperlukan
import os import cv2 import mrcnn.config import mrcnn from mrcnn.model import MaskRCNN
Jaringan saraf memerlukan pembuatan konfigurasi dengan bidang yang diganti
class MaskRCNNConfig(mrcnn.config.Config): NAME = "coco_pretrained_model_config" GPU_COUNT = 1 IMAGES_PER_GPU = 1 DETECTION_MIN_CONFIDENCE = 0.8
Tunjukkan lokasi file dengan skala. Biarkan dalam contoh ini akan berada di folder dengan file ini. Jika tidak, maka akan diunduh.
import mrcnn.utils DATASET_FILE = "mask_rcnn_coco.h5" if not os.path.exists(DATASET_FILE): mrcnn.utils.download_trained_weights(DATASET_FILE)
Mari kita buat model kita dengan pengaturan di atas
model = MaskRCNN(mode="inference", model_dir="logs", config=MaskRCNNConfig()) model.load_weights(DATASET_FILE, by_name=True)
Dan mungkin kita akan mulai memproses semua gambar di direktori images
di direktori saat ini.
IMAGE_DIR = os.path.join(os.getcwd(), "images") for filename in os.listdir(IMAGE_DIR): image = cv2.imread(os.path.join(IMAGE_DIR, filename)) rgb_image = image[:, :, ::-1] detections = model.detect([rgb_image], verbose=1)[0]
Apa yang akan kita lihat di deteksi?
print(detections)
Misalnya, sesuatu yang serupa:
{'rois': array([[ 303, 649, 542, 1176],[ 405, 2, 701, 319]]), 'class_ids': array([3, 3]), 'scores': array([0.99896, 0.99770015], dtype=float32), 'masks': array()}
Dalam hal ini, 2 objek ditemukan.
rois
- susunan koordinat sudut kiri bawah dan kanan atas
class_ids
adalah pengidentifikasi numerik dari objek yang ditemukan, sementara kita perlu tahu bahwa 1 adalah orang, 3 adalah mobil, 8 adalah truk.
scores
- sejauh model yakin dengan solusi, parameter ini dapat DETECTION_MIN_CONFIDENCE
melalui DETECTION_MIN_CONFIDENCE
dalam konfigurasi, memotong semua opsi yang tidak pantas.
masks
- kontur objek. Data digunakan untuk menggambar topeng objek. Karena mereka cukup banyak, dan tidak dimaksudkan untuk pemahaman manusia, saya tidak akan mengutip mereka dalam artikel ini.
Ok, kita bisa berhenti di situ, tetapi kita ingin melihat gambar yang memandu penggunaan jaringan saraf dengan benda-benda yang dipilih dengan indah yang biasanya diberikan?
Akan lebih mudah untuk memanggil fungsi mrcnn.visualize.display_instances
, tetapi kami tidak akan melakukan ini, kami akan menulis sendiri.
Fungsi akan mengambil gambar, dan parameter utama diperoleh dari kamus dari langkah pertama.
def visualize_detections(image, masks, boxes, class_ids, scores): import numpy as np bgr_image = image[:, :, ::-1] CLASS_NAMES = ['BG',"person", "bicycle", "car", "motorcycle", "bus", "truck"] COLORS = mrcnn.visualize.random_colors(len(CLASS_NAMES)) for i in range(boxes.shape[0]): y1, x1, y2, x2 = boxes[i] classID = class_ids[i] label = CLASS_NAMES[classID] font = cv2.FONT_HERSHEY_DUPLEX color = [int(c) for c in np.array(COLORS[classID]) * 255] text = "{}: {:.3f}".format(label, scores[i]) size = 0.8 width = 2 cv2.rectangle(bgr_image, (x1, y1), (x2, y2), color, width) cv2.putText(bgr_image, text, (x1, y1-20), font, size, color, width)

Meskipun salah satu keuntungan utama dari jaringan saraf ini adalah solusi dari tugas segmentasi Instance - memperoleh kontur objek, kami belum menggunakannya, kami akan menganalisisnya.
Untuk menerapkan topeng, tambahkan beberapa baris sebelum menggambar persegi panjang untuk setiap objek yang ditemukan.
mask = masks[:, :, i]
Hasil:

Versi dengan topeng putih Tahap II. Kesuksesan pertama. Pengakuan jumlah mobil.
Untuk pengakuan, kita membutuhkan bingkai mobil yang jelas di dekat, jadi diputuskan untuk mengambil hanya bingkai dari pos pemeriksaan, dan kemudian membandingkannya dengan kesamaan (lebih lanjut tentang itu di bab berikutnya). Metode ini, bagaimanapun, memberikan terlalu banyak ketidakakuratan, karena mesin bisa sangat mirip secara visual dan algoritma saya belum bisa menghindari situasi seperti itu.
Diputuskan untuk menggunakan lib siap pakai dari produsen Ukraina nomeroff-net (bukan iklan). Karena hampir semua kode dapat ditemukan pada contoh untuk model, maka saya tidak akan memberikan deskripsi lengkap.
Saya hanya bisa mengatakan bahwa fungsi ini dapat dimulai dengan gambar asli atau mesin yang dikenali dapat dipotong dari frame dan diteruskan ke fungsi ini.
import sys import matplotlib.image as mpimg import os sys.path.append(cfg.NOMEROFF_NET_DIR) from NomeroffNet import filters, RectDetector, TextDetector, OptionsDetector, Detector, textPostprocessing nnet = Detector(cfg.MASK_RCNN_DIR, cfg.MASK_RCNN_LOG_DIR) nnet.loadModel("latest") rectDetector = RectDetector() optionsDetector = OptionsDetector() optionsDetector.load("latest") textDetector = TextDetector.get_static_module("ru")() textDetector.load("latest") def detectCarNumber(imgPath: str) -> str: img = mpimg.imread(imgPath) NP = nnet.detect([img]) cvImgMasks = filters.cv_img_mask(NP) arrPoints = rectDetector.detect(cvImgMasks) zones = rectDetector.get_cv_zonesBGR(img, arrPoints) regionIds, stateIds, _c = optionsDetector.predict(zones) regionNames = optionsDetector.getRegionLabels(regionIds)
output textArr akan mewakili array string dengan jumlah mesin yang ditemukan pada frame, misalnya:
["293163"]
, atau [""]
, []
- jika tidak ada nomor yang cocok ditemukan.
Tahap III. Identifikasi objek berdasarkan kesamaan.
Sekarang kita perlu memahami cara memperbaiki objek sekali, untuk memahami bahwa itu adalah dia di bingkai berikutnya. Pada tahap ini, kita akan menganggap bahwa kita hanya memiliki satu kamera dan kita hanya akan membedakan antara frame yang berbeda darinya.
Untuk melakukan ini, Anda perlu mengetahui bagaimana kami akan membandingkan dua objek.
Saya akan mengusulkan algoritma pengayakan untuk tujuan ini. Kami membuat reservasi bahwa itu bukan bagian dari bagian utama OpenCV, jadi kami perlu mengirimkan modul contrib. Sayangnya, algoritma ini dipatenkan dan penggunaannya dalam program komersial terbatas. Tetapi kami fokus pada kegiatan penelitian, bukan?
pip3 install opencv-contrib-python --user
~~ Kelebihan operator == ~~ Kami menulis fungsi yang mengambil 2 objek dibandingkan dalam bentuk matriks. Sebagai contoh, kita mendapatkannya setelah memanggil fungsi cv2.open(path)
Kami akan menulis implementasi algoritma kami.
def compareImages(img1, img2) -> bool: sift = cv2.xfeatures2d.SIFT_create()
Temukan poin kunci dan deskriptor menggunakan SIFT. Mungkin saya tidak akan memberikan bantuan untuk fungsi-fungsi ini, karena Anda selalu dapat menyebutnya di shell interaktif sebagai help(somefunc)
kp1, des1 = sift.detectAndCompute(img1, None) kp2, des2 = sift.detectAndCompute(img2, None)
Siapkan algoritma kami.
FLANN_INDEX_KDTREE = 0 indexParams = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) searchParams = dict(checks=50) flann = cv2.FlannBasedMatcher(indexParams, searchParams)
Sekarang jalankan.
matches = flann.knnMatch(des1, des2, k=2)
Hitung kesamaan antar gambar.
matchesCount = 0 for m, n in matches: if m.distance < cfg.cencitivity*n.distance: matchesCount += 1 return matchesCount > cfg.MIN_MATCH_COUNT
Sekarang, cobalah untuk menggunakannya
Untuk melakukan ini, setelah mendeteksi objek, kita perlu memotongnya dari gambar asli
Saya tidak bisa menulis apa pun lebih baik daripada menyimpannya untuk memori lambat, dan kemudian membaca dari sana.
def extractObjects(objects, binaryImage, outputImageDirectory, filename=None): for item in objects: y1, x1, y2, x2 = item.coordinates
Sekarang kita memiliki objek dalam <outputImageDirectory>/objectsOn<imageFilename>
Sekarang, jika kita memiliki setidaknya 2 direktori seperti itu, maka kita dapat membandingkan objek di dalamnya. Jalankan fungsi yang ditulis sebelumnya
if compareImages(previousObjects, currentObjects): print(“ !”)
Atau kita dapat melakukan tindakan lain, seperti menandai objek-objek ini dengan pengidentifikasi yang sama.
Tentu saja, seperti semua jaringan saraf, yang satu ini cenderung memberikan hasil yang terkadang keliru.
Secara umum, kami telah menyelesaikan 3 tugas yang ditetapkan di awal, jadi kami akan menyelesaikannya. Saya ragu bahwa artikel ini membuka mata orang-orang yang telah menulis setidaknya satu program yang memecahkan masalah pengenalan gambar / segmentasi gambar, tapi saya harap saya membantu setidaknya satu pengembang pemula).
Kode sumber lengkap proyek dapat ditemukan di sini .