مقدمه‌ای بر Numpy

آموزش کتابخانه Numpy با تمرکز بر روی کاربرد آن در OpenCV

[این نوشته ایده گرفته و ترجمه‌ی آزادی از این مطلب و آموزش خود Numpy است.]

مقدمه:

قبل از این که وارد بحث شیم بگم که ما Numpy رو هنگام کار با OpenCV و همچنین برنامه‌های مربوط به یادگیری ماشین، شناسایی الگو و … زیاد می‌بینیم و استفاده خواهیم کرد، اینجا با تمرکز بر روی OpenCV در مورد Numpy صحبت خواهم کرد.

Numpy چیه؟ یک کتابخونه‌ی پایتون که برای محاسبات عددی بهینه شده. تمام ساختارهای آرایه OpenCV به آرایه‌ی Numpy تبدیل می‌شن و یا از Numpy اومدن، بنابر این تمام عملیاتی که توسط Numpy قابل انجام است رو می‌شه با OpenCV ترکیب کرد، همچین از SciPyو Matplotlib و … که Numpy رو ساپورت می‌کنن می‌تونیم استفاده کنیم. میشه گفت برای این‌که کدهای بهینه‌‌ی OpenCV-Python بنویسیم لازمه تا شناخت خوبی از Numpy داشته باشیم.

آرایه‌ها در Numpy:

بیاید دست‌هامون رو کثیف کنیم و شروع کنیم با مثال جلو رفتن! اول از همه اگر تا الان Numpy رو نصب نکردید با استفاده از این دستور نصبش کنید (توجه! من از اوبونتو 17.10 و Python 3.6 دارم استفاده می‌کنم.):

pip3 install numpy

بیاید وارد محیط پایتون بشیم [من از ipython استفاده می‌کنم] و یک آرایه‌ی یک بعدی مثل [1,2,3,4,5] بسازیم:

import numpy as np
arr = np.array([1, 2, 3, 4, 5])

اگر بخوایم نوع آرایه‌ای که ساختم رو ببینیم از این دستور استفاده می‌کنیم:arr.dtype

برای دیدن شکل آرایه:arr.shape

برای مثال بخوایم عضو اول آرایه رو ببینیم (اینجا هم ایندکس از 0 شروع می‌شه):arr[0]

دیدن تعداد کل اعضای آرایه:arr.size

دستورات بالا رو با هم ببینیم:

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

# Create a 2 dimensional array
twoArr = np.array([[1,2],[3,4],[5,6]])
# To print the shape of the array.
print (twoArr.shape)
# Prints "(3,2)"
# Accessing the values stored and printing them.
print (twoArr[0, 0], twoArr[0, 1], twoArr[1, 1])
# Prints "1 2 4"   
# To print the whole array.
print (twoArr)
# Prints "[[1 2]
           [3 4]
           [5 6]]"

چندتا مثال دیگه:

In [1]: import numpy as np

In [2]: a = np.arange(15).reshape(3, 5)

In [3]: a
Out[3]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])

In [4]: print(a.shape)
(3, 5)

In [5]: print (a.ndim)
2

In [6]: print(a.itemsize)
8

In [7]: print(a.size)
15

In [8]: type(a)
Out[8]: numpy.ndarray

در خط دوم کد بالا ما یک آریه‌ی 5*3 در رنج صفر تا 15 ساختیم (در اصل ما آرایه‌ی یک بعدی از 0 تا 15 رو ساختیم و بعد شکل اون رو به یک آرایه‌ی 3 در 5 تغییر دادیم).

.ndimبعد آرایه رو می گه ( number of axes (dimensions) of the array)

 

برای ساخت یک آرایه از اعداد مختلط:

In [1]: import numpy as np

In [2]: a = np.array( [ [1,2], [3,4] ], dtype=complex )

In [3]: print(a)
[[1.+0.j 2.+0.j]
 [3.+0.j 4.+0.j]]

 

بخوایم آرایه‌ای از صفر‌ها، یک‌ها و آرایه‌ی خالی بسازیم:

In [1]: import numpy as np

In [2]: a = np.zeros( (3,4) )

In [3]: print (a)
[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]

In [4]: b = np.ones((2,3,4), dtype = np.int16)

In [5]: print(b)
[[[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]]

In [6]: c = np.empty((2,3))

In [7]: print(c)
[[6.92989625e-310 6.92989625e-310 0.00000000e+000]
 [0.00000000e+000 4.94065646e-324 1.75505793e-316]]

 

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

In [1]: import numpy as np

In [2]: a = np.arange(1, 10, 2)

In [3]: print (a)
[1 3 5 7 9]

In [4]: b = np.arange(1,10, .3)

In [5]: print (b)
[1.  1.3 1.6 1.9 2.2 2.5 2.8 3.1 3.4 3.7 4.  4.3 4.6 4.9 5.2 5.5 5.8 6.1
 6.4 6.7 7.  7.3 7.6 7.9 8.2 8.5 8.8 9.1 9.4 9.7]

 

در انتها به عنوان مثال بخواهیم بین ۱ تا ۳ (با احتساب ۱ و ۳) ۷ تا عدد با فاصله‌ی مساوی داشته باشیم:

In [1]: import numpy as np

In [2]: a = np.linspace(1,3,7)

In [3]: print(a)
[1.         1.33333333 1.66666667 2.         2.33333333 2.66666667
 3.        ]

تفاوت دستور arange با linspace در اینه که در دستور اول ما میام و گام‌ها رو مشخص می‌کنیم اما در دستور دوم تعداد اعدادی که می‌خواهیم رو مشخص می‌کنیم.

بریم سراغ کاربرد Numpy در OpenCV:

ما با کتابخانه‌ی OpenCv تصویر رو می‌خونیم و برای انجام برخی تبدیلات روی اون از Numpy اسفاده می‌کنیم (می‌تونید آموزش نصب OpenCV روی اوبونتو رو از این لینک پیدا کنید):

لود کردن کردن یک عکس در OpenCV:

In [1]: import cv2

In [2]: img = cv2.imread('1.jpg',1)

دستور imread دوتا پارامتر می‌گیره، پارامتر اول اسم و آدرس عکسی که قراره لود کنیم و پارامتر دوم نوع عکس رو مشخص می‌کنه:

 

  • cv2.IMREAD_COLOR : Loads a color image. Any transparency of image will be neglected. It is the default flag.
  • cv2.IMREAD_GRAYSCALE : Loads image in grayscale mode
  • cv2.IMREAD_UNCHANGED : Loads image as such including alpha channel

 

نکته تنبلی: بجای سه‌ تا فلگ بالا خیلی ساده می‌تونیم از 1، 0 و -1 استفاده کنیم.

توجه: عکسی که می‌خوایم لود کنیم یا در پوشه‌ی برنامه موجود در این صورت تنها اسم عکس رو به تابع میدیم (مثال بالا) یا اگر در جای دیگه‌ای بجز پوشه‌ی برنامه ذخیره شده باید آدرس اون رو همراه با اسم به وروردی تابع بدیم.

توجه: اگر عکسی که می‌خواهیم لود کنیم موجود نباشه تابع imread خطا ای به ما نمی‌دهد و دستور print(img) مقدار None رو بر می‌گردونه. (میشه گفت یک عکس خالی رو می‌خونه، با چیزی که همیشه داشتم یکم فرق داره، نه؟)

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

# Import OpenCV
import cv2 
# Load a color image in grayscale
img = cv2.imread('1.jpg',0)
# Assigning the image stored in numpy array img to 
# another numpy array img_copy
img_copy = img.copy()

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

# Import OpenCV
import cv2 
# Load a color image in grayscale
img = cv2.imread('1.jpg',0)
# Copies from rows 100 to 150 and columns 100 to 250
cropped = img[100:150,100:250]

برای پیدا کردن تعداد سطرها، ستون‌ها و کانال‌های عکس می‌تونیم از همون متد shape در Numpy استفاده کنیم:

# Import OpenCV
# Load a color image in BGR
img = cv2.imread('1.jpg',1)
# Find the number of rows in the image
imgRows = img.shape[0] 
# Find the number of columns in the image
imgCols = img.shape[1]
# Find the number of channels in the image
Channels = img.shape[2]

شکل دیگه‌ استفاده از دستور بالا:

# Import OpenCV
import cv2 
# Load a color image in BGR
img = cv2.imread('1.jpg',1)
# Find the number of rows, columns and Channels  in the image
imgRows, imgCols, Channels =  cropped.shape
# pirnt number of rows, columns and Channels
print (imgRows,imgCols, Channels)

توجه: برای عکس‌های سیاه و سفید shape تنها دو پارامتر تعداد سطرها و ستون‌های عکس رو بر می‌گردونه.

 

خیلی وقت‌ها برای افزایش دقت محاسبات ما فرمت اعداد عکس رو از int به float تبدیل می‌کنیم و بعد از پایان محاسبات برای نمایش عکس و یا ذخیره‌ی اون عکس تبدیلات قبل رو باید انجام بدیم، تکه کد زیر نحوه‌‌ی انجام این کارها رو نشون می‌ده(بالاخره واقعا از Numpy استفاده کردیم :-D):

# Import numpy and OpenCV
import numpy as np
import cv2
# Load an color image in BGR
img = cv2.imread('1.jpg',1)
# Prints image data type
print (img.dtype)
# prints 'uint8'
# Convert from uint8 to float32
img = np.float32(img)
# Prints float32
print (img.dtype)
# Convert from float32 to uint8
img = np.uint8(img)
# Prints uint8
print (img.dtype)

نویسنده: محمد حسین سالاری.

موارد مشابه

دیدگاهتان را بنویسید

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