چگونه یک مدل برای شناسایی مکان‌ها آموزش دادیم؟

نویسندگان ‌: محیا مهدیان و محمد حسن ستاریان

مقدمه

deeplearning

در هر مسئله دسته‌بندی (Classification)، پیاده‌سازی یک مدل مناسب -از جهت صحت پیش‌بینی- به مولفه‌های متفاوتی وابسته است؛ داشتن ورودی‌های -با ویژگی‌های- گوناگون و به تعداد زیاد یکی از مولفه‌های مهم برای آموزش مدلی که دقیق (Accurate) بوده و قادر به عمومیت بخشی (Generalization) به دانش خود و راستی آزمایی آن در محیط واقعی است می‌باشد. با این حال جمع آوری داده زیاد کاری سخت و نیازمند زمان و هزینه زیاد، بسته به شرایط و نوع داده مورد نیاز خواهد بود. در این شرایط و با توجه به اینکه کار‌های پیشین زیادی انجام شده اند، استفاده از روش‌های یادگیری انتقال (Transfer learning)، درواقع استفاده از یک مدل از پیش آموزش دیده و استفاده از آن به عنوان استخراج کننده ویژگی (Feature Extractor) یا به عنوان شبکه Fine Tuning کمک بسیار زیادی در ساخت مدلی دقیق و مناسب خواهد داشت. همچنین استفاده از روش‌های افزایش داده (Data augmentation) باعث افزایش چشم‌گیر داده شده و در آموزش بهتر مدل موثر خواهد بود؛ با این‌حال در استفاده از این روش باید توجه داشت از روش‌هایی برای تغییر عکس استفاده کرد که عکس خروجی خارج از فضای حالت مسئله نبوده و در شرایط واقعی مسئله وجود داشته باشد. به علاوه در جمع‌آوری داده باید داده‌های جمع آوری شده بررسی و در صورت نیاز پاکسازی‌هایی نیز انجام شود، تا داده‌های نامناسب، نامربوط و بی‌تاثیر حذف شوند اما از عمومیت داده‌ها کم نشده و داده‌های مختلفی در شرایط مختلف آزمون مسئله وجود داشته باشد؛ چرا که هرچه داده‌ها متفاوت‌تر باشند مدل قابلیت عمومیت بخشی بیشتری خواهد داشت. استفاده از پارامترهای (Hyperparameter)‌ مناسب در آموزش مدل، انتخاب دقیق و بسته به شرایط -و داده‌- پارامترها نیز از اهمیت زیادی برخوردار است و شاید نیاز باشد تغییر دقت مدل با تغییر این پارامترها بررسی شود که در این‌صورت نیاز است مدل چندین دفعه آموزش داده شود.

مراحل پیاده‌سازی مدل

هدف ما آموزش مدلی بود تا بتواند مکان‌های دانشگاه را تشخیص بدهد؛ برای پیاده‌سازی مدل خود از فریم‌ورک کراس (Keras) و زبان پایتون استفاده کردیم. از آنجایی که تعداد کلاس‌ها کم بوده و امکان جمع‌آوری داده زیادی که بتواند مدل را خوب آموزش بدهد نبود، مدلی برای استفاده به عنوان مدل پایه (Base Model)‌ برای Fine Tuning انتخاب شد. سپس داده‌های مورد نیاز جمع‌آوری شده، تمیز شده و آماده آموزش شدند. مدل روی گوگل کولب (Google Colab) به همراه استفاده از روش‌های افزایش داده آموزش داده شده و ذخیره شد. برای استفاده از مدل برنامه‌ای برای اجرای آن روی سرور و گرفتن خروجی با میکروفریم‌ورک فلسک نوشته شده و اپلیکیشن اندرویدی نیز برای گرفتن عکس و پیش‌بینی آن در لحظه ساخته شد. هر مرحله به تفضیل توضیح داده خواهد شد:

کد تمامی مراحل در ریپوزتوری «SRU-Place-Recognizer» قابل دسترسی است.

پیدا کردن مدل پایه

VGG16 + places365

همانطور که گفته شد از آنجایی که تعداد کلاس‌ها کم بوده و امکان جمع‌آوری داده زیادی که بتواند مدل را خوب آموزش بدهد نبود، از روش یادگیری انتقال (Transfer learning) استفاده کرده و مدل VGG16 Places365  برای استفاده به عنوان مدل پایه (Base Model)‌ برای Fine Tuning انتخاب شد. این مدل یک شبکه VGG16 است که از پیش با داده‌های دیتاست Places365 که شامل بیش از ۱۰ میلیون عکس در بیش از ۴۰۰ موضوع است آموزش داده شده است؛ پس نه تنها ویژگی‌های اولیه مورد نیاز مسئله در لایه‌های ابتدایی شناسایی شده‌اند بلکه در لایه‌های جلوتر نیز ویژگی‌های بصری عمیقی شناسایی شده اند و مدلی بسیار مناسب برای این مسئله خواهد بود. بنابراین ما از این مدل به عنوان مدل پایه آموزش خود استفاده کردیم به صورتی که تنها لایه‌های کانولوشنی استفاده شده و از میان‌ آن‌ها ۵ لایه آخر را نیز از حالت فریز (freeze) خارج کردیم. در قسمت ساخت مدل بیشتر بخوانید.

جمع‌آوری داده

برای مسئله شش کلاس -شش مکان برای آموزش مدل- در نظر گرفته شد: دانشکده کامپیوتر، دانشکده معماری، سلف، بوفه، ساختمان امور فرهنگی و زمین ورزشی؛ برای جمع‌آوری داده از این مکان‌ها عکس و فیلم از تمامی زوایای ساختمان‌ها گرفته شد. همچنین سعی شد در زمان‌های متفاوتی عکس‌برداری انجام شود تا تصاویر از تنوع قابل قبولی در نور محیط برخوردار باشند. فریم‌های فیلم‌ها بعدا با استفاده از اسکریپت پایتونی زیر جدا شد تا نهایتا در هر کلاس (از هر مکان) ۸۰۰ عکس شامل ۵۰۰ عکس برای آموزش و ۳۰۰ عکس برای تست و مجموعا ۴۸۰۰ عکس تولید شود.

از این اسکریپت به صورت زیر استفاده می‌کنیم (با این فرض که کدهای بالا را در فایلی با نام frameExtractor.py ذخیره کرده اید)؛ پارامتر اول آدرس فایل ویدئو و پارامتر دوم عددی برای شروع نام‌گذاری تصاویر اسکریپت است برای مواقعی که فریم‌های چندین فایل ویدئو را می‌خواهیم جدا کنیم:

آماده‌سازی داده‌ها

از آنجایی که روش جمع‌آوری داده ما، جدا کردن فریم‌ از فیلم‌های گرفته شده بود، تصاویر نامربوط، برای نمونه از محیط اطراف ساختمان و یا تصاویر تار شده نیز در میان عکس‌ها وجود داشت. همچنین تصاویر با کیفیت ۲۱۶۰*۳۸۴۰ گرفته شده بودند و هر کدام تقریبا حجمی بیش از ۳ مگابایت داشتند که برای آموزش شبکه بسیار سنگین بوده و ویژگی‌های (features) بسیار زیادی تولید می‌کردند که برای برنامه خود تا این حد نیاز به جزئیات نداشتیم؛ همچنین عکس‌ها به صورت landscape جدا شده بودند و نیاز به چرخواندن (rotate) داشتند. برای همین، با استفاده از برنامه ImageMagick تصاویر را ۹۰ درجه چرخوانده و سپس همگی را به سایز ۱۹۲*۱۰۸ تبدیل کردیم تا مدل در حین سبک شدن از ویژگی‌های کافی برای آموزش برخوردار باشد.

برای آشنایی با Image Magick و نحوه انجام کار پست «کار با تصاویر توسط ImageMagick» را بخوانید.

در نهایت تصاویر در فولدرهای مربوطه Train و تست و زیرفولدرهایی با اسامی کلاس‌ها قرار داده شدند. این اسم فولدرها بعدا در آموزش مدل و استفاده از دیتا جنریتور (Data Generator) به عنوان اسامی کلاس‌های مدل تعریف می‌شوند. ساختار فولدربندی داده‌ها به صورت زیر شد:

 

ساخت مدل

همانطور که قبلا اشاره شد برای مسئله از Fine Tuning استفاده شد. مدل نهایی تشکیل شده است از لایه‌های کانولوشنی شبکه VGG16 Places365 که به عنوان مدل پایه استفاده شده است و ۵ لایه آخر آن از حالت حالت فریز (freeze) خارج شده و به دو لایه تماما متصل (Fully connected) با ۲۵۶ نود و ۲ نود که به ترتیب از Activation function های Relu (برای شناسایی nonlinearities) و Softmax (برای کد کردن نتیجه در ۶ کلاس) استفاده می‌کنند متصل شدند.

آموزش مدل

google colab

برای آموزش سریعتر مدل و استفاده از GPU که امکان استفاده آن در سیستم خودمان فعلا وجود نداشت، از سرویس گوگل کولب (Google Colab)‌ استفاده کردیم. برای همین منظور فایل‌های لازم برای آموزش مدل به گوگل درایو منتقل شدند -فایل‌ها آپلود شده و از طریق سرویس SavetoDrive به گوگل درایو منتقل شدند- سپس فایل‌ها را در نوت‌بوکی که در گوگل کولب ساخته بودیم وارد کردیم تا مدل را آموزش دهیم.

آموزش نحوه انتقال فایل از گوگل کولب به گوگل درایو را در پست «اتصال مستقیم سرویس کولب (Google Colab) به درایو (Google Drive) از طریق فایل سیستم FUSE» بخوانید.

برای آموزش مدل پس از تعریف ساختار مدل (که در قسمت ساخت مدل توضیح داده شد)، چون که تعداد داده‌ها زیاد بود از دیتا جنریتور (Data Generator) هایی برای خواندن تصاویر از فولدر‌های مربوطه استفاده شده و برای داده‌های آموزش (Train) از روش‌های افزایش داده (Data augmentation) استفاده شد. تصاویر در گروه‌های ۲۰ تایی به شبکه تغذیه (Feed) شده ( batch_size = 20 )، مقادیر steps_per_epoch  و validation_steps  با توجه به تعداد داده‌های Train و Test و تعداد عکس‌های هر گروه ( batch_size) محاسبه شده و با ۱۰ بار تکرار ( epochs = 10 ) شبکه آموزش دید.

بررسی مدل

برای بررسی مدل نمودارهای روند تغییر accuracy و loss در هر epoch چاپ شد تا از نبود over-fitting مطمئن شویم.

accuracy and loss Plots

به علاوه دقت مدل با پیش‌بینی تصاویری از مکان‌های آموزش دیده که مدل قبلا آن عکس‌ها را در دیتاست آموزش یا تست خود نداشته بررسی شد.

تصویر با استفاده از تابع load_img در سایز مورد استفاده مدل خوانده شده و سپس به آرایه تبدیل شده، آرایه تبدیل به آرایه تک بعدی شده و پیش پردازشی رو آن توسط تابع  preprocess_input انجام شده است. این تابع در فایل  places_utils که مدل پایه (VGG16 Places365در اختیار گذاشته موجود است.

ذخیره مدل

در نهایت برای استفاده‌های آتی، مدل را ذخیره کردیم.

 

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

استفاده از مدل در عمل

اسکریپت پیش‌بینی

برای اینکه از مدل استفاده کنیم، برنامه‌ای لازم داشتیم تا تصویر را دریافت کرده و نتیجه پیش‌بینی را برگرداند. برای این منظور اسکریپت زیر نوشته شد:

اسکریپت در ریپازیتوری در دسترس است.

سرور پیش‌بینی

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

برای آشنایی با فلسک و نحوه ایجاد یک برنامه سرور پست «آموزش مقدماتی فلسک (Flask)»‌ را بخوانید.

سه endpoint برای کار با مدل تعریف شدند؛  upload/  برای آپلود عکس (عکس را به صورت base64 دریافت کرده و آن را ذخیره می‌کند)، imagetopredict/  دریافت آخرین عکسی که برای پیش‌بینی فرستاده شده و  predictagain/  برای پیش‌بینی دوباره آخرین عکس آپلود شده. سپس، این برنامه روی سرور دپلوی شده و مدل آماده استفاده عملی شد.

کد برنامه سرور در ریپازیتوری در دسترس است.

برای آشنایی با نحوه دپلوی مدل پست «دپلوی کردن و استفاده از مدل در عمل (Model deployment)» را بخوانید (ما از روش سوم استفاده کردیم).

اپلیکیشن اندروید

حال که سروری داشتیم که با فرستادن عکس می‌توانستیم نتیجه پیش‌بینی را دریافت کنیم، میخواستیم از هر جایی امکان فرستادن عکس را داشته باشیم؛ برای این منظور با استفاده از فریم‌ورک Nativescript-Vue که ترکیب فریم‌ورک‌های Nativescript که برای ساخت اپلیکیشن‌های اندروید و ios با استفاده از زبان جاوااسکریپت (javascript) است و Vue که یک فریم‌ورک جاوااسکریپتی برای ساخت Progressive Web App هاست، اپلیکیشن اندرویدی برای پیش‌بینی تصاویر توسط مدل و با اتصال به سرور تولید شد.

کد اپلیکیشن در ریپازیتوری در دسترس است.

دپلوی کردن و استفاده از مدل در عمل (Model deployment)

10نویسندگان ‌: محیا مهدیان و محمد حسن ستاریان

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

برای اینکار چندین راه وجود دارد؛ در این پست ما روش‌‌های اجرای لوکال، دپلوی با Heroku و اجرا از سرور ریموت را بررسی می‌کنیم.

 

اجرای لوکال


اگر در فکرید که اجرای لوکال به دسترسی از طریق اینترنت چه ربطی دارد، اجازه بدید ابزار مورد نیاز این روش را معرفی کنیم:

ابزار‌ها

ngrok – ابزاری رایگان برای ایجاد تونل از اینترنت به یک پورت در سیستم لوکال است. ngrok یک آدرس قابل دسترس از اینترنت به پورت مشخص شده می‌دهد تا بتوان ترافیک پورت را از خارج سیستم از طریق اینترنت دریافت کرد.

Flask – فلسک یک میکروفریم‌ورک سبک برای راه‌اندازی سریع و راحت وب‌سرور است. آموزش مقدماتی فلسک را بخوانید.

قبل از شروع، طبق این مراحل ngrok را نصب کرده و آن‌را به PATH سیستم خود اضافه کنید.

طبق آموزش مقدماتی فلسک، کدی مانند نمونه کد زیر برای سروری که قادر به گرفتن عکس (upload)، لود مدل آموزش داده‌شده (Load model)، پیش‌بینی عکس (Predict)‌ و برگرداندن خروجی است، بنویسید.

سپس، سرور فلسک را با وارد کردن دستور زیر در ترمینال اجرا کنید:

پس از اجرا، سرور در آدرس http://localhost:5000 در دسترس می‌شود.

حال با استفاده از ngrok به این سرور یک آدرس قابل دسترس در اینترنت اختصاص می‌دهیم؛ برای اینکار یک ترمینال جدید باز کرده و دستور زیر را وارد می‌کنیم:

در این دستور با فراخوانی ngrok گفته ایم به برنامه درحال اجرا در پورت ۵۰۰۰ میخواهیم دسترسی از طریق پروتکل http بدهیم. پس از اجرای دستور بالا مطابق شکل زیر آدرسی که می‌توان برای دسترسی به سرور استفاده کرد به همراه آدرس مدیریت سرویس ngrok به نمایش در‌می‌آید:

ngrok output

پس از آن می‌توانید از طریق این آدرس و endpoint های تعریف شده از مدل خود استفاده کنید.

 

دپلوی با Heroku


شاید سخت‌ترین روش بین دو روش دیگر این روش و استفاده از Heroku است و مفاهیمی که این روش به عنوان پیش‌نیاز لازم دارد تا آشنا باشید کم نیستند. اما شاید از روش‌های دیگر سخت‌تر باشد اما می‌تواند جذاب‌تر و حتی پرکاربرد تر باشد. همچنین لازم به ذکر است این سرویس فعلا برای استفاده مسدود بوده و نیاز به اتصال غیر مستقیم است و در استفاده رایگان حجم پروژه نباید از ۵۰۰ مگابایت بیشتر باشد.

ابزار‌ها

Heroku – سرویس (PaaS (Platform as a service ای و درواقع بستری به عنوان سرویس ابری است که از زبان‌های برنامه نویسی زیادی پشتیبانی می‌کند که برنامه نویس را از کارهای DevOps لازم برای راه‌اندازی یک سرور بی‌نیاز می‌کند.

Flask – فلسک یک میکروفریم‌ورک سبک برای راه‌اندازی سریع و راحت وب‌سرور است. آموزش مقدماتی فلسک را بخوانید.

Github – گیت‌هاب سرویس میزبانی و کنترل نسخه تحت وب قدرت گرفته از گیت (git) است.

GitLFS – سیستم مدیریت فایل‌های حجیم گیت.

GitLFS سرویس ارائه شده توسط GitHub برای کنترل نسخه فایل‌های حجیم (حجیم تر از ۵۰ مگابایت) است و چون ما در پروژه خود فایل‌های نظیر فایل مدل آموزش داده شده و شاید فایل‌های دیگر داشته باشیم به این برنامه احتیاج داریم.

در ادامه مطابق آموزش شروع استفاده از Heroku با زبان پایتون، دلپوی برنامه خود (سرور پیش‌بینی) را، با استفاده از خط فرمان -و با شروع از سیستم خود- بررسی می‌کنیم؛ اما، این مراحل از طریق داشبورد Heroku که پس از ساخت اکانت در هروکو به آن دسترسی دارید نیز قابل انجام است. خوب است برای برنامه خود یک محیط مجازی پایتون ایجاد کرده، پیش‌نیاز‌های آن را نصب کرده از اجرای لوکال آن مطمئن شده و سپس اقدام به دپلوی آن کنید.برای آشنایی بیشتر آموزش ایجاد محیط مجازی پایتون و آموزش ایجاد سرور فلسک را بخوانید.

ورود

قبل از هر چیز یک اکانت رایگان در Heroku بسازید. اگر پایتون را به صورت لوکال نصب ندارید از اینجا دریافت کنید. در ادامه رابط خط فرمان Heroku را نصب کنید.

پس از نصب موارد فوق، ترمیتال را باز کرده و با استفاده از دستور زیر در Heroku لاگین می‌کنیم:

پس از اجرای دستور، ایمیل و رمزعبور خود را وارد کرده تا وارد شوید.

آماده‌سازی

اگر برنامه شما توسط git مدیریت نمی‌شود با استفاده از دستور git init  آن‌را فعال کنید. همچنین فایل‌های حجیم خود را مشخص کنید تا GitLFS آن‌ها را مدیریت کند:

در این مثال فایل model.h5  را که فایل مدل ذخیره شده است و حجم بیشتر از ۵۰ مگابایت دارد را با استفاده از GitLFS مدیریت می‌کنیم.

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

با اجرای این دستور یک git remote  به نام heroku مرتبط با ریپوزیتوری گیت لوکال شما اضافه خواهد شد. همچنین، یک نام تصادفی (در این مثال lit-bastion-5032 ) به این برنامه تخصیص داده می‌شود. همچنین می‌توان با وارد کردن یک نام دلخواه نام مورد نظر خود را به اپلیکیشن اختصاص داد.

هروکو با استفاده از چند فایل تنظیم، تصمیم می‌گیرد برنامه را به چه صورت و با استفاده از چه سرویسی اجرا کند. برای آن‌که مشخص کنیم برنامه چگونه باید اجرا شود به سه کانفیگ فایل runtime.txt و requirements.txt به همراه فایل Procfile نیاز داریم.

runtime.txt

این فایل شامل توضیحاتی در مورد محیط اجرای برنامه و درواقع زبان مورد استفاده است.

ما این فایل را با محتوی زیر ایجاد می‌کنیم:

requirements.txt

این فایل، پیش‌نیازهای اجرای برنامه را مشخص می‌کند.

ما این فایل را با خروجی دستور pip freeze  که پکیج‌های نصب شده برای پروژه را چاپ می‌کند به صورت زیر ایجاد می‌کنیم:

Procfile

این فایل، شامل توضیحات نحوه اجرای برنامه است.

ما ابن فایل را با دستور زیر ایجاد خواهیم کرد:

این دستور بیان می‌کند که برنامه ما یک برنامه از نوع web بوده و لازم است با استفاده از برنامه سرور gunicorn اجرا شود و فایل اجرایی اپلیکیشنی به نام server است.

دلیل استفاده از سرور gunicorn بجای سرور پیش‌فرض پایتون این است که هروکو از این سرور برای اجرا، بخصوص برای اجرای فلسک استفاده می‌کند.

نکته مهم استفاده از gunicorn این است که این برنامه ابتدا یک سرور اجرا کرده سپس برنامه ما را در آن import می‌کند. از آنجایی که برنامه ما خود سرو خواهد شد نیازی به دستور ()app.run  نخواهد بود و اگر در کد خود از این دستور استفاده کرده ایم باید آن را مانند مثال زیر در شرط بررسی import شدن یا نشدن ماژول قرار دهیم:

با اعمال تغییرات فوق و اضافه کردن کانیفگ فایل‌ها، این تغییرات را با استفاده از گیت کنترل می‌کنیم:

قبل از ادامه دپلوی با استفاده از دستور heroku local web  می‌توانیم سرور خود را به صورت لوکال تست کنیم، اما از آنجایی که برنامه gunicorn در ویندوز قابل اجرا نیست اگر از ویندوز استفاده می‌کنید این امکان وجود نخواهد داشت.

حال اگر برنامه ما نیاز به تغییر نداشته و آماده push  کردن هستیم، با دستور زیر برنامه را در ریپوزیتوری ریموتی که هروکو در اختیارمان گذاشته بود push  می‌کنیم:

readme_assets/images/heroku-git-push.gif

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

با استفاده از دستور زیر می‌توانیم آدرس اختصاص داده شده به برنامه را در مرورگر باز کنیم:

برنامه آماده استفاده است!

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

heroku deploy options

اجرا از سرور ریموت


مراحل این روش تا حدود زیادی شبیه روش اول است، چراکه باز نیز با استفاده از flask یک برنامه سرور اجرا می‌کنیم. برای این روش لازم است از یکی از سرویس‌های ارائه دهنده سرور‌های ابری (Cloud servers) و یا سرور‌های اختصاصی (VPS)، سروری تهیه کنید. پس از تهیه سرور IP ای برای دسترسی به سرور به شما داده می‌شود. با استفاده از این سرور و از آنجایی که این IP یک IP عمومی (Public IP)‌ است، تنها کافی است با استفاده از فلسک سروری در سیستم اجرا کرده و host آن را برابر ‘0.0.0.0’ قرار دهیم تا از طریق اینترنت قابل دسترس باشد.

ابزار‌ها

Flask – فلسک یک میکروفریم‌ورک سبک برای راه‌اندازی سریع و راحت وب‌سرور است. آموزش مقدماتی فلسک را بخوانید.

SSH – پروتکل شبکه‌ای برای اتصال امن که یکی از کاربرد‌های آن ورود به یک سیستم ریموت است.

برای اتصال به سرور از SSH استفاده می‌کنیم. برای همین اگر از ویندوز استفاده می‌کنید از نرم‌افزار PuTTY استفاده کرده و اگر از لینوکس استفاده می‌کنید و یا در سیستم ویندوز خود کرنل لینوکس را فعال کرده‌اید (WSL) -از طریق کرنل لینوکس موجود در سیستم- به آی‌پی سرور از طریق SSH متصل شوید.

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

پس از آن تنها کار لازم اجرای اسکریپت سرور فلسک است. توجه کنیم که برای اجرای سرور فلسک host آن‌را برابر ‘0.0.0.0’ و پورت دلخواه (پیش فرض ۵۰۰۰) تنظیم می‌کنیم:

برنامه در آدرس سرور و پورت تعیین شده اجرا شده و از طریق endpointها در دسترس خواهد بود.

 

منابع

مقاله‌های «پلوی کردن مدل کراس» و «دپلوی مدل‌های کراس» در مدیوم

رپوزیتوری گیت «مثال دپلوی اپلیکیشن پایتون در هروکو»، tl;dr

آموزش مقدماتی فلسک (Flask)

Flask, web development one drop at a time

نویسندگان ‌: محیا مهدیان و محمد حسن ستاریان

مقدمه و آشنایی

فلسک یک فریم‌ورک وب مبتنی بر پایتون است برای ایجاد سریع و ساده وب‌سرور که توسط آرمین‌روناچر توسعه داده‌شده است. تلاش برای ساده‌نگه داشتن طراحی فلسک و کوچکی فریم‌ورک و قائل نشدن بسیاری از پیش‌فرض ها برای برنامه‌نویسان دلیلی‌است که این بسته‌نرم افزار را یک میکروفریم‌ورک می‌نامند. فلسک رایگان و متن‌باز بوده و  با مجوز آزاد BSD منتشر شده است.

کار با فلسک به قدری ساده است که اگر کمی با زبان پایتون آشنا باشید با دیدن اولین کدهای فلسک با ساختار این فریم‌ورک آشنا می‌شوید. فریم‌ورک فلسک با همه‌ی سادگی خود بسیار قدرتمند و کاراست و به هیچ عنوان کوچک بودن فریم‌ورک را نمی‌توان با ضعیف بودن آن برابر دانست و امکانات فریم‌ورک‌هایی مثل جنگو و ریلز را با اندکی جستوجو به دست می‌دهد. برای مثال از سرویس‌های بزرگی که از فلسک استفاده می‌کنند می‌توان از Pinterest و Linkedin نام برد که به مناسب بودن فلسک برای توسعه‌ی سرویس‌های اینترنتی اشاره دارد.

دو کتابخانه‌ی اساسی پایه‌‌های قدرتمند فلسک را ساخته‌اند؛ به عنوان واسط وب‌سرور ( WSGI ) از کتابخانه‌ی werkzeug و برای تمپلیت‌انجین از Jinja2 استفاده کرده اند که هردو کتابخانه توسط تیم توسعه ی فلسک توسعه یافته شده است.

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

نصب

آماده کردن محیط مجازی

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

نحوه ایجاد و فعال‌سازی محیط مجازی را از اینجا بخوانید.

نصب فلسک

حالا نوبت نصب بسته ی فلسک است. متداول ترین روش نصب بسته‌های پایتون استفاده از مدیر بسته‌ی pip است که با استفاده از آن فلسک با دستور زیر نصب می‌شود :

برای بررسی صحت نصب فلسک مفسر پایتون را بصورت تعاملی در ترمینال باز کنید ( تنها دستور python را نوشته و  اینتر کنید ) و بسته‌ی فلسک را با دستور زیر فراخوانی کنید :

اگر خطایی رخ نداد فلسک درست نصب شده است و می‌توانید با اجرای دستور زیر نسخه نصب شده را بررسی کنید:

ساختار برنامه‌ها در فلسک

فلسک هیچ محدودیتی درمورد ساختاربندی فایل‌های پروژه برای شما ایجاد نمی‌کند و می‌توانید ساختار خودتان را داشته باشید یا از رول‌های متداول جامعه ی فلسک استفاده کنید.

ساخت برنامه های فلسک

شروع سریع

کدهای یک اپلیکیشن ساده‌ی فلسک که عبارت  Hello World  را در یک صفحه ی وب نمایان می‌کند بصورت زیر است :

این برنامه از چند بخش تشکیل شده است : فراخوانی و تعریف فلسک ، تعریف مسیرها، اجرای فلسک.

فراخوانی و تعریف فلسک

برای ساخت برنامه‌های فلسک نیاز است ابتدا فلسک را در فایل پایتون خود لود کنید و سپس یک نمونه (instance) از Flask بسازید یعنی این بخش :

تنها آرگومان مورد نیاز برای کانستراکتور فلسک نام ماژول یا پکیج main است که برای بیشتر برنامه ها __name__ در پایتون مقدار درستی است.

می‌توانیم بجای نام اینستنس فلسک ( در مثال بالا app ) هر نام متغیر معتبری استفاده کنیم.

فلسک روی pip یک بسته از ماژول‌های مرتبط به هم است و نه یک ماژول و به همین دلیل هر ماژول باید از درون بسته ی flask جداگانه ایمپورت بشود.

تعریف مسیرها

مسیرها همان آدرس‌های (url های) مختلفی هستند که عملیات‌های متفاوتی بر اساس آن‌‌ها انجام می‌شود. مثلا  site.domain  مسیر ریشه و  site.domain/subdomain  یک مسیر دیگر در همان سایت تعریف می‌کند. در کد مثال ما مسیر بصورت زیر تعریف شده بود :

در اینجا یک دکوریتور نوع ()route  از app (که در قسمت قبل ساختیم) برای تابع Hello world  تعریف می‌کند و آدرس مسیر ('/') را به آن می‌فرستد. مسیرها در فلسک اساس ساخت برنامه‌ها هستند. با استفاده از مسیر‌ها می‌توانید به سادگی بخش‌های مختلف وب‌اپلیکیشن خود را بسازید و مدیریت کنید.

اجرای فلسک

در آخر به پایتون می‌گوییم که فلسک را روی یک وب‌سرور اجرا کند که دستورات آن بصورت زیر است :

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

این کد را در یک فایل مانند app.py ذخیره کرده و در خط فرمان با دستور  python app.py  اجرا کنید. خروجی روی ترمینال چیزی شبیه این است :

که آدرس 127.0.0.1:5000  را که در خروجی مشخص شده است اگر در مرورگر خود امتحان کنید روی صفحه عبارت Hello World  نمایان می‌شود. فلسک به صورت پیش‌فرض پورت ۵۰۰۰ را برای اجرا در نظر می‌گیرد.

تابع run می‌تواند پارامتر‌ ای با عنوان host  داشته باشد که مشخص می‌کند سرور برروی چه آدرسی اجرا شود، همچنین توسط پارامتر  port  می‌توان پورتی که سرور روی آن اجرا شود را مشخص کرد و توسط پارامتر  debug و دادن مقدار true  به آن می‌توان مشخص کرد که لاگ‌ها و گزارشات مربوط به اشکال یابی برنامه نیز چاپ شوند.

برای اینکه سرور از طریق کامپیوتر‌های متصل به همین شبکه قابل مشاهده و استفاده باشد به پارامتر  host  مقدار 0.0.0.0  را می‌دهیم.

توجه کنید که پارامتر host از جنس string، پارامتر port از جنس integer و پارامتر debug از جنس boolean است.

برنامه‌های کاربردی‌تر

استفاده از متغیرها در آدرس

در تعریف قوانین آدرس‌دهی می‌توان به آدرس‌ها با استفاده از عملگرهای <>  متغیر اضافه کرد مانند  <variable_name>  تا بخشی از آدرس به صورت متغیر توسط تابع در دسترس باشد.همچنین می‌توان نوع متغیر را با استفاده از یک مبدل مانند  <converter:variable_name>  مشخص کرد:

نوع پیش‌فرص برای متغیرها string  است.

آدرس‌های منحصر به فرد و هدایت آدرس

به نحوه آدرس دهی در برنامه زیر دقت کنید:

آدرس تعریف شده برای  projects  شبیه آدرس دایرکتوی است و در انتهای خود یک ‘/’ دارد. اگر به این آدرس بدون ‘/’ برویم فلسک ما را به آدرس اصلی (آدرس با ‘/’) هدایت می‌کند.

آدرس تعریف شده برای  about  شبیه آدرس فایل است و در انتهای خود ‘/’ ندارد.  اگر به این آدرس با ‘/’ برویم با خطای ۴۰۴ (صفحه‌ای یافت نشد) مواجه خواهیم شد. این امر این امکان را می‌دهد تا آدرس‌های تعریف شده به این سبک منحصر به فرد بوده و کمک می‌کند موتورهای جستوجو یک صفحه را دوبار ایندکس نکنند.

متدهای HTTP

برنامه‌ها هنگام دسترسی به آدرس‌ها از متد‌های HTTP مختلفی استفاده می‌کنند. به صورت پیش‌فرض یک آدرس تنها به متد GET  پاسخ می‌دهد، اما با استفاده از مشخص کردن متدهای لازم در پارامتر methods  از دکوریتور ()route  می‌توان به متدهای مختلف پاسخ داد:

در کد با بررسی نوع (method) درخواست (request) عملیات متفاوتی انجام می‌شود. این بدین معنی است که اگر به یک آدرس با متد GET درخواست بدیم یک پاسخ و اگر به همان صفحه با متد دیگری مانند POST درخواست بدیم پاسخ دیگری دریافت خواهیم کرد.

استفاده از قالب‌ها (templates)

می‌توان مشخص کرد با مراجعه به صفحه‌ای یک فایل HTML رندر شده و به نمایش درآید. برای اینکار فلسک از فولدربندی خاصی استفاده می‌کند. در فولدر پروژه باید دو فولدر به نام های static و templates ایجاد کنید که در فولدر templates فایل های html و در فولدر static فایل های css و js خودتون رو قرار بدهید.

حال  اگر کاربر به صفحه welcome/ برود فانکشن به جای متن خالی، فایل HTML رو return می‌کند. توجه داشته باشید که این فایل HTML باید داخل پوشه templates قرار گرفته باشد تا فلسک اون رو شناسایی بکند.

استفاده در بخشی از برنامه

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

این برنامه یک برنامه یادگیری ماشین است که عکس ارسالی به endpoint با آدرس predict/  و متد POST  را آپلود کرده و با predict آن نتیجه را برمی‌گرداند. با اجرای کد مدل مربوطه لود شده و سرور شروع به گوش دادن به endpoint ذکر شده برای دریافت درخواست‌ها می‌کند و در صورت دریافت درخواستی حاوی تصویر، توابع مربوطه برای predict عکس را صدا زده و نتیجه را برمی‌گرداند.

افرونه‌ها

فلسک یک فریم‌ورک بسیار توسعه پذیر است و می‌توانید بصورت ماژولار کدهای آن را تقسیم بندی و استفاده کنید. همچنین پلاگین‌های بسیاری هم‌اکنون برای آن نوشته شده است که میتوانید در صفحه‌ی extension های فلسک تعدادی از بهترین افزونه‌های فلسک را بیابید و استفاده کنید.

 

منابع

مقاله «میکروفریم‌ورک فلسک – معرفی» از سایت کدرز

مقاله «آشنایی با میکرو-فریمورک فلسک»‌ از سایت هایو

 

مطالعه بیشتر

سری آموزش «The Flask Mega-Tutorial» از miguelgrinberg

محیط‌های مجازی پایتون (Python virtual environments)

python virtual environments visualization

نویسندگان ‌: محیا مهدیان و محمد حسن ستاریان

مقدمه

محیط‌های مجازی (virtual environments) از مهمترین شیوه‌های آزموده شده (Best practice) در توسعه نرم‌افزار تحت پایتون هستند. از آنجایی که با نصب پکیج‌های پایتون، همگی این پکیج‌ها در مسیر‌های مشخصی نصب می‌شوند ممکن است باعث ایجاد مشکلاتی شوند. برای مثال حالتی را در نظر بگیرید که در ایجاد پروژه‌های مختلف به نسخه‌های متفاوتی از برخی کتابخانه‌ها نیاز دارید؛ در این صورت چگونه می‌توانید چندین نسخه‌ متفاوت از یک کتابخانه‌ را در پایتون نصب کنید؟ فرض کنید می‌خواهیم بر روی توسعه دو وب‌سایت؛ یکی توسط نسخه جدید (۱.۸) وب فریم‌ورک جنگو (Django) و دیگری بر روی یک نسخه قدیمی (۰.۹۶) از آن کار کنیم، ولی نمی‌توانیم! چراکه نمی‌شود هر دوی این نسخه‌ها را با هم در پایتون (دایرکتوری site-packages) نصب داشت. یا فرض کنید که برای تست پکیج‌هایی می‌خواهیم بدون نصب آن‌ها در کنار پروژه اصلی، از آن‌ها استفاده کنیم؛ در این وضعیت راه حل ایجاد محیط‌هایی مجازی (Virtual Environments) برای توسعه پروژه‌های مورد نظر است، ابزاری که محیط توسعه و اجرای هر پروژه پایتون را به همراه تمام وابستگی‌های (Dependencies) آن از پروژه‌های دیگر جدا یا ایزوله (AKA. Sandboxing) می‌کند.

در ادامه به بررسی ابزارهای زیر می‌پردازیم:

  • conda
  • virtualenv
  • virtualenvwrapper
  • pyvenv

کوندا (Conda)


یکی از روش‌های مدیریت ورژن‌های پایتون و همچنین ایجاد محیط‌های مجازی پایتون استفاده از کوندا است.

از مزایای conda می‌شود به موارد زیر اشاره کرد:

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

نصب

برای نصب Conda از این آموزش استفاده کنید.

ساخت محیط مجازی توسط Conda

برای ساخت محیط مجازی ای با نام myenv و نصب پایتون ۳.۴ و پکیج‌های package1 و package2 با ورژن دلخواه به صورت زیر عمل می‌کنیم:

ورود و خروج به محیط مجازی

برای ورود و فعال سازی محیط مجازی ای با نام myenv به صورت زیر عمل می‌کنیم:

در صورتی که به درستی وارد محیط مجازی شوید، prompt خط فرمان تغییر می‌کند. برای مثال با فعال کردن محیط myenv توسط دستورات بالا به صورت زیر تبدیل می‌شود:

اکنون می‌توانیم در پروژه خود به کتابخانه‌ها، pip، دایرکتوری site-packages و مفسری اختصاصی دسترسی داشته باشیم. همچنین با فعال کردن یک محیط مجازی، فایل‌های اجرایی مربوط به این محیط درون متغیر PATH قرار می‌گیرند تا دستورات مورد استفاده به سادگی در دسترس باشند.

برای خروج و غیر فعال کردن محیط از دستور زیر استفاده می‌کنیم:

برای لیست کردن محیط‌های مجازی از دستور  conda env list و برای لیست کردن پکیج‌ها درون یک محیط از دستورات conda list ویا pip list با توجه به اینکه با کدام روش پکیج‌ها را نصب کرده‌ایم استفاده می‌کنیم.

حذف محیط مجازی

برای حذف محیط مجازی ای که دیگر به آن احتیاج نداریم به صورت زیر عمل می‌کنیم:

برای مطالعه بیشتر در مورد کوندا و کنترل محیط‌های مجازی توسط آن به منابع مربوطه در انتهای پست مراجعه کنید.

از آنجایی که Conda پکیجی چندمنظوره بوده و امکانات و نرم‌افزار‌های زیادی را همراه خود دارد، حجیم بوده و راه‌اندازی آن ممکن است به زمان بیشتری نیاز داشته باشد. روش دیگر ساخت محیط‌های مجازی استفاده از پکیج virtualenv و یا افزونه آن virtualenvwrapper است که در ادامه توضیح داده خواهند شد.

virtualenv


از معروف‌ترین و پراستفاده ترین روش‌های ساخت محیط‌های مجازی برای پایتون استفاده از پکیج virtualenv  است که در ادامه بررسی میکنیم.

نصب

این پکیج به راحتی با استفاده از پیپ (pip) به صورت زیر قابل نصب است:

 

چنانچه بر روی سیستم عاملی هر دو نسخه پایتون 2x یا 3x نصب است؛ این موضوع که virtualenv را توسط pip کدام نسخه نصب نمایید، اهمیت چندانی ندارد. چرا که امکان استفاده از آن برای دیگر نسخه‌ها نیز وجود دارد.

ساخت محیط مجازی توسط virtualenv 

اکنون برای ایجاد یک محیط مجازی از دستور  virtualenv ENV  استفاده می‌شود که منظور از  ENV  در آن، نشانی دایرکتوری دلخواهی است که قصد داریم محیط مجازی در آن ایجاد گردد:

دستور بالا موجب ایجاد یک محیط مجازی در مسیر  /Documents/ENV  سیستم عامل، بر پایه مفسر پایتونی که از pip آن برای نصب virtualenv استفاده کردیم می‌شود و چنانچه بخواهیم محیط مجازی خود را بر پایه‌ نسخه‌ موجود دیگری از پایتون ایجاد نماییم، لازم است با استفاده از فلگ   --python  نشانی مفسر آن مشخص گردد [صفحه راهنما + این پاسخ ]:

در نمونه کد‌ بالا، نسخه‌های۲.۷ و ۳.۴ پایتون از پیش بر روی سیستم عامل نصب بوده و نسخه ۳.۳ و ۲.۵ توسط کاربر در مسیرهای مشخص شده نصب شده است.

ورود و خروج به محیط مجازی

برای ورود و فعال سازی محیط مجازی ای با نام myenv به صورت زیر عمل می‌کنیم:

توچه کنید که با ورود موفق به محیط مجازی prompt خط فرمان چگونه تغییر می‌کند.

اکنون می‌توانیم در پروژه خود به کتابخانه‌ها، pip، دایرکتوری site-packages و مفسری اختصاصی دسترسی داشته باشیم. همچنین با فعال کردن یک محیط مجازی، فایل‌های اجرایی مربوط به این محیط درون متغیر PATH قرار می‌گیرند تا همانند تا دستورات مورد استفاده به سادگی در دسترس باشند.

در لینوکس می‌توانید با اجرای دستورات  which python3 و  which pip3 بررسی کنید که مسیر فایل اجرایی مفسر پایتون و pip از مسیر معمول آن (usr/bin/python3/)‌ متفاوت است.

پس، برای هر پروژه‌ای کافیست داخل پروژه یکبار با فراخوانی virtualenv کارهای لازمه را انجام دهید و پس از آن هرباری که داخل دایرکتوری پروژه مورد نظر می‌شوید آن محیط را فعال کنید.

برای خروج و غیر فعال کردن محیط از دستور زیر استفاده می‌کنیم:

اگر از لینوکس استفاده می‌کنید، با اضافه کردن alias های زیر می‌توان کار ورود و خروج از محیط‌های مجازی را ساده‌تر کرد:

 

virtualenvwrapper


virtualenvwrapper همونطور که از اسمش پیداست یک افزونه و wrapper برای virtualenv است که علاوه بر راحت کردن کار با آن، ایرادات زیر رو هم رفع می‌کند. توجه کنید که virtualenv پیش‌نیاز این پکیج نبوده و لازم به نصب آن نیست:

  • جلوگیری از ساخت دایرکتوری مربوط به مدیریت پایتون و محیط مجازی کنار فایل‌های پروژه (در صورت استفاده از git، باید این فولدر را در gitignore اضافه کنید)
  • لزوم به اعمال فعال سازی و غیر فعال سازی
  • و موارد دیگر

این پکیج برای لینوکس توسعه داده شده است و برای ویندوز یک توزیع از این پکیج با نام virtualenvwrapper-win قابل استفاده است.

نصب

این پکیج به راحتی با استفاده از پیپ (pip) به صورت زیر قابل نصب است:

پکیج virtualenvwrapper برخلاف virtualenv و مانند conda، تمام محیط‌های مجازی را داخل دایرکتوری ای که ما مشخص می‌کنیم ذخیره می‌کند که اینکار باعث جداسازی کد‌ها و پکیج‌های پایتونی ای که نصب می‌کنیم بدون ایجاد ایراداتی که اشاره شد می‌شود.

پیش از ساخت محیط‌های مجازی، اگر از لینوکس استفاده می‌کنید دو دستور پایین را داخل فایل bashrc. (یا zshrc. یا کانفیگ فایل هر شل مورد استفاده) قرار می‌دهیم:

و اگر از ویندوز استفاده می‌کنید متغیری با نام  WORKON_HOME  در Environment Variable ویندوز اضافه کرده و مقدار آن را برابر  USERPROFILE%\Envs%  می‌گذاریم. [آموزش]
با اینکار فولدر virtualenvs. را در لینوکس و فولدر Envs را در ویندوز و در مسیر‌های مشخص شده برای ذخیره سازی محیط‌های مجازی مشخص می‌کنیم.

ساخت محیط مجازی توسط virtualenvwrapper

برای ساخت محیط مجازی ای با نام myenv و ورود به آن از دستور زیر استفاده می‌کنیم:

ورود و خروج به محیط مجازی

برای ورود و فعال سازی محیط مجازی ای با نام myenv به صورت زیر عمل می‌کنیم:

و برای خروج و غیر فعال کردن محیط از دستور زیر استفاده می‌کنیم:

برای لیست کردن محیط‌های مجازی از دستور  lsvirtualenv و یا دستور  workon بدون ورودی استفاده می‌کنیم.

حذف محیط مجازی

برای حذف محیط مجازی ای که دیگر به آن احتیاج نداریم به صورت زیر عمل می‌کنیم:

یک دستور جالب این پکیج  mktmpenv است که یک محیط مجازی با اسم تصادفی ساخته و آن‌را فعال می‌کند و با غیر فعال کردن آن محیط مجازی را پاک می‌کند که برای تست یک کد یا پکیج به سرعت ایده‌آل است.

pyvenv


در نسخه‌های ۳x پایتون و از ۳.۳ به بعد ماژولی با نام venv برای ایجاد محیط‌های مجازی به کتابخانه استاندارد پایتون افزوده شده است که می‌توان از آن به جای نصب virtualenv استفاده نمود و نیازی به نصب ندارد؛ برای این منظور از دستور  pyvenv  و با الگویی مشابه  pyvenv ENV  استفاده می‌گردد.

ساخت محیط مجازی توسط virtualenvwrapper

برای ساخت محیط مجازی ای با نام myenv و ورود به آن از دستور زیر استفاده می‌کنیم:

ورود و خروج به محیط مجازی

برای ورود و فعال سازی محیط مجازی ای با نام myenv به صورت زیر عمل می‌کنیم:

و برای خروج و غیر فعال کردن محیط از دستور زیر استفاده می‌کنیم:

 

منابع

کوندا (Conda)

مقاله «چرا به محیط‌های پایتون نیاز دارید و چگونه آن‌ها را با کوندا مدیریت کنیم» در مدیوم

مقاله «ساخت محیط‌های مجازی برای پایتون توسط کوندا» از سری مقاله‌های دستورالعمل‌های ۲ دقیقه‌ای برای دانشمندان

virtualenv

فصل «ایجاد محیط مجازی» از کتاب آنلاین پایتون کدرز

مقاله «پایتونیک – معرفی Virtual Environment‌ها قسمت اول» در ویرگول

virtualenvwrapper

مقاله «پایتونیک – معرفی Virtual Environment‌ها قسمت دوم» در ویرگول

مستندات virtualenvwrapper

pyvenv

فصل «ایجاد محیط مجازی» از کتاب آنلاین پایتون کدرز

 

مطالعه بیشتر

این سوال و جواب در stackoverflow

مقاله «رمزبرداری از محیط‌های مجازی»

اجرای نوت‌بوک‌ها تحت وب توسط سرویس Azure notebook

سرویس Microsoft Azure Notebooks یک Interactive Notebook یا یک محیط آنلاین برنامه‌نویسی پویا (interactive) قدرت گرفته از Jupyter است که زبان‌های پایتون، R و #F را پشتیبانی‌می‌کند.

مزیت این سرویس نسبت به سرویس‌های مشابه مثل mybinder و یا حتی repl.it ؛ در دسترس بودن برای همه کاربران و از پیش نصب بودن تعداد زیادی از پکیج‌های مورد نیاز برای انواع زمینه‌ها است. همچنین این سرویس یک ترمینال برای مدیریت و کار با فایل‌های نوت‌بوک در اختیار هر کاربر می‌گذارد و هر کاربر ۴ گیگابایت فضای مموری و ۱ گیگابایت فضای ذخیره‌سازی فایل برای هر نوت‌بوک به صورت رایگان در اختیار دارد.

این سرویس امکان ساخت نوت‌بوک و یا کلون‌کردن (کپی‌کردن) یک ریپوزیتوری گیت که دارای نوت‌بوک است و اجرای آن تحت وب را به کاربران می‌دهد. برای اینکار تنها داشتن یک ایمیل در یکی از سرویس‌های مایکروسافت مثل outlook و یا hotmail کافیست.

 

در ادامه موارد زیر را بررسی می‌کنیم:

  • نحوه ورود و اجرای نوت‌بوک‌ها در Azure notebook و ایجاد یا کلون کردن یک نوت‌بوک
  • نصب پکیج‌ها داخل نوت‌بوک‌ها یا توسط ترمینال

 

ورود، ایجاد یا کلون و اجرای نوت‌بوک‌ها

  • پس از ورود -توسط ایمیل مایکروسافتی (outlook یا hotmail)- برای دسترسی به نوت‌بوک‌ها وارد قسمت Libraries (از گزینه‌های بالای صفحه) می‌شویم تا لیست نوت‌بوک‌ها فعلی نمایش داده شود.
  • برای ساخت و یا کلون کردن نوت‌بوک روی گزینه New Library + کلیک می‌کنیم. حال برای کلون کردن ریپازیتوری کلاس در گیت‌هاب وارد تب From GitHub شده و آدرس آن را در فیلد اول و نام دلخواه خود برای نوت‌بوکی که ساخته خواهد شد را در فیلد دوم و آدرس دلخواهمان برای دسترسی به این نوت‌بوک را در فیلد سوم وارد می‌کنیم.
  • پس از پایان عملیات کلون کردن (مدتی طول می‌کشد) وارد کتابخانه کلون شده می‌شویم و نوت‌بوک‌ها با انتخاب آنها در دسترس هستند.
  • اگر سرور اجرای نوت‌بوک‌ها روشن نباشد با انتخاب یکی از نوت‌بوک‌ها روشن شده و پس از مدتی نوت‌بوک اجرا شده و همانند یک ژوپیتر نوت‌بوک که در کامپیوتر اجرا می‌کردیم، تحت وب قابل استفاده است.
  • با باز کردن نوت‌بوک پنجره‌ای برای انتخاب کرنل مورد نیاز برای این نوت‌بوک باز خواهد شد. البته کرنل را می‌توان بعدا از طریق تب Kernel داخل خود نوت‌بوک هم تغییر داد.
  • در ویدئو برای تست نوت‌بوک و کرنل آن سه کتابخانه openCV، Tensorflow و Keras در نوت‌بوک import شده و ورژن آنها بررسی و چاپ شد.
کلون‌کردن نوت‌بوک‌ها از طریق کلیک روی دکمه launch | azurenb در ابتدای هر نوت‌بوک نیز قابل انجام است.

نصب پکیج

علاوه بر تعداد زیاد پکیج‌های از پیش نصب شده برای هر نوت‌بوک امکان نصب پکیج‌های دلخواه هم از داخل نوت‌بوک و از هم طریق ترمینال وجود دارد.

پکیج‌هایی که نصب می‌شوند تنها در طول مدت روشن بودن سرور نوت‌بوک‌ها فعال هستند و نوت‌بوک‌های غیرفعال پس از ۱ ساعت عدم فعالیت خاموش می‌شوند.

نصب پکیج از داخل نوت‌بوک

  • در داخل نوت‌بوک‌ها با استفاده از اوپراتور «!» در ابتدای خط هر سلول می‌توان دستوری را از داخل نوت‌بوک روی کرنل سیستم‌عامل سرور اجرا کرد و خروجی آن را داخل نوت‌بوک مشاهده کرد. برای امتحان این موضوع دستور cal (کوتاه کلمه calendar) استفاده شد که یک تقویم کوتاه را نمایش می‌دهد.
  • همانطور که دستور cal که یک دستور محیط ترمینال ([terminal [bash) است داخل نوت‌بوک قابل دسترسی است؛ دستورات pip یا conda که برای نصب پکیج‌ها استفاده می‌کنیم هم در دسترس هستند.
  • برای امتحان در دسترس بودن این دو دستور لیست پکیج‌های نصب شده توسط هر دو برنامه با دستورهای pip list و conda list چاپ شد.
  • همچنین برای مثال نصب پکیج، پکیج cowsay از داخل خود نوت‌بوک نصب و بلافاصله قابل import کردن و استفاده شد.

نوت‌بوک توضیحات

نکته مهم در حذف پکیج از داخل نوت‌بوک

از آنجایی که از داخل نوت‌بوک‌ها امکان دادن ورودی (input) به برنامه در حال اجرا روی ترمینال (مثلا هنگام نصب پکیج توسط pip) وجود ندارد و اگر برای حذف یک پکیج نیاز به تایید یا ورود هر نوع اطلاعاتی از سمت کاربر باشد عملیات به صورت کامل انجام نمی‌شود باید از فلگ (flag) یا تنظیم q- به همراه دستور pip استفاده کرد.

نصب پکیج توسط ترمینال

  • هر نوت‌بوک به صورت مجزا ۴ گیگ رم و ۱ گیگ فضای ذخیره‌سازی در اختیار دارد. به علاوه می‌توان به صورت مستقیم از طریق ترمینال به مدیریت و کنترل محیط اختصاصی (Environment / container) نوت‌بوک بر روی سرور پرداخت.
  • ترمینال از طریق دکمه Terminal در صفحه کتابخانه نوت‌بوک‌ها در دسترس است.
  • برای تست ترمینال مشخصات سرور چاپ شد.
  • بر اساس کرنل انتخاب شده برای نوت‌بوک، کرنل پایتون در مسیر جداگانه‌ای مطابق زیر قرار دارد:
    • کرنل python 2.7 :
      مسیر anaconda2_501/~
    • کرنل python 3.5 :
      مسیر anaconda3_420/~
    • کرنل python 3.6 :
      مسیر anaconda3_501/~
  • باید به این نکته توجه کرد که پایتون داخل نوت‌بوک با پایتونی که داخل ترمینال نصب است متفاوت است و در نتیجه برنامه‌های آنها مخصوصا pip و conda که ما نیازشان داریم هم متفاوت هستند؛ چراکه پایتون محیط ترمینال آن پایتونی است که روی سرور نصب است اما پایتونی که به عنوان کرنل نوت‌بوک استفاده می‌شود در مسیری همانند آنچه بالا گفته شد قرار دارد.
  • برای بررسی نکته بالا با استفاده از دستور which و اجرای which pip مسیر برنامه pip درون نوت‌بوک و درون ترمینال چاپ شد که مشاهده می‌شود درون نوت‌بوک pip از درون دایرکتوریanaconda3_501 و درون ترمینال از دایرکتوری دیگری اجرا می‌شوند.
  • برای دسترسی به برنامه pip یا conda ای که پکیج‌های نوت‌بوک را مدیریت می‌کند می‌توان به دو صورت عمل کرد:
    • اجرای مستقیم این برنامه‌ها از مسیر نصبشون به این صورت که بجای دستور pip یا conda می‌نویسیم : [anaconda3_501/bin/[pip or conda/~
    • همچنین می‌توان آدرس این برنامه‌ها را به متغیر (Environment Variable) ای به نام PATH اضافه کنیم تا به راحتی و تنها با نوشتن pip  یا conda در دسترس باشند. برای اینکار با وارد کردن دستور export PATH=~/anaconda3_501/bin:$PATH مسیر برنامه‌های نصب شده پایتون درون فولدر anaconda3_501 (این فولدر باید بر اساس کرنل انتخاب شده برای نوت‌بوک انتخاب شود) به متغیر PATH اضافه شده و برنامه‌های pip و conda (و دیگر برنامه‌ها را) تنها با اسمشان قابل اجرا می‌کند.
  • در ادامه برای استفاده آتی ابتدا یک جمله از شکسپیر درون فایلی نوشته شد.
  • سپس در ترمینال برای مثال نصب پکیج توسط ترمینال، پکیج lolcat نصب شد.
  • همچنین با استفاده از lolcat جمله‌ای از شکسپیر که درون فایل ذخیره شده بود چاپ شد.

نوت‌بوک توضیحات

 

آپدیت

با کلون کردن یک ریپازیتوری و اجرای نوت بوک‌های آن، تغییرات روی ریپازیتوری شامل اضافه شدن فایل‌ها، تغییر در آنها و … درون کتابخانه سرویس Azure به صورت خودکار بروز رسانی نمی‌شود. برای اینکار نیاز است تا با استفاده از git خودمان این کتابخانه (که در واقع کلونی از کتابخانه روی GitHub) است را بروز رسانی کنیم.

برای اینکار به این صورت عمل می‌کنیم که ابتدا ترمینال ریپازیتوریمون رو باز می‌کنیم (بالاتر نحوه باز کردنش توضیح داده شده) و سپس با دستور زیر به پوشه library که پوشه‌ای است که فایل‌های کلون شده از گیت‌هاب قرار داده شده اند میرویم:

→ cd library

در ادامه مطابق تصویر با دستور زیر بررسی می‌کنیم آیا تغییری در فایل‌های نوت بوک داده‌شده است یا خیر:

 git status →

همونطور که مشاهده می‌کنید تغییراتی درون فایل بعضی نوت‌بوک‌ها داده شده است که در قسمت Changes not staged for commit ذکر شده‌اند و فایل‌هایی جدید ایجاد شده‌اند که در قسمت Untracked files مشخص شده‌اند. لازم است قبل از بروزرسانی ریپازیتوری این تغییرات (فایل‌هایی که تغییر کرده‌اند) commit شده [در مورد این کار بخوانید] یا فایل‌ها به حالت اول برگردند (تغییرات آنها پاک شود) که اگر تغییرات داده شده روی نوت‌بوک‌ها مهم نیستند بهتر است همینکار را بکنیم. دلیل این‌کار این است که در طی بروز رسانی ریپازیتوری از منبع آن در گیت‌هاب تغییرات داده شده از دست نرفته و حتی بعدا قابل انتقال به دیگر نسخه‌‌های این ریپازیتوری باشند.

در اینجا تغییرات را پاک کرده و فایل نوت‌بوک‌ها را به حالت اول آنها برمی‌گردانیم. برای اینکار مطابق تصویر با دستور زیر تمامی فایل‌های تغییر کرده را به حالت اولشان برمی‌گردانیم:

→ git checkout .

در دستور بالا به دات (. یا نقطه) در انتهای دستور دقت کنید. این نقطه به معنی اعمال checkout -در نظر نگرفتن تغییرات- به همه فایل‌های modified (فایل‌های تغییر کرده یا همان فایل‌هایی که در تصویر قبلی لیست شده بودند) است.

حال همانطور که از اجرای دوباره دستور git status مشخص است، تغییراتی که در فایل‌ نوت‌بوک‌ها داده بودیم حذف شده اند و نام هیچ فایلی در قسمت Changes not staged for commit ذکر نشده است.

در ادامه برای گرفتن آخرین تغییرات از ریپازیتوری گیت‌هاب و اضافه کردن آنها به ریپازیتوری فعلیمون مطابق تصویر از دستور زیر استفاده می‌کنیم:

→ git pull

پس از اجرای این دستور آخرین تغییرات به زیپازیتوری جاری در Azure اضافه می‌شود. همچنین همانطور که مشاهده می‌کنید لیست نوت‌بوک‌های تغییر کرده به همراه میزان تغییر آن‌ها نمایش داده شده است. حال با بازگشت به قسمت library سرویس نوت‌بوک‌های اضافه شده قابل اجرا هستند.

تصاویر دودویی و حد آستانه

به طور کلی ، عکس ها به سه دسته تقسیم می شوند :

  • باینری یا دودویی(Binary)
  • مقیاس خاکستری (Gray scale)
  • رنگی (Color)

تحلیل تصاویر باینری

زمانی که یک تصویر را آنالیز می کنیم یک سری 0 و 1 به دست می آید.
0، پس زمینه را نشان می دهد.
1، پیش زمینه را نشان می دهد.

                                    

کاربرد های تحلیل تصاویر باینری :

  • بررسی قسمت ها
  • در صنعت و تولید
  • پردازش اسناد متنی

 

(عکس سمت راست خوب باینری نشده است( مناسب نبودن مقدار حد آستانه))

 

 کارهایی که می توانیم با باینری کردن تصاویر انجام دهیم :

  • جدا کردن یک شی از پس زمینه
  • متراکم کردن پیکسل های یک شی
  • محاسبه و استخراج ویژگی های یک شی

مثال – تصویر سلول گلبول قرمز

کاربرد: برای مثال برای تسریع در شمارش گلبول‌های قرمز در تصاویر پزشکی می‌توان از پردازش تصویر استفاده کرد.

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

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

عملکرد های مفید

  • آستانه گذاری یک تصویر در مقیاس خاکستری ( gray scale )
  • تعیین کردن حد آستانه مناسب
  • تحلیل اجزای متصل به هم
  • مورفولوژی دودویی ریاضی
  • انواع استخراج ویژگی، ثابت ( محیطی، مرکزی، مداری، …)

آستانه گذاری

تعریف مختصر:

برای تبدیل یک تصویر gray scale یا مقیاس خاکستری به تصویر دودویی باید یک حد آستانه (Threshold) تعیین کنیم و تمام پیکسل‌های دارای مقدار کمتر از حد آستانه را 0 و تمام پیکسل‌های دارای مقدار بیشتر از حد آستانه را 1 (یا 255) کرد.

آستانه گذاری در OpenCV:

همان طور که بیان شد برای تبدیل تصویر gray scale به تصویر دودویی از آستانه گذاری استفاده میکنیم.

در OpenCV نیز این عملیات پیاده سازی شده و اگر مقدار پیکسلی بیشتر از مقدار threshold ( حد آستانه ) باشد، یک مقدار به آن تعلق می گیرد ( ممکن است آن مقدار سفید باشد. )
درغیر آن صورت مقدار دیگری به آن تعلق می گیرد ( ممکن است آن مقدار سیاه باشد. )

تابعی که در OpenCV برای آستانه گذاری  استفاده می شود، cv2.threshold می باشد

  • پارامتر اول آن تصویر منبع (  image ) می باشد که باید یک تصویر در مقیاس خاکستری ( gray-scale ) باشد.
  • پارامتر دوم، مقدار حد آستانه ( threshold ) می باشد، که برای دسته بندی مقادیر پیکسل ها استفاده می شود.
  • پارامتر سوم، بیشترین مقدار ( Max value ) می باشد، که مقداری را نشان می دهد که اگر پیکسلی از مقدار حد آستانه ( threshold value ) بیشتر ( در مواردی ممکن است کمتر ) باشد، Max value به آن مقدار تعلق میگیرد.
  • پارامتر چهارم مربوط به نوع است. OpenCV حالت های مختلفی برای آستانه گذاری تعیین کرده است :
  • cv2.THRESH_BINARY
  • cv2.THRESH_BINARY_INV
  • cv2.THRESH_TRUNC
  • cv2.THRESH_TOZERO
  • cv2.THRESH_TOZERO_INV

 

 مثال آستانه گذاری

آستانه گذاری به روش Ostu 

در آستانه گذاری سراسری ( global thresholding )، یک مقدار دلخواه برای مقدار حد آستانه ( threshold ) استفاده می شود.
سوالی که پیش می آید این است که مقدار انتخاب شده مناسب است یا خیر؟!
پاسخ : متد آزمایش و خطا
اما با فرض یک تصویر biomodel، ( به بیان ساده تر، تصویر biomodel  تصویری است که histogram دو قله ( یا حداکثر ) دارد. )
برای این تصویر ما می توانیم تقریبا حد وسط قله ها را برای مقدار حد آستانه در نظر بگیریم. یعنی کاری که در روش ostu انجام می شود. به صورت خودکار مقدار حد آستانه از تصویر histogram  برای  تصویر biomodel  محاسبه می شود.

مثال: پس زمینه مشکی است و گیلاس سالم روشن است و قسمت های ضرب دیده تیره متوسط است.

نمودار هیستوگرام (Histogram) دو قسمت از گیلاس را نشان می دهد. ( پس زمینه ی مشکی حذف شده است. )

 

 

در پردازش تصویر، (balanced histogram thresholding (BHT یک متد بسیار ساده است (مثل روش ostu ) و متد lterative selection thresholding یک histogram بر مبنای متد آستانه گذاری ( thresholding ) می باشد.
این رویکرد تصویر را به دو کلاس اصلی تقسیم می کند :

  • پس زمینه ( Background )
  • پیش زمینه ( Foreground )

BHT سعی دارد سطح آستانه ( threshold ) را بهینه کند و histogram را به دو کلاس تقسیم می کند.
این متد histogram را می سنجد که بررسی می کند کدام بخش سنگین تر است و وزن را از بخش سنگین تر حذف کند تا روشن تر شود.

آستانه گذاری تطبیقی

در موارد قبلی، ما از مقدار های سراسری ( global ) به عنوان مقدار حد آستانه ( threshold value ) استفاده کردیم. اما در همه ی شرایط ممکن نیست این مقدار مناسب باشد؛ مثلا در مکانی که عکس شرایط روشنایی متفاوتی دارد، در این موارد ما به آستانه گذاری تطبیقی ( Adaptive theesholding ) رجوع می کنیم که الگوریتم، مقدار حد آستانه را برای نواحی کوچک تصویر محاسبه می کند. بنابراین ما به حد آستانه های متفاوتی برای نواحی مختلف همان تصویر می رسیم.
نتیجه: آستانه گذاری تطبیقی ( adaptive thresholding )، نتایج بهتری برای تصاویر با روشنایی متفاوت به نمایش می گذارد.

متد تطبیقی

  • cv2.ADAPTIVE_THRESH_MEAN_C  مقدار حد آستانه ( threshold )، میانگین مقادیر نواحی همسایه می باشد.
  • cv2.ADAPTIVE_THRESH_GAUSSIAN_C  مقدار حد آستانه ( threshold )، جمع وزنی مقادیر نواحی همسایه می باشد.

آستانه گذاری در پایتون و OpenCV

آستانه گذاری در پایتون و numpy

در ابتدا با numpy تصویر را باینری می‌کنیم.

در این کد با بارگذاری کردن تصویر gray scale، به رنگ های کمتر از حد آستانه ( 127 ) را صفر تعلق می گیرد ( سفید ) و به رنگ های بیشتر از حد آستانه ( 127 )  255 تعلق می گیرد.( سیاه )

نکته :
دلیل اینکه از np.copy استفاده می کنیم این است که اگر به این صورت باشد : ( Newimage = image )
در واقع به یک مکان از حافظه دو اشاره گر اشاره می کند که در این صورت عکس اصلی ( اولیه) خراب می شود.

آستانه گذاری در OpenCV

برای اینکار می‌توانیم از تابع threshold در opencv نیز استفاده کنیم

پس از بارگذاری عکس، این بار به کمک تابع threshold که در آن حد آستانه 127 تعیین شده است، به مقادیر کمتر از این مقدار 0 تعلق می گیرد و به مقادیر بیشتر از این مقدار 1 تعلق می گیرد و نوع آن به صورت باینری (سیاه و سفید) تعیین شده است. ( در اینجا ret نشان دهنده ی حد آستانه است. )

پارامترهای مختلف تابع threshold

در این کد پارامتر چهارم (threshold types) بررسی شده است.

  : cv2.THRESH_BINARY

به مقادیر کمتر از حد آستانه (  127 )،  0 تعلق می گیرد ( سفید ) و به مقادیر بیشتر از حد آستانه،  255 تعلق می گیرد ( سیاه ).

 : cv2.THRESH_BINARY_INV

به رنگ های کمتر از حد آستانه (  127 )، 255 تعلق می گیرد ( سیاه ) و به رنگ های  بیشتر از حد آستانه،  0 تعلق می گیرد ( سفید ).(برعکس مورد قبل)

 : cv2.THRESH_TRUNC

مقادیر بیشتر از حد آستانه بریده می شوند. ( 255 بدون استفاده می ماند. )

 : cv2.THRESH_TOZERO

مقادیر بیشتر از حد آستانه تغییر نمی کنند. و به مقادیر کمتر از حد آستانه، 0 تعلق می گیرد.

 : cv2.THRESH_TOZERO_INV

مقادیر کمتر از حد آستانه تغییر نمی کنند.و به مقادیر بیشتر از حد آستانه، 0 تعلق می گیرد.

یک مثال عملی از دودویی کردن تصویر در OpenCV

در ابتدا به کمک فیلتر ها نویزها را برطرف می کنیم زیرا thresholding ها local هستند باعث ایجاد نویز در تصویر می شوند.در آخر از ostu استفاده می کنیم چون ostu حد آستانه را مشخص می کند تصویر بهتری در خروجی نشان می دهد. ( ممکن است در روش های قبل threshold حد آستانه را درست تعیین نکرده باشیم. )

خروجی ها به صورت زیر است :

نتیجه گیری : ostu تصویر بهتری در خروجی نشان می دهد.

 

threshold Binary

: Adaptive thresholding

: Gaussian ostu thresholding 

 : ostu thresholding

 : Adaptive thresholding with Gaussian

دستکاری تصاویر (۵) – فیلترها و کرنل‌ها

در قسمت قبل با عملیات‌های ریاضی ماتریس‌ها آشنا شدیم. در این قسمت می‌خواهیم به نحوه اعمال فیلتر‌های مختلف روی تصاویر با استفاده از عملیات‌های ریاضی روی ماتریس تصاویر بپردازیم.

برای شروع به چند تعریف نیاز داریم:

تصویر

همانطور که می‌دانید تصویر یک ماتریس است که در هر خانه مقادیر رنگ آن خانه (با توجه به سیستم رنگی مورد استفاده) قرارگرفته اند.

کانولوشن (Convolution)

کانولوشن درواقع یک عملگر ریاضی است که بر روی دو تابع اعمال شده و تابع سومی را به صورت انتگرال حاصلضرب دو تابع که یکی از آنها برعکس شده و روی یکدیگر می‌لغزند تعریف می‌کند.

کراس‌کرولیشن (Cross-correlation)

کراس‌کرولیشن میزان شباهت و ارتباط دو دسته اطلاعات را می‌سنجد. این عملگر همانند عملیات کانولوشن بوده با این تفاوت که در این عملیات تابع عبوری برعکس نمی‌شود.

 

در پردازش تصاویر، توابع ما درواقع ماتریس‌های تصاویر هستند. به ماتریس عبوری (اعمال شده) به تصویر کرنل می‌گوییم. همچنین در پردازش تصاویر (در عموم کتابخانه‌‌های مطرح و همینطور Open CV) از عملیات کراس‌کرولیشین استفاده می‌شود.

کرنل

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

 

حال که با تعاریف اولیه مورد نیاز آشنا شدیم به نحوه استفاده و نتیجه آن روی تصاویر می‌پردازیم:

اعمال کرنل روی تصویر

 

در اعمال کرنل روی تصویر نیاز داریم تا با عبور کرنل بر روی تصویر و انجام عملیات کراس‌کرولیشن نتیجه عملیات در خانه‌ای از خانه‌‌های کرنل (که روی تصویر قرار‌گرفته اند) نگاشته شود. برای این‌کار عموما خانه وسط ماتریس کرنل را در نظر می‌گیرند؛ درنتیجه عموم کرنل‌های مورد استفاده ماتریس‌هایی فرد-فرد هستند.

برای عبور کرنل بر روی تصویر می‌توان دو رویه داشت:

  • کانولوشن بدون حاشیه‌گذاری (Valid Padding Convolution)
    عبور کرنل به صورتی که خانه اول ماتریس کرنل (خانه [۰.۰]) بر روی خانه اول ماتریس تصویر بیافتد و کرنل از تصویر خارج نشود.
    این روش باعث از دست رفتن قسمت‌هایی از حاشیه تصویر می‌شود.
نحوه عبور یک ماتریس کرنل بر روی یک ماتریس تصویر و انجام عملیات کراس‌کرولیشن
نحوه عبور کرنل روی ماتریس تصویر و انجام عملیات کراس‌کرولیشن در حالت Valid Padding

 

  • کانولوشن با حاشیه‌گذاری (Same Padding Convolution)
    عبور کرنل به صورتی که خانه مرکز کرنل (خانه‌ای که برای نوشتن مقادیر عملیات در هر مرحله انتخاب شده) بر روی خانه اول ماتریس تصویر بیافتد.
    در این حالت کرنل می‌تواند از تصویر خارج شود که مقادیر خارج از تصویر عموما صفر در نظر گرفته می‌شوند.
نحوه عبور کرنل روی ماتریس تصویر و انجام عملیات کراس‌کرولیشن در حالت Same Padding

توجه کنید که در تصویر بالا حرکت کرنل بیشتر از یک پیکسل است؛ برای همین تصویر خروجی از ورودی کوچکتر شده است.

 

به جز دو روش فوق برای جلوگیری از کوچک شدن تصویر می‌توان از روش‌های تکرار حاشیه تصویر (Edge Value Replication) و یا گسترش آینه‌وار (Mirror Extension) نیز استفاده کرد:

از راست به چپ: گسترش آینه‌وار، تکرار حاشیه تصویر و حاشیه‌گذاری

استفاده از کرنل‌ها

چند مثال از کرنل‌ها با فرض اینکه خانه وسط هر کرنل برای نوشتن مقادیر استفاده شود و همچنین خانه وسط بر روی هر پیکسل قرارگیرد و کرنل در هر مرحله یک پیکسل جابه‌جا شود :

کرنل تطابق

با توجه به کرنل با جابه‌جا شدن روی تصویر تغییری روی تصویر اعمال نمی‌کند چرا که با قرارگیری روی هر پیکسل تنها مقدار همان پیکسل بدون تغییر روی خودش نوشته می‌شود.

کرنل انتقال به چپ

با توجه به کرنل با جابه‌جا شدن روی تصویرو قرار گیری روی هر پیکسل مقدار پیکسل سمت راستش را جایگزین آن می‌کند. درنتیجه تصویر ۱ پیکسل به سمت چپ میرود.

 

 

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

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

فیلتر محوی (Blur Filter)

با عبور یک کرنل Moving Average (کرنل تصویر پایین) که کرنلی با مجموع مقادیر ۱ است و مقدار هر خانه را با میانگین مقدار خانه‌های همسایه‌اش جایگذین می‌کند، می‌توان تصویر را محو کرد.

 

این کرنل تغییرات ناگهانی در رنگ تصویر را ملایم‌تر می‌کند. به تصویر زیر که عبور کرنل بالا بر روی یک ماتریس است دقت کنید:

 

همچنین با افزایش سایز کرنل می‌توان میزان تاری تصویر را افزایش داد:

 

فیلتر تیزی (Sharpen Filter)

کرنل زیر را در نظر بگیرید:

می‌توان این کرنل را به صورت زیر باز کرد:

ماتریس سمت راست همان کرنل مربوط به فیلتر محوی (Blur) است که تصویر را بدون جزئیات تولید می‌کند؛ با تفریق این ماتریس از خود تصویر (ماتریس وسط) جزئیات تصویر اصلی حاصل می‌شود؛ حال با اضافه کردن این ماتریس به خود تصویر می‌توان جزئیات تصویر را به آن افزود و تصویری با جزئیات نمایان‌تر شده تولید کرد.

نتیجه حاصل از جدا کردن جزئیات و اضافه کردن آن به عکس را می‌توان به ترتیب در سطر‌های تصویر زیر مشاهده کرد:

درنتیجه فیلتر تیزی (Sharpen Filter) به صورت زیر است:

 

مقدمات OpenCV، خواندن و نمایش تصاویر، فضاهای رنگی

برای استفاده از پکیج opencv در برنامه خود باید عبارت  “import cv2” را در اول برنامه نوشته شود و همچنین برای استفاده از کتابخانه numpy دربرنامه خود باید عبارت  “import numpy as np” نوشته شود برای اینکه کلمه numpy کمی طولانی میباشد از کلمه np به جای آن استفاده میشود که کوتاه تر است . که با اضافه کردن as np  این کار صورت میگیرد.

برای اینکه از پکیج opencv استفاده شود باید cv2. نوشته شود و بعد آن توابعی را که از آن کتابخانه احتیاج داریم را بنویسیم .

برای اینکه از پکیج opencv استفاده شود باید cv2. نوشته شود و بعد آن توابعی را که از آن کتابخانه احتیاج داریم را بنویسیم .

برای load (بارگذاری)  یک عکس در برنامه باید از عبارت ()cv2.imread  استفاده کنیم که در پکیج opencv قراردارد.

در آرگومان اول باید آدرس کامل آن عکس که میخواهید بارگذاری شود را بدهید و دقت کنید که باید فرمت عکس هم نوشته شود که در مثال بالا عکس دارای فرمت jpg میباشد.

آرگومان دوم آن یک flag میباشد که راهی که عکس باید خوانده شود را تعیین میکند.

  • Cv2.IMREAD_COLOR : عکس رنگی را بارگذاری میکند.از شفافیت عکس غفلت خواهد شد. این یک flag پیش فرض میباشد.
  • Cv2.IMREAD_GRAYSCALE : عکس سیاه سفید را بارگذاری میکند.
  • Cv2.IMREAD_UNCHANGED :عکس را به صورتی که کانال alpha را داراست بارگذاری میکند.

میتوان به جای این سه flag از پاس دادن عدد 1 و 0 و 1- به ترتیب استفاده کرد.

برای مثال کد زیر را ببینید:

برای نمایش یک عکس در یک پنجره باید ازتابع ()cv2.imshow استفاده کرد که این پنجره به صورت اتوماتیک  با اندازه عکس متناسب میشود برای مثال:

آرگومان اول آن عنوانی است که در بالای پنجره ای که قرار است عکس را نمایش بدهد نشان داده میشود که این عنوان را باید داخل ‘  ‘ و یا “  “ بنویسید.

آرگومان دوم آن نام عکسی است که میخواهیم نمایش داده شود.

عبارت “cv2.waitKey”  یک تابع اجباری است که به ما اجازه میدهد تا زمانی که پنجره عکس باز است اطلاعات را دریافت کنیم.

آرگومان این تابع زمانی بر حسب میلی ثانیه میباشد که این تابع تا زمانی که تعیین شده منتظر میماند البته اگر شما تا آن زمان کلیدی را فشار دهید پنجره بسته خواهد شد.

اگر به این تابع 0 پاس دهید این تابع تا زمانی که کلیدی فشرده شود منتظر میماند.

تابع “cv2.destroyAllWindows” تمام پنجره های ساخته شده را خراب میکند که اگر یادتان برورد این عبارت را بنویسید برنامه شما هنگ میکند.

اگر شما بخواهید فقط یک پنجره مشخص را خراب کنید باید از تابع “cv2.destroyWindow”  استفاده کنید .

برای ذخیره کردن عکس در کامپیوتر خود باید ازتابع ()cv2.imwrite استفاده کرد که آرگومان اول آن نام فایل و آرگومان دوم آن عکسی است که میخواهید ذخیره شود برای مثال با نوشتن عبارت “cv2.imwrite(‘output.jpg’, input)” عکس input با اسم output و با فرمت jpg در کامپیوتر ذخیره میشود.

اگر با اجرای این خط کلمه true  چاپ شد یعنی این عکس با موفقیت ذخیره شده.

برای فهمیدن سایزعکس باید از “print (input.shape)” استفاده کنیم که عبارت print هر چه که در پرانتز از آن خواسته شده باشد را چاپ میکند که چون ما سایز عکس خود را میخواهیم باید input.shape را به آن پاس بدهیم. برای مثال این عبارت را چاپ میکند (600, 800, 3) که پارامتر اول آن ارتفاع عکس بر حسب پیکسل و دومی عرض عکس بر حسب پیکسل و سومی کانال های عکس میباشد که در اینجا کانال های عکس 3 میباشد به این معنی است که عکس رنگی میباشد یعنی سه کانال RGB را داراست و اگر کانال سوم 0 بود یعنی عکس سفید سیاه (grayscale) میباشد به صورت زیر:

 

تغییر فضای رنگی

در opencv بیشتر از 150 متد تبدیل فضای رنگی وجود دارد.

برای تبدیل کردن فضای رنگی از تابع “cv2.cvtcolor(input_image , flag)” استفاده میشود که flag نوع تبدیل را تعیین میکند.

برای تبدیل BGR به Gray از  فلگ “cv2.COLOR_BGR2GRAY”  استفاده میشود و همچنین برای تبدیل Gray به BGR از فلگ “cv2.COLOR_GRAY2BGR”  استفاده میشود.

 

یک فضای رنگی مفید دیگر HSV میباشد.

برای HSV رنج Hue برابر [0,179] و رنج  saturation برابر [0,255] و رنج Value برابر [0,255] میباشد.

برای تبدیل BGR به HSV از فلگ  “cv2.COLOR_BGR2HSV”  استفاده میشود.

با این تبدیل ما میتوانیم یک شی رنگی استخراج کنیم.در HSV فهمیدن یک رنگ خیلی آسون تر از فضای رنگی RGB میباشد.

تصویر زیر یک تصویر HSV میباشد.

تصویر زیر کانال Hue میباشد.

تصویر زیر کانال saturation میباشد.

تصویر زیر کانال Value میباشد.

دانلود و نصب آناکوندا برای کار با پایتون

به آدرس https://www.continuum.io/downloads  بروید.

  1. نسخه‌ای که میخواهیم دانلود و نصب کنیم نسخه بالاتر یا برابر با Python 3.5 version است. لطفا ورژن پایین تر دانلود نکنید.
  2. برای دانلود نسخه ی مناسب, باید بدانید ویندوزتان 32 بیتی یا 64 بیتی است. اگر نمیدانید این لینک را مطالعه کنید:
    https://support.microsoft.com/en-us/help/15056/windows-7-32-64-bit-faq
  3. اگر از سیستم عامل ویندوز استفاده نمیکنید, به اینجانب  پیام بدهید و راهنمای نصب سیستم عامل  (Max، Linux) را دریافت کنید.

راهنمای دانلود برای ویندوز:

اگر سیستم عامل 32 بیتی دارید, روی لیک 32 بیتی و اگر 64 بیتی دارید روی لینک مربوطه کلیک کنید. (مطابق تصویر زیر)

راهنمای نصب:

  • روی فایل exe کلیک نمایید
  • مراحل را پیش بروید تا به تصویر زیر برسید؛ مطابق تصویر هر دو گزینه را تیک بزنید

توجه: (خود Anaconda توصیه کرده به علت احتمال تداخل PATH با نسخه های دیگر پایتون روی سیستمتان این گزینه را تیک نزنید. با این حال اگر دفعه اولی است که پایتون را نصب میکنید, برای سادگی توصیه میکنم این گزینه را تیک بزنید.)

– نصب در حود 15 دقیقه طول میکشد؛ در انتها روی دکمه ی finish کلیک نمایید.

 

راهنمای اجرا

راهنمای اجرای spyder :

از منوی start

آیکن مربوط به Anaconda Navigator

روی دکمه ی آبی رنگ (Launch) اجرای spyder کلیک کنید.

در نهایت محیط زیر را مشاهده خواهید کرد:

در سمت راست (2) کنسول و در سمت چپ (1) محیط کد نویسی را مشاهده میکنید که در کلاس تشریح شد.

 

راهنمای اجرای نوت‌بوکهای jupyter:

پوشه‌ی حاوی فایلهای .ipynb را که از گیت‌هاب درس دانلود کرده اید به مسیر دلخواه کپی کنید.

به این مسیر رفته و shift + کلیک راست کنید.

گزینه‌ی Open command window here را کلیک کنید.

در پنجره‌ی باز شده دستور jupyter notebook را تایپ کنید.

حال باید مرورگر شما باز شده و نوت‌بوکهای شما نشان داده شوند.

آموزش نصب OpenCV و شروع

گام اول – دانلود و نصب Anaconda Python Package

  • به آدرس  https://www.continuum.io/downloads  بروید.
  • نسخه مورد نظر را انتخاب کنید.توصیه میکنم برای این کلاس نسخه پایتون 3 به بالا را دانلود و نصب کنید.
  • آزمایش نصب – به windows command prompt یا CMD ویندوز بروید.
  • دستور زیر را تایپ کنید

jupyter notebook

برای اطلاعات بیشتر در مورد گام اول این پست را بخوانید.

گام دوم – نصب و اجرای OpenCV

  • به windows command prompt یا CMD ویندوز بروید.
  • دستورات زیر را به ترتیب وارد کنید ( باید به اینترنت متصل باشید.)

 

حال باید تمام سلولهای نوت‌بوک

00-Beginning.ipynb

بدون خطا اجرا شود. (برای اجرای نوت‌بوکها به قسمت راهنمای اجرای نوت‌بوکهای jupyter مراجعه کنید.