پیاده‌سازی سیستم تشخیص و ردیابی خودرو در پایتون — راهنمای جامع

۹۷۱ بازدید
آخرین به‌روزرسانی: ۲۱ تیر ۱۴۰۲
زمان مطالعه: ۱۳ دقیقه
پیاده‌سازی سیستم تشخیص و ردیابی خودرو در پایتون — راهنمای جامع

در مبحث سیستم‌های «رانندگی خودران» (Autonomous Driving)، مدل «تشخیص و ردیابی خودرو» (Vehicle Detection and Tracking) یکی از مهم‌ترین بخش‌های مورد نیاز برای پیاده‌سازی چنین سیستم‌هایی است. یک سیستم تشخیص و ردیابی خودرو باید به اندازه‌ای سریع و دقیق باشد که بتوان از آن برای کاربردهای جهان واقعی نظیر «کنترل و مدیریت ترافیک» (Traffic Control and Management)، کنترل «اتومبیل‌های خودران» (Autonomous Automobiles) و سایر موارد استفاده کرد. در مرحله بعد، لازم است سیستم مکملی برای «ردگیری» (Tracking) خودروها به صورت «بلادرنگ» (Real-Time) طراحی شود تا اتومبیل بتواند بدون برخورد با دیگر خودروهای موجود در جاده، به مسیر خود ادامه دهد.

در این مطلب، هدف پیاده‌سازی یک سیستم تشخیص و ردیابی خودرو با استفاده از روش‌های «بینایی کامپیوتر» (Computer Vision) است. در سیستم پیاده‌سازی شده، از تکنیک‌های «پردازش تصویر» (Image Processing) نظیر «هیستوگرام گرادیان‌های جهت‌دار» (Histogram of Oriented Gradients)، برای استخراج ویژگی از تصاویر لحظه به لحظه ویدئویی و از مدل‌های «یادگیری ماشین» (Machine Learning)، جهت «دسته‌بندی باینری» (Binary Classification) اشیاء تشخیص داده شده به دو کلاس (Cars) و (Non-Cars) استفاده می‌شود. برای درک بهتر نحوه عملکرد سیستم تشخیص و ردیابی خودرو، به شکل زیر دقت کنید. این شکل نمایی از چگونگی تشخیص اشیاء و دسته‌بندی آن‌ها به دو کلاس (Cars) و (Non-Cars)، در یک سیستم تشخیص و ردیابی خودرو را نشان می‌دهد.

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)
تشخیص اشیاء و دسته‌بندی آن‌ها در یک سیستم تشخیص و ردیابی خودرو

بخش‌های مختلف یک سیستم تشخیص و ردیابی خودرو

در این مطلب کاربردی، از روش‌های بینایی ماشین و پردازش تصویر برای پیاده‌سازی بخش‌های مختلف سیستم تشخیص و ردیابی خودرو استفاده می‌شود. البته، تکنیک‌های پیچیده‌تر و پیشرفته‌تری نسبت به روش ارائه شده در این مطلب، جهت تشخیص و ردیابی خودرو وجود دارد (نظیر روش‌های «یادگیری عمیق» (Deep Learning)). مزیت مهم استفاده از روش‌های بینایی ماشین برای تشخیص و ردیابی خودرو، پیاده‌سازی سر راست و مرحله به مرحله بخش‌های مختلف و تحلیل آن‌ها، جهت درک بهتر نحوه عملکرد سیستم است.

به دلیل اینکه روش‌های پیشرفته‌تر نظیر یادگیری عمیق، بر پایه «شبکه‌های عصبی مصنوعی» (Artificial Neural Network) بنا نهاده شده‌اند، مانند «جعبه سیاه» عمل می‌کنند. در این دسته از روش‌ها، درک فرایند تبدیل ورودی‌ها (تصاویر) به خروجی‌های نهایی (خودروهای تشخیص داده شده در تصویر) و مراحل مختلف طی شده برای رسیدن به این جواب‌ها، برای کاربران بسیار سخت است.

برای پیاده‌سازی بخش‌های مختلف سیستم تشخیص و ردیابی خودرو، مراحل زیر طی خواهند شد. لازم به ذکر است که کلیه مراحل زیر، در زبان برنامه‌نویسی پایتون پیاده‌سازی شده‌اند و کدهای لازم در انتهای هر بخش قرار داده شده است.

  • تحلیل داده‌های استفاده شده برای تشخیص و ردیابی خودرو
  • استفاده از روش «استخراج ویژگی» (Feature Extraction) هیستوگرام گرادیان‌های جهت‌دار برای پیدا کردن بهترین ویژگی‌ها جهت تشخیص و ردیابی خودرو
  • آموزش یک مدل یادگیری و دسته‌بندی «ماشین بردار پشتیبان» (Support Vector Machine)
  • پیاده‌سازی یک «پنجره لغزان» (Sliding-Window) در سیستم تشخیص و ردیابی خودرو  و استفاده از ماشین بردار پشتیبان آموزش دیده، برای جستجو خودرو در تصاویر و دسته‌بندی اشیاء موجود در پنجره به دو کلاس (Cars) و (Non-Cars)
  • تولید مدل «نقشه حرارت» (Heatmap) در سیستم تشخیص و ردیابی خودرو جهت شناسایی و نشانه‌گذاری خودروهای شناسایی شده در تصاویر
  • استفاده از روش‌های «هموارسازی» (Smoothing) تصاویر برای بهتر کردن نتایج خروجی و از بین بردن «مثبت‌های غلط» (False Positives) در ویدئوها (منظور از مثبت‌های غلط، تصاویری هستند که اشیاء موجود در آن‌ها به اشتباه در کلاس (Cars) دسته‌بندی شده‌اند، درحالی که باید در کلاس (Non-Cars) دسته‌بندی شوند)

تحلیل داده‌ها

به تصویر زیر دقت کنید. به نظر شما کدام یک از تصاویر نمایش داده شده، خودرو را نمایش می‌دهد؟ بدون شک، پاسخ به چنین سؤالی برای کاربران انسانی راحت خواهد بود و آن‌ها قادر خواهند بود با دقت بسیار بالا، خودروهای موجود در تصاویر را تشخیص دهند. ولی، یک سیستم تشخیص و ردیابی خودرو، باید برای انجام چنین کاری «آموزش» (Training) ببیند.

به عبارت دیگر، یک سیستم تشخیص و ردیابی خودرو باید یاد بگیرد داده‌های تصویری حاوی خودرو را از دیگر داده‌های تصویر تشخیص دهد و از همه مهم‌تر، خودروهای شناسایی شده را نشانه‌گذاری و در مسیر حرکتی ردیابی کند. بهترین راه آموزش یک سیستم تشخیص و ردیابی خودرو، استفاده از حجم زیادی از داده‌های تصویری برچسب‌گذاری شده با برچسب کلاسی (Cars) و (Non-Cars) و مدل‌سازی یک «دسته‌بند» (Classifier) تصویر، بر اساس تصاویر برچسب‌گذاری شده است.

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)
نمونه‌ای از تصاویر استفاده شده از کلاس‌های مختلف برای آموزش مدل دسته‌بند

تصاویری که قرار است برای آموزش یک مدل تشخیص و ردیابی خودرو استفاده شود، باید از تصاویر و فایل‌های ویدئویی جهان واقعی استخراج شده باشند. در مرحله بعد لازم است تا تصاویری که حاوی خودرو هستند توسط برچسب‌های کلاسی مناسب، برچسب‌گذاری شوند. برای آموزش مدل تشخیص و ردیابی خودرو، از یک مجموعه داده حاوی 8792 تصویر برچسب‌گذاری شده با برچسب کلاسی (Cars) و 8968 تصویر برچسب‌گذاری شده با برچسب کلاسی (Non-Cars) استفاده شده است. تصاویر برچسب‌گذاری شده با برچسب کلاسی (Cars) از طریق لینک [+] و تصاویر  برچسب‌گذاری شده با برچسب کلاسی (Non-Cars) از طریق لینک [+] قابل بارگیری هستند.

Vehicle train images count: 8792
Non-vehicle train image count: 8968

در مرحله بعد، تصاویر کلاس‌های (Cars) و (Non-Cars) به ساختار داده‌های آرایه‌ای قابل تعریف توسط بسته نرم‌افزاری numpy تبدیل و در قالب «لیست‌های» (Lists) جداگانه‌ای ذخیره می‌شوند. برای چنین کاری در سیستم تشخیص و ردیابی خودرو، از تابع زیر استفاده می‌شود:

1def get_dataset(rootdir):
2    images = []
3    for subdir, dirs, files in os.walk(rootdir):
4        for file in files:
5            if '.DS_Store' not in file:
6                images.append(os.path.join(subdir, file))
7                
8    return list(map(lambda img: cv2.cvtColor(cv2.imread(img), cv2.COLOR_BGR2RGB), images))

نمونه‌ای از تصاویر موجود در کلاس‌های (Cars) و (Non-Cars) در شکل زیر نمایش داده شده است. «کمیت» (Quantity) و «کیفیت» (Quality) بهینه تصاویر استفاده شده برای آموزش مدل دسته‌بند، جهت تضمین عملکرد مناسب سیستم تشخیص و ردیابی خودرو بسیار حیاتی است. تصاویر کم و بی‌کیفیت، سبب تولید پیش‌بینی‌های نادرست می‌شوند.

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)
نمونه‌ای از تصاویر استفاده شده برای آموزش مدل دسته‌بند در این سیستم

استخراج ویژگی از تصاویر

در سیستم پیاده‌سازی شده برای تشخیص و ردیابی خودرو، از روش‌های استخراج ویژگی مختلفی برای انتخاب بهترین ویژگی‌ها (جهت آموزش مدل دسته‌بند تصاویر) استفاده شده است. روش‌های استخراج ویژگی استفاده شده در سیستم تشخیص و ردیابی خودرو، عملکرد بهینه سیستم را در تشخیص خودروها تضمین می‌کنند.

روش هیستوگرام‌های رنگ

ساده‌ترین روش برای استخراج ویژگی از تصاویر، استخراج ویژگی از «کانال‌های رنگ» (Color Channels) تصاویر است. بنابراین، برای استخراج ویژگی کافی است تا هیستوگرام کانال‌های رنگ یک تصویر ترسیم و داده‌های مرتبط با ویژگی‌های تصویر، از «دسته‌‌های» (Bins) هیستوگرام استخراج شوند. دسته‌های هیستوگرام، اطلاعات مفیدی در رابطه با تصویر نمایش می‌دهند و به استخراج ویژگی‌های خوب از تصاویر کمک می‌کنند.

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

روش Spatial Binning برای استخراج ویژگی از تصاویر

استفاده از سه «کانال رنگی» (Color Channels) موجود در «تصاویر با وضوح کامل» (Full Resolution Images)، بار محاسباتی زیادی را به سیستم تشخیص و ردیابی خودرو تحمیل می‌کند. با استفاده از روش Spatial Binning، می‌‌توان از یک سو، اطلاعات کافی جهت تشخیص و ردیابی خودرو را در تصاویر حفظ کرد و از سوی دیگر، بار محاسباتی سیستم را به طور قابل ملاحظه‌ای کاهش داد.

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

همان طور که در تصویر بالا مشاهده می‌شود، حتی زمانی که دقت پیکسلی تصاویر به (32x32) کاهش می‌یابد، خودرو به خوبی در تصاویر قابل شناسایی است. این بدین معنی است که ویژگی‌های مرتبط با خودرو، هنوز در تصویر حفظ شده‌اند. برای کاهش دقت تصاویر در زبان برنامه‌نویسی پایتون، می‌توان از بسته نرم‌افزاری OpenCV و تابع ()cv2.resize استفاده کرد. همچنین، در صورتی که کاربر تمایل داشته باشد تا تصاویر جدید تولید شده (تصاویری که دقت آن‌ها کاهش پیدا کرده است) را به «بردار ویژگی یک‌بعدی» (One Dimensional Feature Vector) تبدیل کند، کافی است از تابع ()ravel در بسته numpy استفاده شود.

روش هیستوگرام گرادیان‌های جهت‌دار برای استخراج ویژگی از تصاویر

یک «توصیف‌گر ویژگی» (Feature Descriptor)، نمایشی از یک تصویر یا مجموعه‌ای از تصاویر است که از طریق استخراج اطلاعات مفید و دور انداختن اطلاعات غیر اصلی، آن تصویر یا مجموعه تصاویر را ساده‌سازی می‌کند. روش هیستوگرام گرادیان‌های جهت‌دار، یک توصیف‌گر ویژگی است که در بینایی ماشین و پردازش تصویر جهت «تشخیص اشیاء» (Object Detection) استفاده می‌شود.

روش هیستوگرام گرادیان‌های جهت‌دار، قلب تپنده سیستم پیاده‌سازی شده برای تشخیص و ردیابی خودرو است. با استفاده از این روش، اطلاعات بامعنا و مفید از تصویر استخراج می‌شود. روش هیستوگرام گرادیان‌های جهت‌دار، سعی می‌کند تا «جنبه عمومی» (General Aspects) خودروها را در تصویر شناسایی کند و نه «جزئیات خاص» آن‌ها را. روش کار هیستوگرام گرادیان‌های جهت‌دار به این صورت است که ابتدا، تصویر بخش‌بندی می‌شود. سپس، در هر بخش، گرادیان (شیب) تغییرات در هر کدام از «جهت‌های» (Orientations) داده شده محاسبه می‌شود. در منابع مختلف علمی، از HOG به عنوان عبارت مخفف برای معرفی هیستوگرام گرادیان‌های جهت‌دار استفاده می‌شود.

در توصیف‌گر HOG، توزیع (هیستوگرام) جهت گرادیان‌ها (یا همان گرادیان‌های جهت‌دار) به عنوان ویژگی استفاده می‌شود. از آنجایی که اندازه گرادیان‌های (مشتق بر مبنای X و Y) اطراف «لبه‌ها» (Edges) و «گوشه‌های» (Corners) تصویر بزرگ هستند و گوشه‌ها و لبه‌ها، اطلاعات به مراتب بیشتری در مورد شکل اشیاء در تصویر در اختیار قرار می‌دهند، در نتیجه، گرادیان‌ها، اطلاعات بسیار مفیدی در رابطه با یک تصویر به سیستم تشخیص و ردیابی خودرو ارائه می‌کنند.

از طریق توابع و قطعه کدهای زیر، ویژگی‌های مفید موجود در تصویر با استفاده از روش‌های معرفی شده استخراج می‌شوند.

1class Parameters():
2    color_space='RGB'
3    spatial_size=(32, 32)
4    hist_bins=8
5    orient=9
6    pix_per_cell=8
7    cell_per_block=2
8    hog_channel=0
9    hist_range = (0, 256)
10    spatial_feat=True
11    hist_feat=True
12    hog_feat=True
13    def __init__(self, color_space='RGB', spatial_size=(32, 32),
14                 hist_bins=8, orient=9, 
15                 pix_per_cell=8, cell_per_block=2, hog_channel=0, scale = 1.5,hist_range = (0, 256),
16                 spatial_feat=True, hist_feat=True, hog_feat=True):
17        # HOG parameters
18        self.color_space = color_space
19        self.spatial_size = spatial_size
20        self.hist_bins = hist_bins
21        self.orient = orient
22        self.pix_per_cell = pix_per_cell
23        self.cell_per_block = cell_per_block
24        self.hog_channel = hog_channel
25        self.scale = scale
26        self.spatial_feat = spatial_feat
27        self.hist_feat = hist_feat
28        self.hog_feat = hog_feat
29        self.hist_range = hist_range
30
31def extract_features(img, params):
32        file_features = []
33        # Read in each one by one
34        # apply color conversion if other than 'RGB'
35        feature_image = convert_image(img, params.color_space)    
36
37        if params.spatial_feat == True:
38            spatial_features = bin_spatial(feature_image, size=params.spatial_size)
39            file_features.append(spatial_features)
40        if params.hist_feat == True:
41            # Apply color_hist()
42            hist_features = color_hist(feature_image, nbins=params.hist_bins)
43            file_features.append(hist_features)
44        if params.hog_feat == True:
45        # Call get_hog_features() with vis=False, feature_vec=True
46            if params.hog_channel == 'ALL':
47                hog_features = []
48                for channel in range(feature_image.shape[2]):
49                    hog_features.append(get_hog_features(feature_image[:,:,channel], 
50                                        params.orient, params.pix_per_cell, params.cell_per_block, 
51                                        vis=False, feature_vec=True))
52                hog_features = np.ravel(hog_features)        
53            else:
54                hog_features = get_hog_features(feature_image[:,:,params.hog_channel], params.orient, 
55                            params.pix_per_cell, params.cell_per_block, vis=False, feature_vec=True)
56            # Append the new feature vector to the features list
57            file_features.append(hog_features)
58            
59        # Return list of feature vectors
60        return np.concatenate(file_features)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

در مرحله بعد لازم است تا پارامتر‌های مناسب برای آموزش مدل‌دسته‌بند انتخاب شوند. انتخاب پارامترهای مناسب، نقش مهمی در پیش‌بینی درست برچسب کلاسی تصاویر خواهد داشت. در این جا و با استفاده از قطعه کد زیر، کلاسی به نام parameters تعریف و تمامی پارامترهای مدل دسته‌بندی تصویر مقداردهی می‌شوند:

1Parameters(
2        color_space = 'YCrCb',
3        spatial_size = (16, 16),
4        orient = 8,
5        pix_per_cell = 8,
6        cell_per_block = 2,
7        hog_channel = 'ALL',
8        hist_bins = 32,
9        scale = 1.5,
10        spatial_feat=True, 
11        hist_feat=True, 
12        hog_feat=True
13)

کیفیت فرایند استخراج ویژگی، ارتباط مستقیمی با پارامترهای انتخاب شده برای مدل دارد. پارامترهای نمایش داده شده در جدول زیر، از طریق «آزمون و خطا» (Trial) به دست آمده‌اند. برای انتخاب این مقادیر، عملکرد سیستم با ترکیب‌های مختلفی از مقادیر پارامترها، تست و در نهایت، بهترین ترکیب از مقادیر پارامترها، برای استخراج ویژگی از تصاویر انتخاب شده‌اند.

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)
تست عملکرد سیستم با ترکیب‌های مختلفی از مقادیر پارامترها و انتخاب بهترین ترکیب
تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)
تاثیر پارامتر تعداد پیکسل‌ها در هر سلول بر ویژگی‌های HOG تولید شده
تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)
تاثیر پارامتر تعداد جهت‌ها بر ویژگی‌های HOG تولید شده
1vehicle = image1
2non_vehicle = image2
3
4car_spatial_features = extract_features(vehicle, params)
5notcar_spatial_features = extract_features(non_vehicle, params)
6plt.figure()
7plt.subplot(121)
8plt.plot((car_spatial_features))
9plt.xlabel("Car Spatial Features",fontsize=15)
10
11plt.subplot(122)
12plt.plot(notcar_spatial_features)
13plt.xlabel("Non-Car Spatial Features",fontsize=15)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

1def show_hog(vehicle, non_vehicle, params):
2    _,vehicle_hog = get_hog_features(vehicle[:,:,0],params.orient, params.pix_per_cell, params.cell_per_block, vis=True, feature_vec=True)
3    _,non_vehicle_hog = get_hog_features(non_vehicle[:,:,0],params.orient, params.pix_per_cell, params.cell_per_block, vis=True, feature_vec=True)
4    f, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize=(20,10))
5    ax1.set_title('Vehicle')
6    ax1.imshow(vehicle, cmap='gray')
7    ax2.set_title('Vehicle hog')
8    ax2.imshow(vehicle_hog, cmap='gray')
9    ax3.set_title('Non-vehicle')
10    ax3.imshow(non_vehicle, cmap='gray')
11    ax4.set_title('Non-vehicle hog')
12    ax4.imshow(non_vehicle_hog, cmap='gray')

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

آموزش مدل دسته‌بند تصویر در سیستم تشخیص و ردیابی خودرو

مدل‌های ماشین بردار پشتیبان، مجموعه‌ای از روش‌های «یادگیری نظارت شده» (Supervised Learning) در حوزه‌های «هوش مصنوعی» (Artificial Intelligence) و یادگیری ماشین هستند. از ماشین‌های بردار پشتیبان، برای «دسته‌بندی» (Classification)، «رگرسیون» (Regression) و «تشخیص داده‌های پرت» (Outliers Detection) استفاده می‌شود.

در این مطلب، از مدل دسته‌بندی ماشین بردار پشتیبان با «کرنل خطی» (Linear Kernel) به عنوان دست‌بند تصاویر استفاده شده است. در این مدل، هدف پیدا کردن یک «ابر صفحه» (Hyperplane) بهینه است که می‌تواند به بهترین شکل ممکن، داده‌های مسئله را به دو کلاس (در این حالت، دو کلاس Cars و Non-Cars) دسته‌بندی کند.

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)
ماشین بردار پشتیبان

مدل ماشین بردار پشتیبان با کرنل خطی، توسط تابع LinearSVC در بسته SciKit-Learn پیاده‌سازی می‌شود. از قطعه کد زیر، برای آموزش مدل دسته‌بند استفاده می‌شود.

1sample_size = 8750
2cars = vehicles[0:sample_size]
3notcars = non_vehicles[0:sample_size]
4car_features = list(map(lambda img: extract_features(img, params), cars))
5notcar_features = list(map(lambda img: extract_features(img, params), notcars))
6X = np.vstack((car_features, notcar_features)).astype(np.float64)                        
7# Fit a per-column scaler
8X_scaler = StandardScaler().fit(X)
9# Apply the scaler to X
10scaled_X = X_scaler.transform(X)
11# Define the labels vector
12y = np.hstack((np.ones(len(car_features)), np.zeros(len(notcar_features))))
13# Split up data into randomized training and test sets
14rand_state = np.random.randint(0, 100)
15X_train, X_test, y_train, y_test = train_test_split(
16    scaled_X, y, test_size=0.2, random_state=rand_state)
17print('Using:',params.orient,'orientations',params.pix_per_cell,
18    'pixels per cell and', params.cell_per_block,'cells per block')
19print('Feature vector length:', len(X_train[0]))
20# Use a linear SVC 
21svc = LinearSVC()
22# Check the training time for the SVC
23t=time.time()
24svc.fit(X_train, y_train)
25t2 = time.time()
26print(round(t2-t, 2), 'Seconds to train SVC...')
27# Check the score of the SVC
28print('Test Accuracy of SVC = ', round(svc.score(X_test, y_test), 4))

برای آموزش مدل دسته‌بند، تصاویر کلاس‌های Cars و Non-Cars وارد سیستم تشخیص و ردیابی خودرو می‌شوند. سپس، با استفاده از روش‌های استخراج ویژگی شرح داده شده، ویژگی‌های موجود در تصاویر استخراج می‌شوند. برای تقسیم‌بندی داده‌ها به دو دسته «داده‌های آموزشی» (Training Data) و «داده‌های تست» (Test Data)، از تابع train_test_split در بسته SciKit-Learn استفاده می‌شود. پس از آموزش مدل دسته‌بندی با استفاده از داده‌های آموزشی و تست مدل آموزش دیده با استفاده از داده‌های تست، نتایج زیر به عنوان عملکرد سیستم روی داده‌های تست به ثبت رسیده است:

Using: 8 orientations 8 pixels per cell and 2 cells per block
Feature vector length: 5568
3.04 Seconds to train SVC...
Test Accuracy of SVC = 0.9911

دسته‌بندی فریم‌های تصویری با استفاده از پنجره لغزان

تا اینجای کار، سیستم تشخیص و ردیابی خودرو قادر است تصاویر با دقت پیکسلی (64x64) را دریافت و برچسب کلاسی (Cars یا Non-Cars) آن‌ها را پیش‌بینی کند. برای اینکه بتوان کلیه اشیاء موجود در تصاویر واقعی با دقت پیکسلی (720x1280) را دسته‌بندی کرد، از مفهومی به نام پنجره لغزان استفاده می‌شود.

در حوزه بینایی ماشین، پنجره لغزان یک ناحیه مستطیلی شکل، با عرض و طول ثابت است که در راستای یک تصویر حرکت می‌کند. روش کار در پنجره‌های لغزان بدین صورت است که معمولا قسمتی از تصویر که در داخل این پنجره قرار دارد، استخراج می‌شود. سپس، تصویر استخراج شده به مدل دسته‌بند تصویر وارد می‌شود تا مشخص شود که آیا در تصویر مربوطه، خودرو وجود دارد یا نه.

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

همان طور که در تصاویر بالا مشهود است، پس از اینکه تعدادی تصویر تست وارد سیستم تشخیص و ردیابی خودرو می‌شوند، پنجره لغزان روی هر تصویر حرکت می‌کند. قسمتی از تصویر که داخل پنجره قرار دارد، وارد مدل دسته‌بندی می‌شود. در صورتی که مدل دسته‌بندی تصاویر، برچسب کلاسی Cars را به یک تصویر اختصاص دهد، برای نشان‌گذاری تصاویر حاوی خودرو، دور تصویر مربوطه یک ناحیه مستطیلی قرار می‌گیرد. این ناحیه، یک خودروی تشخیص داده شده را در تصویر نشان می‌دهد. همان‌طور که در تصاویر بالا مشخص است، برای هر کدام از خودروهای تشخیص داده شده، تعدادی ناحیه هم‌پوشان تعریف شده است. همچنین، در یکی از تصاویر، به اشتباه در وسط جاده یک خودرو تشخیص داده شده است («مثبت غلط» (False Positive)).

در این مطلب، برای ترکیب نواحی هم‌پوشان و حذف نواحی مثبت غلط، از مدلی به نام «نقشه حرارت» (Heat Map) و یک مقدار «حد آستانه» (Threshold) استفاده می‌شود. با استفاده از قطعه کد زیر، مدل نقشه حرارت و حد آستانه تعریف می‌شوند.

1def add_heat(heatmap, bbox_list):
2    # Iterate through list of bboxes
3    for box in bbox_list:
4        # Add += 1 for all pixels inside each bbox
5        # Assuming each "box" takes the form ((x1, y1), (x2, y2))
6        heatmap[box[0][1]:box[1][1], box[0][0]:box[1][0]] += 1
7    # Return updated heatmap
8    return heatmap# Iterate through list of bboxes
9    
10def apply_threshold(heatmap, threshold):
11    # Zero out pixels below the threshold
12    heatmap[heatmap <= threshold] = 0
13    # Return thresholded map
14    return heatmap
15    
16    
17def heat_threshold(img, threshold, svc, X_scaler, windows_list, params):
18    heat = np.zeros_like(img[:,:,0]).astype(np.float)
19    # Add heat to each box in box list
20    heat = add_heat(heat,windows_list)
21    # Apply threshold to help remove false positives
22    heat = apply_threshold(heat,threshold)
23    # Visualize the heatmap when displaying    
24    heatmap = np.clip(heat, 0, 255)
25    # Find final boxes from heatmap using label function
26    labels = label(heatmap)
27    draw_img = draw_labeled_bboxes(np.copy(img), labels)
28    
29    return draw_img, heatmap

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

اگر به تصاویر بالا دقت کنید، نواحی هم‌پوشان به خوبی با یکدیگر ترکیب نشده‌اند و ناحیه مستطیلی، خودرو را به طور کامل پوشش نمی‌دهد. برای تشخیص بهتر خودرو در تصاویر، از روش «زیرنمونه‌گیری هیستوگرام گرادیان‌های جهت‌دار» (HOG Sub-Sampling) استفاده می‌شود. این روش، عملکرد بهتری در تولید پنجره لغزان و حرکت دادن آن در تصویر ارائه می‌دهد.

در این روش، ویژگی‌های HOG تنها یکبار استخراج می‌شوند ولی می‌توانند به دفعات مختلف زیرنمونه‌گیری شوند تا پنجره کاملی شکل بگیرد. به عبارت دیگر، در این روش پنجره‌های جستجوی مختلفی در تصویر اصلی تشکیل و در نهایت با یکدیگر ترکیب می‌شوند تا نواحی تشخیص خودرو به خوبی مشخص شوند. از قطعه کد زیر، برای پیدا کردن خودروها با استفاده از روش زیرنمونه‌گیری هیستوگرام گرادیان‌های جهت‌دار استفاده می‌شود.

1def find_cars_hog_sub(img, ystart, ystop, svc, scaler, params, cells_per_step = 1):
2    draw_img = np.copy(img)
3    cspace = params.color_space
4    
5    img_tosearch = img[ystart:ystop,:,:]
6    if cspace != 'RGB':
7        if cspace == 'HSV':
8            ctrans_tosearch = cv2.cvtColor(img_tosearch, cv2.COLOR_RGB2HSV)
9        elif cspace == 'LUV':
10            ctrans_tosearch = cv2.cvtColor(img_tosearch, cv2.COLOR_RGB2LUV)
11        elif cspace == 'HLS':
12            ctrans_tosearch = cv2.cvtColor(img_tosearch, cv2.COLOR_RGB2HLS)
13        elif cspace == 'YUV':
14            ctrans_tosearch = cv2.cvtColor(img_tosearch, cv2.COLOR_RGB2YUV)
15        elif cspace == 'YCrCb':
16            ctrans_tosearch = cv2.cvtColor(img_tosearch, cv2.COLOR_RGB2YCrCb)
17    else: ctrans_tosearch = np.copy(img_tosearch)  
18    
19    if params.scale != 1:
20        imshape = ctrans_tosearch.shape
21        ctrans_tosearch = cv2.resize(ctrans_tosearch, (np.int(imshape[1]/params.scale), np.int(imshape[0]/params.scale)))
22        
23    ch1 = ctrans_tosearch[:,:,0]
24    ch2 = ctrans_tosearch[:,:,1]
25    ch3 = ctrans_tosearch[:,:,2]
26    # Define blocks and steps as above
27    nxblocks = (ch1.shape[1] // params.pix_per_cell) - params.cell_per_block + 1
28    nyblocks = (ch1.shape[0] // params.pix_per_cell) - params.cell_per_block + 1 
29    nfeat_per_block = params.orient*params.cell_per_block**2
30    
31    # 64 was the orginal sampling rate, with 8 cells and 8 pix per cell
32    window = 64
33    nblocks_per_window = (window // params.pix_per_cell) - params.cell_per_block + 1
34    nxsteps = (nxblocks - nblocks_per_window) // cells_per_step
35    nysteps = (nyblocks - nblocks_per_window) // cells_per_step
36    
37    # Compute individual channel HOG features for the entire image
38    hog1 = get_hog_features(ch1, params.orient, params.pix_per_cell, params.cell_per_block, feature_vec=False)
39    hog2 = get_hog_features(ch2, params.orient, params.pix_per_cell, params.cell_per_block, feature_vec=False)
40    hog3 = get_hog_features(ch3, params.orient, params.pix_per_cell, params.cell_per_block, feature_vec=False)
41    car_windows = []
42    for xb in range(nxsteps):
43        for yb in range(nysteps):
44            ypos = yb*cells_per_step
45            xpos = xb*cells_per_step
46            # Extract HOG for this patch
47            hog_feat1 = hog1[ypos:ypos+nblocks_per_window, xpos:xpos+nblocks_per_window].ravel() 
48            hog_feat2 = hog2[ypos:ypos+nblocks_per_window, xpos:xpos+nblocks_per_window].ravel() 
49            hog_feat3 = hog3[ypos:ypos+nblocks_per_window, xpos:xpos+nblocks_per_window].ravel() 
50            hog_features = np.hstack((hog_feat1, hog_feat2, hog_feat3))
51            xleft = xpos*params.pix_per_cell
52            ytop = ypos*params.pix_per_cell
53            # Extract the image patch
54            subimg = cv2.resize(ctrans_tosearch[ytop:ytop+window, xleft:xleft+window], (64,64))
55          
56            # Get color features
57            spatial_features = bin_spatial(subimg, size=params.spatial_size)
58            hist_features = color_hist(subimg, nbins=params.hist_bins, bins_range=params.hist_range)
59            # Scale features and make a prediction
60            test_features = X_scaler.transform(np.hstack((spatial_features, hist_features, hog_features)).reshape(1, -1))    
61            test_prediction = svc.predict(test_features)
62            
63            if test_prediction == 1:
64                xbox_left = np.int(xleft*params.scale )
65                ytop_draw = np.int(ytop*params.scale )
66                win_draw = np.int(window*params.scale )
67                cv2.rectangle(draw_img,(xbox_left, ytop_draw+ystart),(xbox_left+win_draw,ytop_draw+win_draw+ystart),(0,0,255),6) 
68                car_windows.append(((xbox_left, ytop_draw+ystart),(xbox_left+win_draw,ytop_draw+win_draw+ystart)))
69                
70    return car_windows

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

تشخیص و ردیابی خودرو (Vehicle Detection and Tracking)

پیاده‌سازی سیستم تشخیص و ردیابی خودرو و تولید ویدئوی نهایی

در نهایت، هر کدام از تصاویر یا «فریم‌های» (Frames) موجود در ویدئو، از طریق سیستم تشخیص و ردیابی خودرو پردازش می‌شوند تا محل قرارگیری خودروها در تصاویر مشخص شود. سپس، فریم‌های پردازش شده با هم ترکیب می‌شوند تا ویدئوی نهایی شکل بگیرد.

از قطعه کد زیر، برای پردازش نهایی ویدئوها در سیستم تشخیص و ردیابی خودرو استفاده می‌شود.

1def pipeline(img):
2    ystart = 350
3    ystop = 656
4    threshold = 1
5    car_windows = find_cars_hog_sub(img, ystart, ystop, svc, X_scaler, params)
6    draw_img, heat_map = heat_threshold(img, threshold, svc, X_scaler, car_windows, params)
7    
8    return draw_img

در پایان کار، برای تشخیص مسیر حرکت خودرو، از قطعه کد زیر استفاده می‌شود:

1from advanced_lane_helper_functions import *
2nx = 9
3ny = 6
4objpoints = []
5imgpoints = []
6objp = np.zeros((9*6,3), np.float32)
7objp[:,:2] = np.mgrid[0:9,0:6].T.reshape(-1,2)
8
9#Finding in mtx, dst
10img = cv2.imread('camera_cal/calibration2.jpg')
11
12# Convert to grayscale
13gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
14
15# Find the chessboard corners
16ret, corners = cv2.findChessboardCorners(gray, (nx, ny), None)
17
18# If found, draw corners
19if ret == True:
20    imgpoints.append(corners)
21    objpoints.append(objp)
22
23    # Draw and display the corners
24    cv2.drawChessboardCorners(img, (nx, ny), corners, ret)
25
26ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
27# Define a class to receive the characteristics of each line detection
28class Lane():
29    def __init__(self):
30        self.last_left = None
31        self.last_right = None
32        self.left_fit = None
33        self.right_fit = None
34        self.counter = 0
35        self.reset_counter = 0
36def pipeline_advanced(img, lane, show_values=False):
37    warped_img, left_fit, right_fit, M = find_lanes(img, mtx, dist, lane)
38    left_curvature, right_curvature, center = radius_curvature(warped_img, left_fit, right_fit)
39    
40    return draw_on_image(img, warped_img, left_fit, right_fit, M, left_curvature, right_curvature, center, show_values)
41lane = Lane()
42def process_image_advanced(img):
43    return pipeline_advanced(img, lane)
44
45white_output_advanced = 'output_video/project_video_advanced.mp4'
46clip1 = VideoFileClip("output_video/project_video.mp4")
47white_clip = clip1.fl_image(process_image_advanced)
48%time white_clip.write_videofile(white_output_advanced, audio=False)

برای بارگیری کامل کدها، فایل‌ها و کلاس‌های تعریف شده برای پیاده‌سازی سیستم تشخیص و ردیابی خودرو، به لینک [+] مراجعه کنید. فایل ویدئو نهایی حاصل از اجرای سیستم تشخیص و ردیابی خودرو در ادامه آمده است.

اگر نوشته بالا برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

^^

بر اساس رای ۱۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
Chatbots LifeMedium
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *