هک خودرو؛ چطوری با پردازش تصویر خودرومونو هوشمند کنیم؟

در حال حاضر بیش از 20 میلیون خودرو در جاده های ایران وجود داره و این تعداد در جهان بیش از یک میلیارد هست. آماری که باعث میشه امنیت یکپارچه، بخشی جداناپذیر از وسایل نقلیه بسیاری از تولیدکنندگان خودرو باشه و بسیاری از قوانین و استانداردها برای امنیت وسایل نقلیه وجود داشته باشه. با این حال هک خودرو عمری به اندازه 15 سال داره؛ تغییر مدیریت موتور و تزریق سوخت، ارسال سیگنال های مخفی برای واحدهای کنترل الکترونیکی (Electronic Control Units یا ECUs) خودرو یا ارسال ترافیک جعلی برای سیستم مسیریابی آنلاین و تغییر مسیر خودرو در این سال ها اتفاق افتاده. جالبه بدونید به صورت غیر رسمی گروه هایی ادعای دسترسی غیرمجاز به سیستم ایمنی خودروها یا ارتباط از راه دور با خودروهای متصل رو داشتند.از طرف دیگه، در سال های اخیر هوش مصنوعی با ورود به دنیای وسایل نقلیه، نمونه های موفقی از خودروهای خودران هوشمند رو به دنیا معرفی کرده. با مستقر شدن تعداد کافی از این خودروهای خودران، جان میلیون ها انسان از خطر مرگ حفظ میشه و به شکل چشم گیری سرعت گذر جهان به انرژی های پاک بیشتر خواهد شد.خودروی خودران شرکت Waymo (زیر مجموعه هلدینگ آلفابت) با بهره گیری از تجارب خودرو خودران گوگلدر این پست قصد داریم با رویکرد آموزشی و مرحله به مرحله، سیستمی طراحی کنیم که پس از دریافت تصاویر دوربین تعبیه شده در جلوی خودرو و پردازش این تصاویر، تغییر مسیر ناگهانی راننده بر اثر خستگی یا خطای انسانی رو تشخیص داده و از طریق علائم جلو داشبورد داخل خودرو به راننده اخطار بده.برای پیاده سازی این سیستم، از یک طرف تصاویر دوربین رو به لپ تاپ ارسال کرده و از طرف دیگه فرمان های کنترلی برای هشدار به راننده رو به سامانه مالتی پلکس خودرو ارسال میکنیم؛ یعنی تصاویر به صورت بلادرنگ (Real-time) پردازش شده و در صورت تغییر مسیر ناگهانی، فرمان هشدار به راننده داده میشه. از اونجاییکه برای ایجاد این سیستم و دسترسی به سیستم شبکه خودرو نیازمند کمی قهرمان بازی هستیم، توصیه میشه اگر دنبال دردسر نیستید این کار رو روی خودرو خودتون امتحان نکنید? .در این ماجراجویی، خودرو "رانا" رو انتخاب کردیم. خودرویی که بر پایه پلتفرم 206 صندوق دار و با کمی تغییر در ظاهر و چراغ های جلو و عقب ساخته شده. البته با نگاهی فنی تر به این خودرو، متوجه میشید که از تمامی تولیدات خودروساز، وسیله و قطعه ای در این خودرو وجود داره. خودروی مورد آزمایش؛ هدف ایجاد یک سیستم هشدار برای مواقعی هست که خودرو از مسیر اصلی یا از باند جاده ای که در حال حرکت هست خارج میشه.در بخش اول سعی میکنیم تصاویر گرفته شده از جلوی خودرو رو پردازش کرده و مسیر حرکت اصلی خودرو رو تشخیص بدیم و در بخش دوم با هک خودرو و متصل شدن به شبکه الکترونیکی داخل خودرو، فرمان های کنترلی لازم برای هشدار به راننده رو ارسال میکنیم.پردازش تصاویر دریافتیزمانیکه ما رانندگی می کنیم، با کمک چشمامون خطوط جاده رو به عنوان یک مرجع ثابت برای تصمیم گیری ها و هدایت خودرو در نظر می گیریم. این اولین چیزیه که در طراحی خودروهای خودران توسط الگوریتم های مختلف پیاده سازی می شه. در اینجا ما تصویری مشابه تصویر سمت راست رو دریافت کرده و با الگوریتم های پردازش تصویر، مسیر (لاین) ی که در حال حرکت در اون هستیم - مشابه تصویر سمت چپ - رو مشخص میکنیم. در این پست از ویدیو هایی که در هنگام رانندگی از جاده ها در روز و شب از داخل ماشین ضبط کردیم، استفاده میکنیم. این تصاویر به علت سرعت بالای خودرو، مناسب نبودن مکان دوربین و نور و محیط واقعی دارای نویز بسیار بالایی هستند.نمونه خروجی سیستم برای تصاویر واقعی گرفته شده از رانندگی که در آنها نور محیطی و نویز مشهود است؛ سمت راست تصاویر ورودی و سمت چپ تصاویر پردازش شده برای تشخیص لاین فعلی در حال رانندگی برای روز (بالا) و شب (پایین) طیف خاکستری و حذف نویزدر این پست برای پردازش تصاویر از OpenCV فریم ورک بینایی کامپیوتر - پردازش تصویر و زبان ++C استفاده خواهیم کرد. در اولین گام بخش بالا و پایین تصاویر که اطلاعات مهمی از جاده رو شامل نمیشند، حذف میکنیم. چون بیشتر الگوریتم ها از تفاوت تغییر رنگ (یا همان نور یا تاثیر گذاری یک شی در بخشی از تصویر و در اینجا خط کشی جاده) استفاده می کنند، در همین مرحله تصویر رو به طیف خاکستری تبدیل می کنیم؛ یعنی مقدار هر پیکسل در سه کانال رنگی تصویر (قرمز، سبز و آبی یا RGB) ورودی رو به یک مقدار بین 0 تا 255 تبدیل میکنیم. https://gist.github.com/hkhojasteh/259cd19c83e9bb58eb29fb6848841a56 تبدیل تصویر رنگی ورودی دریافت شده از دوربین به تصویر طیف خاکستری و حذف بالا و پایین در تصویر روز (راست) و شب (چپ)یافتن خطوط خط کشی و جداسازیقبل از تشخیص لبه ها، به روشنی باید چیزی که در تصویر به دنبال اون هستیم رو مشخص کنیم. خط کشی جاده ها همیشه سفید یا زرد هستند. با نگاه بیشتر به تصاویر گرفته شده، یک روش ساده برای جداسازی خطوط خط کشی سفید، استخراج پیکسل هایی است که مقدار بیشتری نسبت به بقیه پیکسل های مجاور یا درون تصویر دارند. بنابراین نقاطی رو انتخاب می کنیم که مقداری کمی بیشتر از چارک بالای مقدار همه پیکسل های تصویر دارند.در ادامه چون رنگ زرد به آسانی قابل جداسازی در یک تصویر سه کاناله RGB نیست و ممکنه این مقادیر در حالت برداشت مقدار بر حسب چارک حذف بشند، فرمت نمایش تصویر رو به Hue, Saturation, Value یا HSV تبدبل میکنیم و نقاط نظیر با رنگ های زرد تصویر HSV رو در تصویر طیف خاکستری به عنوان نقاط مورد نظر استخراج می کنیم (برای یافتن طیف های رنگی می تونید از فتوشاپ یا این ابزار آنلاین استفاده کنید). نهایتا مجموع نقاط انتخاب شده سفید و زرد با اعمال یک فیلتر حذف نویز با میانگین گیری از پیکسل های همسایه، برای تحلیل های بعدی استفاده می شند. https://gist.github.com/hkhojasteh/dbd36d5f806dbd7c31626c1718dff2f5 استخراج پیکسل های مورد نیاز برای شناسایی خط کشی های جاده در تصاویر روز (راست) و شب (چپ)تشخیص لبه های خطوطخُب، بعد از اینکه خطوط اصلی رو در تصویر حفظ کردیم و مقادیر دیگر رو حذف کردیم، باید لبه های اصلی خط کشی ها رو تشخیص بدیم. برای اینکار ابتدا باید به این سوال پاسخ بدیم:از نظر ریاضی در یک تصویر (یک ماتریس از مقادیر داده رنگی)، چه چیزی لبه رو تعریف می کنه؟با نگاهی دقیق تر به داده های اطراف یک لبه، می تونیم به این نتیجه برسیم که لبه ها بخش هایی هستند که مقادیر پیکسل ها به سرعت تغییر می کنند. بنابراین تشخیص لبه، یافتن پیکسل هایی ای که در مقایسه با همسایه هاشون مقادیری به شدت متفاوت دارند.نمونه تشخیص خط کشی با استفاده از گرادیان تغییر مقادیر پیکسل ها برای یک لبهخوشبختانه در حوزه پردازش تصویر، این مسئله قبلا حل شده است. الگوریتم آشکارساز لبه Canny به همین روش و با یافتن مقادیر گرادیان در یک آستانه مشخص در طول تصویر اینکار رو انجام میده. بنابراین نیازی نیست که به مقادیر رنگ تصاویر فکر کنیم، تنها تغییرات مقدار برای ما اهمیت داره و می تونیم با این الگوریتم لبه ها رو در تصاویر مرحله قبل پیدا کنیم. https://gist.github.com/hkhojasteh/27da434736e4f4a26610edf1f1e4a791 نمونه خروجی برای الگوریتم آشکارساز لبه برای خط کشی های جاده در تصاویر روز (راست) و شب (چپ)تشخیص خطوط مسیرتا به اینجای کار، پیکسل هایی که لبه های خطوط رو نشون میدند، مشخص کردیم. حالا باید با اتصال این پیکسل ها به هم خطوط مشخص کننده مسیر رو تشخیص بدیم. مثل مرحله قبل این مسئله هم با یک تئوری ریاضی قابل حل هست. بیایید دوباره نگاهی به لبه های یافته شده بیاندازیم:لبه یافته شده در یک ناحیه مشخص شده (سبز)؛ خطوط کاندید برای لبه با رنگ آبی در تصویر مشخص شده است.با نگاه نزدیک به لبه ها، مشخصه که بهترین خطی که یک لبه رو نمایش میده، خطی است که بیشترین تعداد پیکسل از لبه رو هم شامل میشه (خط ب در تصویر بالا). یافتن این خط یک مسئله دشوار هست. چرا که ممکنه تعداد این خطوط خیلی زیاد باشه و نیاز هست تا تمام خط های ممکن بررسی بشند.برای این منظور می تونیم از تبدیل هاف استفاده کنیم. در این تبدیل، ما تمام پیکسل های لبه رو به یک فرم نمایش ریاضی دیگه تبدیل میکنیم. بعد از تبدیل کامل، هر پیکسل در "فضای تصویر" به یک خط یا منحنی در "فضای هاف" تبدیل می شه؛ یعنی در فضای هاف هر خط به شکل یک نقطه در تصویر نمایش داده میشه. نمایشی از فضای تصویر و فضای هاف متناظر به همراه پارامترها (منبع)بنابراین ما نیازی به حل مسئله یافتن خطی که از همه پیکسل های همسایه عبور کنه نداریم و تنها کافی است خطی رو پیدا کنیم که در فضای هاف هست و نهایتا این خط رو به فضای تصویر نگاشت کنیم. https://gist.github.com/hkhojasteh/a0f4e97a4d8c8d78eb936d87b78f8d17 خطوط یافت شده (زرد) با استفاده از پیکسل های لبه بعد از نگاشت از فضای هاف به فضای تصویر و قرار گرفته بر روی تصاویر اصلیگروه بندی و تصمیم گیریدر مرحله آخر پردازش تصاویر، هدف ایجاد یک معیار برای تصمیم گیری است. اگر تا اینجا همه چیز درست پیاده سازی شده باشه، خطوطی خواهیم داشت که نماینده ای از خط کشی جاده برای مسیری هستند که در حال عبور از اون هستیم. ابتدا این خطوط رو به دو دسته خط کشی سمت راست و چپ تقسیم می کنیم. یک تفاوت آشکار بین دو گروه از خط ها، جهت شیب این خطوط است. اندازه شیب هر خط زاویه رو اندازه می گیره. خطوط افقی شیب صفر و خطوط عمودی شیب بینهایت دارند. پس شیب خط های یافته شده اندازه ای بین این دو مقدار دارند، چراکه اون ها از پایین تصویر به سمت مرکز، نسبت به افق زاویه دارند.جهت شیب یک خط نشون میده که با حرکت از چپ به راست، آیا خط به بالا متمایل است یا پایین؟ خطوط با شیب منفی به سمت پایین و خطوط با شیب مثبت به بالا حرکت می کنند. این همان چیزی است که در سیستم مختصات عادی اتفاق می افته. در سیستم مختصاتی که ما از اون استفاده می کنیم، نقطه مرکز در گوشه بالا سمت چپ تصویر هست؛ یعنی در اینجا جهت شیب ما معکوس خواهد بود.پس خط های سمت راست شیب مثبت دارند و به پایین حرکت می کنند. مشاهدات نشون میدند که خطوطی که شیب خیلی کمی دارند احتمالا خطوط خوبی برای یافتن خط تصمیم گیری نیستند. بنابراین سعی می کنیم از این بین خطوطی که شیبی بیشتر/کمتر از 0.4 (+/-) دارند رو انتخاب کنیم. https://gist.github.com/hkhojasteh/ce2a6d5ea72d2480143a8c2bc8ab4f8f نتیجه نهایی پردازش تصویر برای یافتن خط تصمیم گیری میزان انحراف خودرو از جاده (خط چین) در شب (بالا) و روز (پایین)خط تصمیم گیری که نماینده ای از انحراف خودرو از مسیر در حال حرکت هست، میانگینی از دو گروه است. برای این خط، مقدار میانگین بیشترین و کمترین x از هر گروه، مشخص کننده مقدار x خواهد بود.آخرین مرحله در اینجا دریافت تصاویر از دوربین هست. کافیه تا هر فریم (Frame) از ویدیو به صورت جداگانه دریافت شده و تمام مراحل بالا برای اون تکرار بشه. البته در مورد ویدیو میشه با دقت بیشتری اشیا مختلف رو دنبال کرد یا هر فریم رو در بازه زمان و نسبت به بقیه فریم ها در نظر گرفت که در اینجا به علت طولانی شدن مطلب به اون نمی پردازیم. اگر علاقمندید که این تصاویر رو از طریق شبکه بین موبایل و لپ تاپ دریافت کنید هم می تونید این کدها رو بررسی کنید. https://gist.github.com/hkhojasteh/e1f7ed72a62a5b91876bbfb33c2d31f5 ما موفق شدیم! الان سیستمی داریم که می تونه مسیر خودرو رو تشخیص بده. کافیه با توجه به محل قرارگیری دوربین در جلو خودرو، در صورتیکه انحراف این خط بیشتر از میزان کالیبره شده بود؛ یعنی خودرو به صورت ناگهانی تغییر مسیر داد، فرمان های هشدار به راننده داده بشه.سیستم تشخیص تغییر مسیر راننده با بهره گیری از بینایی کامپیوتر برای تصاویر واقعی از رانندگی در شباما منظور از فرمان هشدار چیه؟ در ادامه می خوایم به همین سوال پاسخ بدیم.بدون شک کاندیدای اول برای ارتباط با سامانه های الکترونیکی خودرو پورت OBD-II هست. بعد از سال 2004 تمام تولیدکنندگان اروپایی برای کاهش کابل های داخلی خودرو موظف به قرار دادن این پورت در تولیدات خود شدند که یک رابط استاندارد برای دریافت اطلاعات مختلف (مثل ولتاژ باتری، دمای روغن، دور موتور و ...) و عیب یابی (Diagnostics) خودرو است. در خودروهای جدیدتر، این پورت به عنوان یک یونیت (Unit) در باس کن (CAN bus) با دیگر بخش های داخلی خودرو در ارتباط هست. بنابراین می شه از طریق اون اطلاعات رد و بدل شده روی شبکه داخلی خودرو رو رصد کرد یا با ارسال برخی فرامین با یونیت های داخل خودرو ارتباط داشت. تمام نود (Node) ها از طریق دو رشته سیم با نام CAN high یا CANH و CAN low یا CANL که به این شبکه متصل شده اند با هم صحبت می کنند و فریم (Frame) های ارسالی همراه با یک ID عددی برای جداسازی هر فریم و حداکثر 8 بایت داده ارسال می شوند. CAN از دیفرانسیل سیگنالینگ استفاده می کنه؛ یعنی به ازای هر افزایش مقدار سیگنال روی یکی از خط ها به همان میزان مقدار رو روی خط دیگه کاهش میده. از این روش در محیط های پر نویز برای افزایش تحمل خطای سیستم استفاده میشه.قالب بیت های داده در بسته های CAN استانداردتا اونجاییکه می دونم، اطلاعات آنلاین زیادی از اطلاعات CAN برای رانا روی اینترنت پیدا نمیشه. محتویات هر فریم به صورت عمومی ثبت نشدند و با توجه به کارخونه سازنده منحصر بفرد هستند. پس تصمیم گرفتم برخی از جزئیات دسترسی اطلاعات خودروها رو از طریق منبع کدهای این مطلب به صورت عمومی منتشر کنم.شمای نودهای مختلف در خودرو رانا با سیستم مالتی پلکس ECO MUXخودروی رانای ما با موتور TU5 مجهز به شبکه مالتی پلکس با پنج نود FCM یا Front Control Module در قسمت جلوی راننده برای کنترل چراغ ها و محدوده جلو خودرو، ICN یا Instrument Cluster Node برای کنترل بخش های مختلف جلو آمپر و BCM یا Body Control Module در داشبورد برای مدیریت قفل مرکزی، درها و شیشه بالابر که تحت پروتکل CAN Low Speed با هم در ارتباط هستند. در این سیستم BCM دستوراتی که روی سیستم اهرم های پشت فرمان به صورت آنالوگ دریافت میکنه رو به صورت دیجیتال به دستورات شبکه تبدیل میکنه تا بقیه نودها اون ها رو دریافت کنند و این نود به عنوان رابط عیب یابی مستقیما با پورت OBD در ارتباط هست. همچنین در خودرو ما ECU ی موتور و یونیت ABS در یک شبکه با استاندارد CAN High Speed هستند.ما می خوایم برای زمانیکه راننده از مسیر اصلی منحرف میشه یک هشدار ایجاد کنیم. با ساختاری که در بالا توضیح داده شد، چراغ های هشدار مربوط به راهنما در صفحه نمایش جلو داشبورد (جلو آمپر) یک انتخاب خوب هستند. پس سعی میکنیم با هک شبکه و ارسال فریم مربوط به روشن و خاموش شدن چراغ های راهنمای سمت راست و چپ در جلو داشبورد ، به راننده زمانیکه به صورت ناگهانی از مسیر خارج شد، اخطار بدیم. بنابراین اگر خودرو از مسیر اصلی منحرف بشه، راننده بدون اینکه راهنما زده باشه، چراغ راهنمای سمت مورد نظر رو روی صفحه نمایش میبنه.طبق نقشه ها، اطلاعات دسته راهنما به صورت آنالوگ تحلیل میشه؛ یعنی این اهرم با تغییر سطح سیگنال حالت فعلی رو به BCM اطلاع میده. از طرفی میدونیم که اطلاعات چراغ های راهنما از BCM به ICN در شبکه ارسال میشه. چون پورت OBD خودرو ما به صورت مستقیم در شبکه حضور نداره و به BCM متصل هست، برای دسترسی به اطلاعات شبکه با وصل شدن به عنوان فرد میانی (man-in-the-middle) مقادیر فریم های داخل باس رو شنود می کنیم. با کمی جستجو در مستندات و نقشه ها، در میابیم که سیگنال های داده شبکه مورد نیاز ما از BCM قابل ارسال و دریافت هستند. پایه 1 و 2 کانکتور 18 پایه سفید روی BCM به ترتیب مربوط به CANH و CANL هستند. نحوه دسترسی به BCM و محل کانکتور 18 پایه در شکل زیر مشخص شده اند.اتصالات و محل نود BCM داخل خودرو رانا با سیستم ECO MUX؛ دسترسی از زیر داشبورد بالای پای راننده، کنار جعبه فیوز داخل اتاقبرای دسترسی به داده ها می تونیم از کانکتورهای T استفاده کنیم یا با خراش دادن بخشی از روکش سیم با سیم دیگری داده ها رو دریافت کنیم. چون زمانبندی و مقادیر داده فریم های ارسالی در شبکه نباید تحت تاثیر قرار بگیره، پس برای دریافت داده ها از سیم ها از روش T استفاده میکنیم. سطح سیگنال CAN بین 1.25 تا 3.75 ولت هست، برای خواندن این مقادیر در سطح دیجیتال، از فرستنده و گیرنده TJA1050 کمک گرفته و خروجی رو با MAX232 و FT2232 از طریق کابل USB دریافت می کنیم. اگر همه چیز تا به اینجا خوب پیش رفته باشه، داده های ارسالی از پورت USB با درایور مربوطه از طریق یک پورت سریال مجازی قابل دریافت هستند.نحوه برقراری ارتباط برای دریافت و ارسال داده ها از طریق کانکتور T (قرمز رنگ) بر روی سوکت نری (سفید رنگ) BCM خودرو مابعد از آماده سازی سخت افزاری برای دریافت داده ها، سعی میکنیم داده ها رو دریافت کنیم. برای این منظور برنامه ای می نویسیم که داده های پورت سریال رو بخونه و تحلیل کنه. طبق توضیحات بالا، فریم های CAN بر اساس استاندارد مشخصی تولید میشند. طبق استاندارد هر فریم با مقدار 0X7F تموم میشه و فریم ها شامل ID منحصر بفرد هستند؛ بنابراین می تونیم هر فریم رو با مقدار انتهایی و ID اون ها شناسایی کرده و دیگر بخش های فریم رو جداسازی کنیم. هر نود در شبکه CAN داده های خودش رو در یک بازه زمانی در شبکه ارسال میکنه و در هر لحظه مقادیر زیادی داده روی شبکه وجود داره. این نکته هم حائز اهمیت هست که اگر به شبکه CAN پرسرعت متصل هستیم با معماری سخت افزاری که توضیح داده شد، چون سرعت سریال کمتر از میزان داده های دریافتی هست، ممکنه بخشی از داده ها از بین بره که باید این مورد رو هم توی برنامه در نظر بگیریم.برنامه نوشته شده با قابلیت نمایش داده های دریافتی، جداسازی اطلاعات فریم ها و ارسال داده های دلخواه در شبکهبا این برنامه، داده های شبکه بلادرنگ قابل تشخیص و جداسازی هستند. در صورتیکه فریم جدیدی در شبکه ارسال بشه، در ستون سمت چپ مشخص میشه. حالا نوبت این رسیده که فریم های مربوط به دستور روشن شدن چراغ راهنمای سمت راست و چپ در صفحه نمایش جلو آمپر رو پیدا کنیم. این فریم ها زمانی به جلو آمپر ارسال میشند که دسته راهنما در کنار فرمان به بالا و پایین حرکت داده بشه. پس کافیه در حالتیکه برنامه در حال اجرا هست، اهرم رو به طرفین حرکت داده و فریم های مربوطه رو دریافت کنیم.سیستم هوشمند ما با آخرین مرحله کامل میشه، این فریم ها رو به صورت جداگانه زمانیکه خودرو از مسیر اصلی منحرف شد، برای جلوآمپر ارسال میکنیم تا راننده از تغییر مسیر خودرو مطلع شود.ارسال فرمان های روشن شدن چراغ های راهنمای راست و چپ برای زمانیکه راننده از مسیر منحرف میشهاین مطلب به صورت کامل از طریق گیت هاب و مطلب قبلی از اینجا در دسترس هست. همچنین اگر علاقمند به موضوعات هوش مصنوعی، یادگیری ماشین و بینایی کامپیوتر هستید می تونید من رو در توییتر دنبال کنید.توییت مربوط به پروژه تشخیص حالت بدن تست شده بر روی تصاویر همایش فریلنداز تمامی عزیزانی که در چند هفته پیاده سازی و نگارش این مطلب راهنمایی هاشون راهگشای من بود، صمیمانه تشکر میکنم. خوشحال میشم اگر مطلب رو پسندید با بقیه به اشتراک بذارید و ? کنید.این ماجراجویی تموم شد. حالا نوبت شماست که سیستم هوشمند خودتون رو طراحی کنید و تجربیاتتون رو به اشتراک بذارید. به نظر شما چالش های ایجاد یک خودروی خودران هوشمند چیه؟ http://vrgl.ir/Eu7UE