مقدمه : برای پروژه ی احراز هویت کاربر توسط کارت ملی هوشمند , تعدادی داده (تصویر کارت ملی) جمع آوری شد که پردازش برخی از این داده ها بخاطر زاویه و مقیاسی که داشتند امکان پذیر نبود به این خاطر تصاویر به صورت دستی توسط برنامه ی Camscanner تراز و سپس برش داده شدند.برنامه ی تراز کردن کارت ملی برای انجام خودکار این فرایند نوشته شده است.
…نویسنده: المیرا قربانی
اعضای گروه : عاطفه ولی پور – المیرا قربانی
مقدمه
برای اکثر افراد پیش آمده است که خواستار ترجمه ی یک متن باشند یا معنی یک کلمه را بخواهند . ساده ترین راه برای آن ها استفاده از گوگل ترنسلیت می باشد. اما تا چه اندازه میتوانیم مطمئن باشیم که گوگل ترنسلیت ، ترجمه ی صحیحی به ما ارائه میکند؟ گوگل ترنسلیت یک ماشین هوشمند است که برای ترجمه ی کلمات عمومی در زبان ها ی مختلف دنیا مورد استفاده قرار میگیرد. …
Recurrent Neural Networks
جلسات پیش با RNN ها آشنا شدیم و با ساختن یک language مدل توانستیم مدلی طراحی کنیم که یک کلمه را دریافت کند و کلمات بعدی را حدس بزند.
در ادامه به بررسی شبکه های LSTM و GRU میپردازیم.
یادآوری:
شبکه ی RNNشامل تعدادی Hidden نورون است که این Hidden نورون ها تکرار میشوند به طوری که انگار در طول زمان باز و تکرار میشوند.
Notations:
X1,X2,….Xn ورودی های شبکه هستند که به مرور زمان به شبکه میدهیم به طور مثال اگر بخواهیم کلمه کلمه به شبکه بدهیم ابتدا X1 , … الی آخر پشت هم می آیند. این ورودی ها شامل یک سری وزن هستند که با Wax نمایش میدهیم و یک سری وزن که از state مرحله ی قبلی ورودی میگیرد که همان حافظه ی ما و خروجی را تشکیل میداد .
a : خلاصه ای از ورودی های قبلی است که دار ی حافظه است و براسا ورودی هی قبلی و ورودی فعلی تصمبم میگیرد.
Simple syntax RNN:
برای ساده تر شدن از این پس تنها یک بردار وزن برای X و a خواهیم داشت که در کنار هم این دو Concatمیشوند.
در نهایت :
مشکل RNNها :
استفاده از این شبکه برای جملات کوتاه مشکلی ایجاد نمی کند.اما اگر جمله ی ما ادامه پیدا کند این شبکه نمیتواند به صورت Long Term جمله را حفظ کند و اصطلاحا مشکل Wanishing Gradiant به وجود میاید .
RNN Unit:
مطابق شکل یک وزنی داریم که در concat شده ی ورودی و stateقبلی ضرب میشود و به activation function داده میشوند که y hatما را تشکیل میدهد.
GRU:
برای حل مشکل Wanishing Gradiant برای جملاتی مثل :
The cat, which already ate …, was full.
برای اینکه بدانیم در جای خالی با توجه به ضمیر چه چیزی به کار ببریم نیاز داریم حافظه ی طولانی تری داشته باشیم .
در gru به state که داریم c میگوییم که مخفف cell است .به عبارتی cهمان <a<t قبلی است .
بجای مشخص شدن stateجاری یک stateپیشنهادی داریم~C که کاندیدی برای stateجاری است که هنوز به صورت قطعی قرار نیست stateجاری باشد.
ورودی جاری و state قبلی در هم concatشده و در وزن Wc ضرب میشوند.
GRU Simplified:
تفاوت با RNNساده :
یک سری گیت اضافه شده برای بررسی پذیرش کاندید state
برای بررسی آپدیت گیت یک activation function sigmoid داریم .(0:بروز نکن ,1:بروز کن)
رای تعیین <C<t اگر Г آپدیت برابر با 1 بود بروز رسانی صورت میگیرد و اگر 0 باشد , کاندید state را نمیپذیرد و stateمرحله قبل را در نظر میگیرد.
Full Gru:
در Full GRU یک گیت جدید اضافه میکنیم که بررسی میکند stateمرحله قبل چقدر به context جاری مربوط میشود.
activation function گیت جدید یک sigmoid است که مقدار 0 یا 1 برمیگرداند و تصمیم میگیرد حافظه قبلی چقدر به ورودی جاری مربوط میشود و براساس ورودی میتواند تصمیم بگیرد ,گیت حافظه را برای خروجی دادن این state در نظر بگیرد یا خیر.
LSTM:
شبکههای LSTM که خلاصه شده عبارت “Long Short Term Memory” هستند، نوع خاصی از شبکههای عصبی بازگشتی هستند که توانائی یادگیری وابستگیهای بلندمدت را دارند و مشکل wanishing gradiant حل کردند.این شبکهها برای اولین بار توسط Hochreiter و Schmidhuber در سال ۱۹۹۷ معرفی شدند.
در حقیقت هدف از طراحی شبکههای LSTM، حل کردن مشکل وابستگی بلندمدت بود. به این نکته مهم توجه کنید که به یاد سپاری اطلاعات برای بازههای زمانی بلند مدت، رفتار پیشفرض و عادی شبکههای LSTM است و ساختار آنها به صورتی است که اطلاعات خیلی دور را به خوبی یاد میگیرند که این ویژگی در ساختار آنها نهفته است.
مقایسه بین LSTM و GRU
در lstm گیت Γr نداریم این گیت مشخص میکند چه میزان از حافظه را دخیل کند اگر 0 باشد به طور کلی اثر حافظه را از بین میبرد,میتوان قرار داد اما ضروری نیست.
lstmدر مقایسه با gru تعداد گیت های بیشتری دارد. در lstm برای فراموش کردن هم یک گیت اضافه شده و مشخص میکند برای برای بازنویسی< C<t چه میزان کاندید state را تاثیر بدهیم به عبارتی چقدر بخاطر بسپرد و چقدر فراموش کند.
Bidirectional RNN:
ماژول تکرار در RNN دو طرفه می تواند RNN معمولی، LSTM یا GRU باشد. ساختار و اتصالات یک RNN دو طرفه در شکل زیر نشان داده شده است. دو نوع ارتباط وجود دارد که یکی از آن ها در زمان پیش می رود که به ما کمک می کند تا از بازنمایی های قبلی یاد بگیریم و دیگر به عقب بازگردیم، که به ما در بازنمایی های آینده کمک می کند. مثلا ما دیتای آفلاین داریم مثل ویدیو یا یک متن
Deep Rnn:
مطابق شکل state مرحله قبل که رسیده توی کروشه 1 در نظر گرفته شده یعنی برای لایه اول و برای هر لایه عدد کروشه متفاوت است .در هر مرحله state ایجاد میکنند و به مرحله ی بعدی میروند .میتوانیم این state را به یک softmax و یا sigmiodوصل کنیم .این state ها زمانی که شروع میشوند با 0 مقدار دهی میشوند ,لایه ها روی هم stack شده و یک شبکه دیپ ایجاد میکنند .y های خروجی قرار است برای ما چیزی حساب کنند در طول زمان X دریافت کرده اند و یک state خود yهم چند لایه است ,میتوانیم مستقل از دیپ بودن قبلش خروجی لایه را به یک شبکه cnnبدهیم :
استفاده از خروجی y :
تولید متن با شبکه بازگشتی LSTM در Keras
در این مثال به پیاده سازی یک شبکه lstm میپردازیم که بر روی کتاب فیلسوف آلمانی نیچه به صورت
character-level پیاده سازی شده.
ابتدا مجموعه داده را بارگذاری میکنیم:
1 2 3 4 5 6 7 8 |
import keras import numpy as np path = keras.utils.get_file( 'nietzsche.txt', origin='https://s3.amazonaws.com/text-datasets/nietzsche.txt') text = open(path).read().lower() print('Corpus length:', len(text)) |
توسط maxlen مشخص میکنیم به شبکه چند حرف چند حرف بدیم . در این مثال طول کلمات 60 تایی است و ممکن است این 60 تا وسط کلمه تمام شود یا بیشنر از طول رشته ی ورودی باشد.
در for زیر کاراکتر 61 ام به عنوان label در نظر گرفته میشود.
توسط setنیز تعداد کاراکتر های یونیک را مشخص میکنیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# Length of extracted character sequences maxlen = 60 # We sample a new sequence every `step` characters step = 3 # This holds our extracted sequences sentences = [] # This holds the targets (the follow-up characters) next_chars = [] for i in range(0, len(text) - maxlen, step): sentences.append(text[i: i + maxlen]) next_chars.append(text[i + maxlen]) print('Number of sequences:', len(sentences)) # List of unique characters in the corpus chars = sorted(list(set(text))) print('Unique characters:', len(chars)) # Dictionary mapping unique characters to their index in `chars` char_indices = dict((char, chars.index(char)) for char in chars) # Next, one-hot encode the characters into binary arrays. print('Vectorization...') x = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool) y = np.zeros((len(sentences), len(chars)), dtype=np.bool) for i, sentence in enumerate(sentences): for t, char in enumerate(sentence): x[i, t, char_indices[char]] = 1 y[i, char_indices[next_chars[i]]] = 1 |
ایجاد شبکه (Building the network)
1 2 3 4 5 6 7 |
from keras import layers model = keras.models.Sequential() model.add(layers.LSTM(128, input_shape=(maxlen, len(chars)))) model.add(layers.Dense(len(chars), activation='softmax')) optimizer = keras.optimizers.RMSprop(lr=0.01) model.compile(loss='categorical_crossentropy', optimizer=optimizer) |
این کدی است که ما برای توزیع احتمالی اصلی خارج از مدل استفاده می کنیم و یک شاخص کاراکتر را از آن به دست می آوریم. میدانیم predict دقیقا 0 و 1 نیست .در این جا نقش temperature این است که براساس احتمالات رندم انتخاب کند.هر چقدر temperature بیشتر باشد احتمال نفر اول را بیشتر نشان میدهد.
1 2 3 4 5 6 7 |
def sample(preds, temperature=1.0): preds = np.asarray(preds).astype('float64') preds = np.log(preds) / temperature exp_preds = np.exp(preds) preds = exp_preds / np.sum(exp_preds) probas = np.random.multinomial(1, preds, 1) return np.argmax(probas) |
و در نهایت ایجاد متن
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import random import sys for epoch in range(1, 60): print('epoch', epoch) # Fit the model for 1 epoch on the available training data model.fit(x, y, batch_size=128, epochs=1) # Select a text seed at random start_index = random.randint(0, len(text) - maxlen - 1) generated_text = text[start_index: start_index + maxlen] print('--- Generating with seed: "' + generated_text + '"') for temperature in [0.2, 0.5, 1.0, 1.2]: print('------ temperature:', temperature) sys.stdout.write(generated_text) # We generate 400 characters for i in range(400): sampled = np.zeros((1, maxlen, len(chars))) for t, char in enumerate(generated_text): sampled[0, t, char_indices[char]] = 1. preds = model.predict(sampled, verbose=0)[0] next_index = sample(preds, temperature) next_char = chars[next_index] generated_text += next_char generated_text = generated_text[1:] sys.stdout.write(next_char) sys.stdout.flush() print() |
نمونه خروجی متن ایجاد شده :
1 2 3 |
self in the self in the self in the self in the self in the same and perhaps of the man of make one consupertaon of the whole of the religion and continter the are my, and here of a free in the gan the self-contition of the belief and the pruble of the religious fact, the most the perhaps and and perhaps the the different to the complice of the are the present the gard every provioning of the german destranged us the one of the probleass of the soul in the |
محیط گوگل کولب امکان استفاده از GPU را به صورت رایگان میدهد و امکان نصب و کار با پکیج های مختلف زبان پایتون و فریم ورکهای مطرح یادگیری عمیق همانند Tensorflow, Keras, Pytorch,Fast.ai را فراهم میکند.
مراحل ایجاد یک نوت بوک
ابتدا مطمئن شوید که به حساب کاربری gmail خود متصل هستید . اگر حساب کاربری gmail ندارید اینجا را کلیک کنید.
* توجه :در تمام طول کار، باید ویپیان یا فیلترشکن روشن باشد.
از اینجا وارد محیط google drive شوید .
روش اول :
در محیط google drive یک پوشه ایجاد کنید :
پوشه ای که ایجاد کرده ایم را انتخاب میکنیم
با کیلک راست بر روی My drive فایل های نوت بوک وdataset.py [Upload files] و
Data_hoda_full را آپلود میکنیم.
با کلیک راست بر روی نوت بوک مانند شکل زیر،نوت بوک را با colaboratoryباز میکنیم :
بعد از باز شدن نوت بوک GPU را فعال میکنیم:
یک cell جدید ایجاد میکنیم :
کد زیر را در cell وارد میکنیم :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
!apt-get install -y -qq software-properties-common python-software-properties module-init-tools !add-apt-repository -y ppa:alessandro-strada/ppa 2>&1 > /dev/null !apt-get update -qq 2>&1 > /dev/null !apt-get -y install -qq google-drive-ocamlfuse fuse from google.colab import auth auth.authenticate_user() from oauth2client.client import GoogleCredentials creds = GoogleCredentials.get_application_default() import getpass !google-drive-ocamlfuse -headless -id={creds.client_id} -secret={creds.client_secret} < /dev/null 2>&1 | grep URL vcode = getpass.getpass() !echo {vcode} | google-drive-ocamlfuse -headless -id={creds.client_id} -secret={creds.client_secret} !mkdir -p drive !google-drive-ocamlfuse drive print('Files in Drive:') !ls drive/ |
بعد از run شدن cell دو مرحله تایید اعتبار داریم ، در هر مرحله بر رو لینک کلیک کنید و کد رو در تکست باکس وارد کنید :
کدهای زیر را به نوت بوک اضافه میکنیم تا فایل ها از گوگل درایو به محیط colab اضافه شوند :
add cell+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
from google.colab import auth from googleapiclient.discovery import build import io , requests, os import sys auth.authenticate_user() from googleapiclient.discovery import build drive_service = build('drive', 'v3') def get_parent_folder(folder_name): page_token = None folder_array = [] query = "name='%s' and mimeType='application/vnd.google-apps.folder'" % folder_name while True: response = drive_service.files().list(q=query, spaces='drive', fields='nextPageToken, files(id, name)', pageToken=page_token).execute() for file in response.get('files', []): # Process change #print (file.get('name'), file.get('id')) folder_array.append({"name" : file.get('name'), "id" : file.get('id')}) page_token = response.get('nextPageToken', None) if page_token is None: break return folder_array def get_files_from_parent(parent_id): page_token = None folder_array = dict() query = "'%s' in parents" % parent_id while True: response = drive_service.files().list(q=query, spaces='drive', fields='nextPageToken, files(id, name)', pageToken=page_token).execute() for file in response.get('files', []): # Process change #print (file.get('name'), file.get('id')) folder_array.update({file.get('name'):file.get('id')}) page_token = response.get('nextPageToken', None) if page_token is None: break return folder_array def get_file_buffer(file_id, verbose=0): from googleapiclient.http import MediaIoBaseDownload request = drive_service.files().get_media(fileId=file_id) downloaded = io.BytesIO() downloader = MediaIoBaseDownload(downloaded, request) done = False while done is False: # _ is a placeholder for a progress object that we ignore. # (Our file is small, so we skip reporting progress.) progress, done = downloader.next_chunk() if verbose: sys.stdout.flush() sys.stdout.write('\r') percentage_done = progress.resumable_progress * 100/progress.total_size sys.stdout.write("[%-100s] %d%%" % ('='*int(percentage_done), int(percentage_done))) downloaded.seek(0) return downloaded |
add cell +
1 2 3 4 5 6 7 8 9 10 11 12 |
parent_folder = get_parent_folder('google colab') print(parent_folder) parent_folder[0]["id"] input_file_meta = get_files_from_parent(parent_folder[0]["id"]) print(input_file_meta) for file, id in input_file_meta.items(): downloaded = get_file_buffer(id, verbose=1) dest_file = os.path.join('/content/datalab/', file) print("\nprocessing %s data" % file) with open(dest_file, "wb") as out: out.write(downloaded.read()) print("Done %s" % dest_file) |
حالا یک دایرکتوری برای دیتاست ایجاد میکنیم :
add cell+
1 |
!mkdir dataset |
دیتاست هدی را به پوشه ی دیتاست اضافه میکنیم :
add cell+
1 |
!mv Data_hoda_full.mat !mv Data_hoda_full.mat \dataset |
روش دوم ایجاد نوت بوک :
وارد سایت colab.research.google.com میشویم :
NEW NOTEBOOK >>> NEW PYTHON3 NOTEBOOK
سپس از منو file نوت بوک جدید را آپلود میکنیم :
یک cell جدید ایجاد میکنیم سپس دستور زیر را وارد میکنیم :
1 |
!mkdir dataset |
فایل و پوشه ی دیتاست را آپلود میکنیم :
add cell+
1 2 3 |
from google.colab import files src = list(files.upload().values())[0] open('\dataset','wb').write(src) |
دیتاست هدی را به پوشه ی دیتاست اضافه میکنیم :
add cell+
1 |
!mv Data_hoda_full.mat !mv Data_hoda_full.mat \dataset |
روش سوم :
ابتدا ریپازیتوری خود را با دیتاست موردنظر و دلخواه روی گیت هاب ایجاد کنید
یا در صورت وجود ریپازیتوری آدرس آن را به صورت زیر یافته و با دستور زیر آن را در جوپیتر ران کنید
*توجه داشته باشید که فرمت دستورات لینوکسی میباشد.
1 |
! git clone --recursive [GITHUB LINK REPO] |
مثال :
1 |
! git clone --recursive https://github.com/Alireza-Akhavan/class.vision.git |
بعد از اتمام موفقیت آمیز بودن عملیات کلون از ریپازیتوری گیت هاب خروجی زیر را مشاهده میکنید:
در ادامه مسیر جاری را پیدا کرده و فایل های دریافت شده از مخزن را در مسیر دلخواه ( بعنوان مثال /content ) منتقل کنید:
در نهایت کد های اجرایی مورد نظر را در یک سلول جدید وارد کرده و برنامه را اجرا کنید:
بروزرسانی : 1397/11/06
تبدیلات همگن (Affine Transform)
انتقال (Translation) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import cv2 import numpy as np image = cv2.imread('images/input.jpg') # Store height and width of the image height, width = image.shape[:2] quarter_height, quarter_width = height/4, width/4 # | 1 0 Tx | # T = | 0 1 Ty | # T is our translation matrix T = np.float32([[1, 0, quarter_width], [0, 1,quarter_height]]) # We use warpAffine to transform the image using the matrix, T img_translation = cv2.warpAffine(image, T, (width, height)) cv2.imshow('Translation', img_translation) cv2.waitKey() cv2.destroyAllWindows() |
برای پیاده سازی این تبدیلات از cv2.warpAffine استفاده میکینم.
به طور مثال در کد زیر :
پس از خواندن عکس و دریافت عرض و طول تصویر:
1 2 3 |
cv2.imread('images/input.jpg') height, width = image.shape[:2] |
یک نسبت دلخواه برای انتقال طول و عرض تصویر در نظر گرفتیم :
1 |
quarter_height, quarter_width = height/4, width/4 |
با استفاده از ضرب ماتریس انتقال در مختصات تصویر ،تصویر انتقال پیدا میکند :
1 2 3 |
T = np.float32([[1, 0, quarter_width], [0, 1, quarter_height]]) # پارامتر اول ، سطر اول # پارامتر دوم ، سطر دوم |
از warpAffine برای تبدیل عکس استفاده میکنیم که ورودی های آن به صورت زیر است :
1 2 |
#image, transform matris , (width, height)=>output image cv2.warpAffine(image, T, (width, height)) |
چرخاندن (Rotations) :
*یادآوری
ماتریس دوران:
دوران در opencv
1 2 3 4 |
cv2.getRotationMatrix2D(rotation_center_x, rotation_center_y, angle of rotation, scale) # rotation_center_x : مرکز چرخش نسبت به عرض # rotation_center_y : مرکز چرخش نسبت به ارتفاع # angle of rotation : زوایه چرخش |
1 2 3 4 5 6 7 8 9 10 11 |
import cv2 import numpy as np image = cv2.imread('images/input.jpg') height, width = image.shape[:2] # Divide by two to rototate the image around its centre rotation_matrix = cv2.getRotationMatrix2D((width/2, height/2), 20, .5) print(rotation_matrix) rotated_image = cv2.warpAffine(image, rotation_matrix, (width, height)) cv2.imshow('Rotated Image', rotated_image) cv2.waitKey() cv2.destroyAllWindows() |
- از نقص های این روش میتوان به ایجاد فضاهای سیاه اطراف تصویر اشاره کرد که در ادامه فضاهای سیاه ایجاد شده اطراف تصویر را با کراپ از بین میبریم.
روشی دیگر برای دوران :
ترانهاده ماتریس
ماتریس ترانهاده با تغییر جای سطر ها با ستون ها باعث چرخش تصویر میشود و فضای سیاه اطراف تصویر ایجاد نمی کند .
1 2 3 4 5 6 |
#Other Option to Rotate img = cv2.imread('images/input.jpg') rotated_image = cv2.transpose(img) cv2.imshow('Rotated Image - Method 2', rotated_image) cv2.waitKey() cv2.destroyAllWindows() |
flip تصویر
تصویر را در جهت افق و خط عمود آینه می کند.
1 2 3 4 5 6 |
# Let's now to a horizontal flip. flipped = cv2.flip(image, 1) cv2.imshow('original', image) cv2.imshow('Horizontal Flip', flipped) cv2.waitKey() cv2.destroyAllWindows() |
پارامتر دوم :
1 |
cv2.flip(image, 1) |
صفر یا false عکس را حول محور x ها قرینه میکند.
یک یا True عکس را حول محور y ها قرینه میکند.
تغییر اندازه (scaling, resizing) و درونیابی (interpolations)
1 2 3 4 5 |
cv2.resize(image, dsize(output image size), x scale, y scale, interpolation) # image : دریافت عکس ورودی # dsize(output image size) : اندازه تصویر خروجی # x scale, y scale : تغییر مقیاس در راستای x و y # interpolation : روش درون یابی |
- fx و fy پارامتر های نام دار هستند میتوان آنها را به تابع پاس نداد.
روش های درون یابی :
- Bilinear Interpolation (درج وابسته به ۴ پیکسل ۴ طرف)
- Bicubic interpolation (درج وابسته به ۴ پیکسل ۴ طرف به علاوه ۴ پیکسل اریب)
- Nearest Neighbor (نزدیکترین همسایه)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import cv2 import numpy as np # load our input image image = cv2.imread('images/input.jpg') cv2.imshow('Original Image', image) cv2.waitKey() # bilinear interpolation (used by default) # Let's make our image 3/4 of it's original size image_scaled = cv2.resize(image, None, fx=0.75, fy=0.75) cv2.imshow('Scaling - Linear Interpolation', image_scaled) cv2.waitKey() # bicubic interpolation over 4x4 pixel neighborhood # Let's double the size of our image img_scaled = cv2.resize(image, None, fx=2, fy=2, interpolation = cv2.INTER_CUBIC) cv2.imshow('Scaling - Cubic Interpolation', img_scaled) cv2.waitKey() # nearest-neighbor interpolation # Let's skew the re-sizing by setting exact dimensions img_scaled = cv2.resize(image, (900, 400), interpolation = cv2.INTER_AREA) cv2.imshow('Scaling - Skewed Size', img_scaled) cv2.waitKey() cv2.destroyAllWindows() |
استفاده از ماتریس تبدیل
جهت هایی را که میخواهیم scale شوند را در قطر ماتریس قرار میدهیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import cv2 import numpy as np image = cv2.imread('images/input.jpg') # Store height and width of the image height, width = image.shape[:2] # | Sx 0 0 | # T = | 0 Sy 0 | # T is our translation matrix T = np.float32([[0.5, 0, 0], [0, 0.5,0]]) # We use warpAffine to transform the image using the matrix, T img_translation = cv2.warpAffine(image, T, (width, height)) cv2.imshow('Translation', img_translation) cv2.waitKey() cv2.destroyAllWindows() |
معایب :
- مشکل سیاهی تصویر را دارد.
- عکس بعد از اعمال interpolations باید crop شود .
Image Pyramids
در بعضی موارد، ما باید با تصاویری با وضوح مختلف تصویر مشابه کار کنیم. به عنوان مثال، هنگام جستجو برای چیزی در یک تصویر، مانند چهره، ما مطمئن نیستیم که کدام اندازه از شئ در تصویر وجود دارد.
1 2 3 4 5 6 7 8 9 |
import cv2 image = cv2.imread('images/input.jpg') smaller = cv2.pyrDown(image) larger = cv2.pyrUp(smaller) cv2.imshow('Original', image ) cv2.imshow('Smaller ', smaller ) cv2.imshow('Larger ', larger ) cv2.waitKey(0) cv2.destroyAllWindows() |
در این روش عکس را به صورت پلکانی به سایز های مختلف می بریم :
1 2 |
smaller = cv2.pyrDown(image) larger = cv2.pyrUp(smaller) |
کاربرد: آموزش به هوش مصنوعی برای تشخیص اشیاء
Cropping
Opencv تابع مشخص برای کراپ کردن ندارد.
روش های جایگزین :
یکی از روش های کراپ کردن slicing است که با دادن بازه ی دقیقی از x ,y (برای ساده تر شدن عکس را بصورت دو بعدی و سیاه سفید تصور میکنیم)همان بازه ی مشخص شده را کراپ می کنیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import cv2 import numpy as np image = cv2.imread('images/input.jpg') height, width = image.shape[:2] # Let's get the starting pixel coordiantes (top left of cropping rectangle) start_row, start_col = int(height * .25), int(width * .25) # Let's get the ending pixel coordinates (bottom right) end_row, end_col = int(height * .75), int(width * .75) # Simply use indexing to crop out the rectangle we desire cropped = image[100:300 , 200:800] cv2.imshow("Original Image", image) cv2.imshow("Cropped Image", cropped) cv2.waitKey(0) cv2.destroyAllWindows() |
نکات :
مختصات شروع و پایان حتما باید اعداد صحیح باشند.
در بازه نویسی به صورت [ x1 : x2 , y1:y2 ] :
x1 شامل بازه میشود اما x2 نوشته نمیشود .
روش دیگر اسلایس کردن ماتریس ها به کمک numpy است.
مثال:
a=np.array([[100,200,400],[1,2,3]])
میخواهیم عناصر سطر اول [0] و ستون دوم [1] را انتخاب کنیم.
a [0: , 1:] => array([[200, 400],[ 2, 3]])
شبکه های اجتماعی