Numpy

saalek110

Well-Known Member
سالک: من می بینم که ‌‌numpy مثل یک دوست همیشه کنار opencv است...میشه رابطه اشان را توضیح بدهی؟

deepseek:

خیلی خوب گفتی، دقیقاً NumPy مثل یک دوست جدانشدنی و همه‌کاره برای OpenCV است. بیا این رفاقت را باز کنیم.

رابطهشان یک رابطه همزیستی بنیادین است، نه فقط یک اتحاد ساده.

۱. هسته اصلی: زبان مشترک تصاویر

مهمترین دلیل این رفاقت این است: تصویر در OpenCV، در اصل یک آرایه NumPy است.

وقتی با cv2.imread() عکسی را میخوانی، چیزی که برمیگردد یک numpy.ndarray است. هیچ ساختار داده اختصاصی و سنگینی مثل OpenCV_Image وجود ندارد.

· تصاویر رنگی: یک آرایه ۳ بعدی به شکل (ارتفاع, عرض, کانال)
· تصاویر خاکستری: یک آرایه ۲ بعدی به شکل (ارتفاع, عرض)

این یعنی هر بلایی که میشود سر یک آرایه NumPy آورد، دقیقاً همان را میشود سر یک تصویر OpenCV هم آورد. این یک تصمیم درخشان بود، چون OpenCV را بینهایت منعطف کرد.

۲. چرا این رفاقت اینقدر خوب جواب میدهد؟

الف. پردازش و جادوی ریاضی (قدرت اصلی NumPy)

OpenCV عملیات تخصصی بینایی ماشین را انجام میدهد، اما محاسبات پشت صحنه و دستکاری سریع دادهها را کاملاً به NumPy میسپارد.

تصور کن میخواهی یک ماسک باینری روی تصویر بگذاری:

```python
import cv2
import numpy as np

img = cv2.imread('photo.jpg')
mask = cv2.imread('mask.jpg', 0) # خواندن ماسک به صورت خاکستری

# اینجا OpenCV هیچ تابع آماده‌ای برای این کار خاص ندارد،
# اما NumPy این کار را مثل آب خوردن انجام می‌دهد:
# نواحی غیرسیاه ماسک را در تصویر اصلی، قرمز کن
img[mask != 0] = [0, 0, 255]
```

میبینی؟ بدون NumPy باید با حلقه‌های کُند روی تکتک پیکسلها کار میکردی. NumPy این عملیات را بهینه و برداری انجام میدهد.

ب. دروازه‌ای به دنیای دیگر کتابخانه‌ها

OpenCV با این کار خودش را به کل اکوسیستم علمی پایتون وصل کرده است:

· هر کتابخانه‌ای که با NumPy کار میکند (یعنی تقریباً همه)، میتواند مستقیماً تصاویر OpenCV را بخواند و پردازش کند.
· میخواهی تصویر را با Matplotlib نمایش دهی؟ مستقیم آرایه را به plt.imshow() بده.
· میخواهی با SciPy روی آن فیلتر بگذاری؟ مستقیم به تابع بده.
· میخواهی آن را برای یک مدل TensorFlow/PyTorch آماده کنی؟ فقط نیاز به تغییر شکل آرایه داری.

OpenCV خودش را درگیر نمایش تصویر و محاسبات پایه نکرد و این وظیفه را به بهترین ابزار موجود سپرد.

پ. پیش‌پردازش و مهندسی ویژگی

قبل از اینکه یک تصویر به الگوریتمهای سنگین OpenCV برود، باید آماده شود. این آماده‌سازی تقریباً همیشه با NumPy است:

· نرمال‌سازی: img = img / 255.0
· تغییر اندازه عددی: scaled = img * 1.5
· ایجاد تصاویر مصنوعی: blank = np.zeros((500, 500, 3), dtype=np.uint8) و بعد نقاشی با توابع OpenCV.

جمع‌بندی: چه کاری را به کی بسپاریم؟

وظیفه ابزار مناسب مثال
خواندن/نوشتن تصویر OpenCV cv2.imread() , cv2.imwrite()
پردازش تخصصی تصویر OpenCV تشخیص چهره، تطبیق الگو، آستانه‌گیری، تبدیلات مورفولوژی
دستکاری پیکسلی و ریاضی NumPy برش زدن، ماسک کردن شرطی، عملیات ریاضی، تغییر اندازه کانال
رابط با کتابخانه‌های دیگر NumPy فرستادن تصویر به Matplotlib یا مدل یادگیری ماشین

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

saalek110

Well-Known Member
Numpy مال پایتون است ، اگر کسی بخواد در سی ملاسکار کنه که numpy نیستش

کاملاً درسته، پرسش هوشمندانه‌ای است. آفرین که گفتی NumPy کتابخانه‌ای برای پایتون است و در C++ چیزی به اسم NumPy وجود خارجی ندارد.

ولی نگران نباش، رفاقت همچنان برقرار است، فقط اسم رفیق عوض می‌شود! بیا ببینیم در C++ چه خبر است.

۱. جانشین NumPy در ++C: کلاس cv::Mat

در پایتون، NumPy ستون فقرات بود و خود OpenCV آن را نداشت. اما در C++، خود OpenCV کلاس قدرتمندی به نام cv::Mat را دارد. این کلاس دقیقاً همان نقش NumPy را بازی می‌کند:

· مخزن داده: همان آرایه چندبعدی که تصویر را نگه می‌دارد.
· موتور ریاضی: عملیات ماتریسی، محاسبات پیکسلی و جبر خطی را انجام می‌دهد.
· مدیریت حافظه: خودکار و هوشمند حافظه را مدیریت می‌کند. (خداحافظ new و delete)

در پایتون: pip install opencv-python (که NumPy را هم خودکار نصب می‌کند)
در C++: کافی است OpenCV را بیلد یا نصب کنی. کلاس Mat بخشی از خود OpenCV است.

۲. مقایسه مستقیم: NumPy در پایتون vs. Mat در ++C

ببین چقدر فلسفه شبیه هم است:

عملیات پایتون با NumPy ++C با cv::Mat
ساختن تصویر خالی np.zeros((h, w, 3), np.uint8) cv::Mat::zeros(h, w, CV_8UC3)
دسترسی ویرایشگر به پیکسل img[y, x] = [0,0,255] img.at<cv::Vec3b>(y, x) = cv::Vec3b(0,0,255);
برش ناحیه roi = img[0:h, 0:w] cv::Mat roi = img(cv::Range(0, h), cv::Range(0, w));
عملیات ماتریسی result = img1 + img2 cv::Mat result = img1 + img2; (عملگرها سربارگذاری شده‌اند)
تقسیم عددی scaled = img / 255.0 cv::Mat scaled; img.convertTo(scaled, CV_32F, 1.0/255.0);

می‌بینی؟ cv::Mat در C++ تمام آن انعطاف و قدرت برداری NumPy را به صورت Native برایت فراهم می‌کند.

۳. اما یک نکته ظریف برای حرفه‌ای‌ها وجود دارد

اگر واقعاً در C++ به قدرت NumPy (مثلاً برای جبر خطی خیلی سنگین یا سرعت کرنل‌های سفارشی) نیاز پیدا کنی، رفیق سنتی NumPy در C++ کتابخانه Eigen است. OpenCV طوری طراحی شده که بدون درز و اصطکاک با Eigen کار کند:

```cpp
#include <opencv2/core/eigen.hpp>

cv::Mat img = cv::imread("photo.jpg");
Eigen::MatrixXd eigen_matrix;

// تبدیل مستقیم و بدون کپی داده (در صورت امکان)
cv::cv2eigen(img, eigen_matrix);

// حالا می‌توانی تمام جادوی Eigen را روی ماتریس اِعمال کنی
```

پس در دنیای C++:

· رفیق اول و داخلی: cv::Mat که دیگر نیازی به NumPy نداری.
· رفیق تخصصی ریاضی: Eigen که در صورت نیاز، خیلی راحت جایگزین NumPy می‌شود و با OpenCV همکاری نزدیکی دارد.

پس این رفاقت فراتر از پایتون است، یک فلسفه طراحی در OpenCV است که همیشه یک ساختار داده قدرتمند، کارآمد و آشنا به جبر خطی را کنار خود دارد، چه آن ساختار NumPy باشد، چه cv::Mat یا Eigen.
 

saalek110

Well-Known Member
توابع numpy چیه ؟

عالی، برگردیم به سراغ رفیق اول OpenCV. گفتی که NumPy مثل یک دوست همیشه کنار OpenCV است، حالا ببینیم این دوست چه توانایی‌هایی (توابعی) دارد که اینقدر ارزشمندش کرده.

توابع NumPy را می‌شود به چند دسته کلی تقسیم کرد. دقیقاً همین تابع‌ها هستند که کار با تصاویر را در OpenCV راحت و سریع می‌کنند:

---

۱. توابع ایجاد آرایه (ساختن بوم نقاشی)

قبل از هر چیز، باید بتوانیم یک تصویر خام یا یک ماتریس را از صفر بسازیم.

تابع کاربرد مثال در دنیای تصویر
np.zeros() آرایه‌ای پر از صفر می‌سازد. ساخت یک تصویر کاملاً سیاه.
np.ones() آرایه‌ای پر از یک می‌سازد. ساخت یک تصویر سفید (با ضرب در ۲۵۵).
np.full() آرایه‌ای پر از یک عدد دلخواه. ساخت یک تصویر خاکستری یکدست.
np.arange() تولید اعداد با گام مشخص. ساخت یک گرادیان خطی برای تست الگوریتم‌ها.

```python
# ساخت یک تصویر آبی یکدست با NumPy (کانال‌های BGR در OpenCV)
import numpy as np
# ارتفاع=۴۸۰، عرض=۶۴۰، ۳ کانال رنگی، نوع داده=عدد صحیح ۸ بیتی
blue_img = np.full((480, 640, 3), (255, 0, 0), dtype=np.uint8)
```

---

۲. توابع شکل و جابجایی (تغییر ساختار تصویر)

این توابع آرایه را تغییر شکل می‌دهند، کپی نمی‌کنند. برای کار با OpenCV حیاتی هستند.

تابع کاربرد مثال در دنیای تصویر
reshape() تغییر ابعاد آرایه بدون تغییر داده. تبدیل یک آرایه ۱ بعدیِ تخت به یک تصویر ۲ بعدی.
flatten() / ravel() تبدیل آرایه چندبعدی به یک آرایه ۱ بعدی. آماده‌سازی داده تصویر برای ورودی یک مدل یادگیری ماشین.
transpose() جابجایی محورها (Transpose). چرخاندن ۹۰ درجه‌ای مختصات تصویر.

---

۳. توابع ریاضی و آماری (چشم و مغز محاسباتی)

اینجا جایی است که NumPy می‌درخشد و OpenCV را قدرتمند می‌کند. عملیات روی کل تصویر، بدون حلقه و بسیار سریع.

تابع کاربرد مثال در دنیای تصویر
np.mean() محاسبه میانگین کل آرایه. محاسبه روشنایی متوسط یک تصویر.
np.std() محاسبه انحراف معیار. سنجش کنتراست تصویر.
np.min() / np.max() پیدا کردن حداقل و حداکثر مقدار. پیدا کردن روشن‌ترین و تاریک‌ترین نقطه تصویر.
np.sum() جمع تمام مقادیر. محاسبه مجموع پیکسل‌های یک ناحیه برای اندازه‌گیری مساحت.
np.sqrt(), np.sin(), np.log() توابع ریاضی عمومی. اعمال ویرایش و نگاشت تُن روی پیکسل‌ها.

---

۴. توابع منطقی و ماسک‌گذاری (هنر انتخاب و فیلتر)

جادوی اصلی که در مثال قبلی نشان دادم، با این توابع اتفاق می‌افتد.

تابع کاربرد مثال در دنیای تصویر
عملگرهای شرطی (>, <, ==) مقایسه عنصر به عنصر آرایه. پیدا کردن پیکسل‌های بالای یک آستانه: img > 128
np.where() شرط پیشرفته: "اگر شرط برقرار بود این، وگرنه آن". اعمال یک تغییر رنگ روی نواحی خاص از تصویر.
np.logical_and/or/not ترکیب شرط‌ها. پیدا کردن پیکسل‌هایی که هم قرمز هستند و هم روشن.

```python
# مثال: فقط پیکسل‌های خیلی تاریک را به سفید تغییر بده
img[img < 50] = 255
# پیدا کردن مختصات پیکسل‌های کاملاً قرمز
red_pixels_coords = np.where((img[:, :, 2] == 255) & (img[:, :, 1] == 0) & (img[:, :, 0] == 0))
```

---

۵. توابع ترکیب و تقسیم (جراحی کانال‌های رنگ)

برای جدا کردن و چسباندن کانال‌های رنگی که در OpenCV حیاتی است.

تابع کاربرد مثال در دنیای تصویر
np.split() تقسیم یک آرایه در راستای یک محور. جدا کردن دستی کانال‌های BGR (هرچند خود cv2.split بهینه‌تر است).
np.concatenate() چسباندن چند آرایه به هم. چسباندن دو تصویر کنار هم برای نمایش مقایسه‌ای.
np.hstack() / np.vstack() چسباندن افقی/عمودی (خلاصه‌شده concatenate). نمایش چند نسخه از یک تصویر در یک پنجره.

این‌ها فقط یک چشیده از قدرت NumPy بود. نکته طلایی این است: به‌محض اینکه عملیاتی روی کل تصویر به ذهنت رسید (مثلاً نصف کردن روشنایی، صفر کردن یک ناحیه، یا پیدا کردن پیکسل‌های خاص)، قبل از اینکه به فکر حلقه for بیفتی، بدان که احتمالاً یک تابع NumPy وجود دارد که آن را در یک خط و ۱۰۰ برابر سریع‌تر انجام دهد.
 

saalek110

Well-Known Member
کارهای رایج ارایه ای روی عکسها چیه؟

خیلی هم عالی، می‌خوای دانش NumPy را مستقیم روی عمل جراحی تصاویر پیاده کنی.

تا اینجا فهمیدیم که عکس یک آرایه NumPy است. حالا ببینیم رایج‌ترین کارهایی که سر این آرایه می‌آید تا یک عکس خام را به دادۀ مفید تبدیل کند چیست.

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

---

۱. برش زدن و ناحیه مورد نظر

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

```python
import cv2
import numpy as np

img = cv2.imread('image.jpg')

# بریدن یک مستطیل از وسط عکس
h, w = img.shape[:2]
center_crop = img[h//4 : 3*h//4, w//4 : 3*w//4]

# جدا کردن کانال آبی (B)
blue_channel = img[:, :, 0]
```

---

۲. ماسک‌گذاری (Masking) - جراحی انتخابی

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

```python
# پیدا کردن پیکسل‌های خیلی روشن (آستانه ۲۰۰)
bright_mask = img > 200

# دو کار رایج با این ماسک:
# الف) تغییر رنگ: پیکسل‌های روشن را قرمز کن
img[bright_mask] = [0, 0, 255]

# ب) استخراج بدون پس‌زمینه (Background Removal)
# همه پیکسل‌های غیر از یک رنگ خاص را به سفید تغییر بده
non_red_mask = (img[:, :, 2] < 200) # کانال قرمز ضعیف
img[non_red_mask] = [255, 255, 255]
```

---

۳. تغییرات سراسری با عملیات برداری

به جای ضرب و جمع روی تک‌پیکسل‌ها، کل آرایه را یکجا دستکاری می‌کنیم.

```python
# الف) تغییر روشنایی (Brightness Adjustment)
brighter = cv2.add(img, 50) # روش بهتر (از سرریز شدن جلوگیری می‌کند)
# اما اگر با NumPy برویم:
# brighter = img + 50 # مراقب سرریز (overflow) باش!

# ب) افزایش کنتراست (Contrast Adjustment)
alpha = 1.5 # ضریب کنتراست
beta = -30 # تنظیم روشنایی برای جبران
contrasted = cv2.convertScaleAbs(img, alpha=alpha, beta=beta)

# پ) نرمال‌سازی برای مدل‌های یادگیری ماشین (صفر تا یک)
normalized = img.astype(np.float32) / 255.0
```

---

۴. تغییر فضای رنگی با دستکاری کانال‌ها

گاهی لازم است کانال‌ها را جابه‌جا یا ترکیب کنیم.

```python
# OpenCV تصویر را به صورت BGR می‌خواند، اما Matplotlib به RGB نیاز دارد.
# تبدیل BGR به RGB با NumPy (سریع‌ترین روش، فقط تغییر ترتیب کانال‌ها)
bgr_img = cv2.imread('image.jpg')
rgb_img = bgr_img[:, :, ::-1] # برعکس کردن ترتیب آخرین بعد

# یا ساخت یک تصویر خاکستری از میانگین کانال‌های رنگی
gray_manual = np.mean(bgr_img, axis=2).astype(np.uint8)
```

---

۵. رسم اشکال هندسی با NumPy قبل از توابع OpenCV

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

```python
# الف) ساخت "ناحیه مورد علاقه" (ROI) دایره‌ای شکل با NumPy
mask = np.zeros(img.shape[:2], dtype=np.uint8) # آرایه خالی
cv2.circle(mask, (center_x, center_y), radius, 255, -1) # OpenCV دایره کشید
masked_img = cv2.bitwise_and(img, img, mask=mask) # ماسک را اعمال کن

# ب) ساخت یک تصویر با الگوی شطرنجی برای کالیبراسیون دوربین
chess = np.zeros((480, 640), dtype=np.uint8)
chess[::40, ::40] = 255 # هر ۴۰ پیکسل یک ردیف را سفید کن
chess[20::40, 20::40] = 255
```

---

۶. تبدیلات اطلس و تصویری ساده

```python
# الف) قرینه/برگردان (Flip)
flipped_h = img[:, ::-1] # قرینه افقی با NumPy
flipped_v = img[::-1, :] # قرینه عمودی

# ب) برش یک ناحیه و چسباندن به جای دیگر
roi = img[100:200, 50:150]
img[300:400, 200:300] = roi # شرط: ابعاد باید دقیقاً برابر باشند

# پ) ایجاد حاشیه (Padding) / اضافه کردن قاب به تصویر
bordered = cv2.copyMakeBorder(img, 20, 20, 20, 20, cv2.BORDER_CONSTANT, value=[255,0,0])
```

---

خلاصه جمع‌بندی: الگوی ذهنی

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

۱. آیا فقط قسمتی از عکس را می‌خواهم؟ → برش آرایه (Slicing)
۲. آیا می‌خواهم پیکسل‌هایی با یک ویژگی خاص را هدف بگیرم؟ → ماسک بولی (Boolean Masking)
۳. آیا می‌خواهم عملیاتی یکسان روی کل پیکسل‌ها انجام دهم؟ → عملیات برداری (Vectorized Operations)
۴. آیا می‌خواهم ساختار کانال‌ها را تغییر دهم؟ → جاب‌جایی محور (Axis manipulation)

راز کار اینجاست: تا می‌توانی از حلقه for فرار کن! جوابت در یکی از این عملیات برداری NumPy نهفته است.
 

saalek110

Well-Known Member
. NumPy (مخفف Numerical Python) کتابخانهای بنیادین در پایتون برای محاسبات عددی است. اگر بخواهم در یک جمله خلاصه کنم، NumPy قالبی برای کار با داده است که سرعت و انعطاف خیره‌کننده‌ای دارد.

در ادامه مهم‌ترین جنبه‌هایش را قدم به قدم بررسی می‌کنیم:

---

۱. چرا NumPy؟ مشکل لیست‌های پایتون

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

· کندی: حلقه‌های پایتون روی حجم بالای داده بسیار کند هستند.
· حافظه: هر آیتم در لیست پایتون یک شیء کامل است که سربار حافظه زیادی دارد.

NumPy با دو راهکار این مشکلات را حل می‌کند:

· آرایه همگن: به جای اشیاء متنوع، یک آرایه هست که تمام عناصرش از یک نوع هستند (مثلاً int32). این حافظه را به شدت کاهش می‌دهد.
· پیاده‌سازی به زبان C: محاسبات اصلی توسط کدهای سریع C و Fortran انجام می‌شود، نه پایتون.

---

۲. سنگ بنای NumPy: آرایه n بعدی (ndarray)

قلب NumPy شیء ndarray است. یک جدول چندبُعدی از اعداد، همگی با نوع داده یکسان.

· ایجاد آرایه‌ها:
```python
import numpy as np

# از لیست پایتون
arr1d = np.array([1, 2, 3])

# ماتریس ۲x۳
arr2d = np.array([[1, 2, 3], [4, 5, 6]])

# توابع کمکی پرکاربرد
np.zeros((2, 3)) # ماتریس ۲x۳ پر از صفر
np.ones((3, 2)) # پر از عدد یک
np.arange(0, 10, 2) # مثل range پایتون: [0, 2, 4, 6, 8]
np.linspace(0, 1, 5) # ۵ عدد با فاصله مساوی بین ۰ و ۱
```
· آرایه تصادفی:
```python
np.random.rand(2, 3) # توزیع یکنواخت بین ۰ و ۱
np.random.randn(3, 3) # توزیع نرمال استاندارد
np.random.randint(1, 10, size=(2, 5)) # اعداد صحیح تصادفی
```
· ویژگی‌های کلیدی یک آرایه:
```python
arr = np.array([[1, 2, 3], [4, 5, 6]])

print(arr.shape) # (2, 3) -> ابعاد آرایه
print(arr.ndim) # 2 -> تعداد ابعاد
print(arr.dtype) # int64 -> نوع داده عناصر
print(arr.size) # 6 -> تعداد کل عناصر
```

---

۳. ابرقدرت اصلی: عملیات برداری (Vectorization)

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

```python
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])

# بدون هیچ حلقه‌ای:
print(a + b) # [ 6, 8, 10, 12]
print(a * b) # [ 5, 12, 21, 32]
print(a ** 2) # [ 1, 4, 9, 16]
print(np.sqrt(a)) # [1. 1.414 1.732 2. ]

# عملیات روی ماتریس‌ها:
arr = np.array([[1, 2], [3, 4]])
print(arr * 10) # هر عنصر ضربدر ۱۰ می‌شود
```

---

۴. ایندکس‌گذاری و برش (Indexing & Slicing)

انعطاف‌پذیری عظیمی برای انتخاب و تغییر بخش‌های یک آرایه.

· در آرایه‌های یک‌بُعدی (شبیه لیست):
```python
arr = np.array([10, 20, 30, 40, 50])
print(arr[1:4]) # [20 30 40]
```
· در آرایه‌های چندبُعدی:
```python
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

print(arr2d[0, 1]) # 2 (سطر اول، ستون دوم)
print(arr2d[:, 1]) # [2 5 8] (تمام سطرها، ستون دوم)
print(arr2d[1:, :2]) # [[4, 5], [7, 8]] (سطرهای ۱ تا آخر، ستون‌های ۰ و ۱)
```
· ایندکس‌گذاری شرطی (بولی): فوق‌العاده قدرتمند برای فیلتر کردن داده‌ها.
```python
data = np.array([15, 22, 8, 31, 5])
mask = data > 15 # آرایه‌ای از True/False: [False, True, False, True, False]
print(data[mask]) # [22 31] فقط مقادیر بزرگتر از ۱۵
```

---

۵. تغییر شکل آرایه (Reshaping)

بدون کپی کردن داده، ساختار آرایه را عوض می‌کنید.

```python
a = np.arange(12) # [ 0, 1, 2, ... , 11]
b = a.reshape(3, 4) # ماتریس ۳x۴
c = a.reshape(2, 6) # ماتریس ۲x۶
d = b.ravel() # برمی‌گردد به آرایه ۱ بعدی [ 0...11]
```

علامت 1- خیلی کاربردی است: "خودت این بعد را حساب کن."

```python
e = a.reshape(2, -1) # یعنی 2 سطر، و هرچقدر ستون لازم است (می‌شود 2x6)
```

---

۶. جبر خطی (Linear Algebra)

NumPy یک کتابخانه کامل جبر خطی دارد (np.linalg).

```python
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

# ضرب ماتریسی (ضروری)
C = np.dot(A, B) # یا A @ B
print(C) # [[19 22] [43 50]]

# ماتریس معکوس
inv_A = np.linalg.inv(A)

# مقادیر ویژه و بردارهای ویژه
eigenvalues, eigenvectors = np.linalg.eig(A)
```

---

۷. کار با فایل‌ها

NumPy فرمت دودویی .npy خودش را دارد که سریع و فشرده است. همچنین می‌تواند فایل‌های متنی مثل CSV را بارگذاری و ذخیره کند.

```python
# ذخیره و بارگذاری سریع یک آرایه
np.save('data_array.npy', arr)
loaded_arr = np.load('data_array.npy')

# بارگذاری از فایل CSV
data_from_csv = np.loadtxt('file.csv', delimiter=',')
```

---

یک مثال عملی

فرض کن می‌خواهیم قیمت نهایی ۱۰۰,۰۰۰ سهام یک شرکت را با قیمت پایه 10 و درصد تغییرات random محاسبه کنیم.

روش کند پایتون:

```python
prices = [10.0] * 100_000
for i in range(100_000):
prices *= (1 + np.random.randn() * 0.05) # کند
```

روش NumPy (۲۰-۳۰ برابر سریع‌تر):

```python
base_price = 10.0
daily_returns = np.random.randn(100_000) * 0.05
final_prices = base_price * (1 + daily_returns) # یک عملیات روی کل آرایه
```

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

خلاصه و نکته پایانی

یادگیری NumPy پیش‌نیاز تقریباً تمام کتابخانه‌های علمی دیگر پایتون (مثل Pandas, Matplotlib, SciPy, Scikit-Learn) است. اگر می‌خواهید وارد دنیای داده شوید، وقت گذاشتن روی مفاهیم برادکستینگ (Broadcasting) و ایندکس‌گذاری فانتزی (Fancy Indexing)، یک سرمایه‌گذاری فوق‌العاده است.

سوال بعدی‌ات چیه؟
 

saalek110

Well-Known Member
خیلی خب، بریم سراغ بخش شیرین ماجرا! توی این مرحله، از مفاهیم پایه فاصله می‌گیریم و با ترفندها و ابزارهای کاربردی NumPy آشنا می‌شیم که روزانه به کار میان، در کنارش هم تمرینات هدفمند حل می‌کنیم تا مطلب کاملاً جا بیفته.

---

جعبه ابزار مخفی NumPy (توابع کاربردی)

اینا اون تابع‌هایی هستن که اگر بلد باشی، سرعت کدنویسیت چند برابر می‌شه:

۱. ناجی ابعاد: np.newaxis و None

برای اضافه کردن یک بعد جدید به آرایه (مثلاً تبدیل بردار سطری به ستونی) بدون تغییر داده، فوق‌العاده‌ست.

```python
arr = np.array([1, 2, 3]) # شکل: (3,)

# تبدیل به بردار ستونی
col_vec = arr[:, np.newaxis] # یا arr[:, None]
print(col_vec.shape) # (3, 1)

# تبدیل به بردار سطری
row_vec = arr[np.newaxis, :] # یا arr[None, :]
print(row_vec.shape) # (1, 3)
```

۲. پادشاه شرط‌ها: np.where()

نسخهٔ وکتورایز شدهٔ if-else. سرعتش از هر حلقه‌ای بیشتره.

```python
scores = np.array([85, 42, 91, 66, 58])
# اگه نمره بالای ۶۰ باشه "قبول"، وگرنه "رد"
result = np.where(scores > 60, "Pass", "Fail")
print(result) # ['Pass' 'Fail' 'Pass' 'Pass' 'Fail']
```

۳. معجزهٔ دسترسی: Fancy Indexing

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

```python
arr = np.array([10, 20, 30, 40, 50])
indices = [0, 3, 4]
print(arr[indices]) # [10 40 50]

# برای آرایه‌های دوبعدی:
arr2d = np.arange(10, 22).reshape(3, 4)
# می‌خوایم عناصر (0,1) , (1,3) , (2,0) رو برداری
print(arr2d[[0, 1, 2], [1, 3, 0]]) # [11 19 18]
```

۴. خرد جمعی: توابع تجمیعی شرطی

می‌تونی تعداد چیزایی که یه شرط دارن رو بشمری، بدون حلقه.

```python
arr = np.random.randint(1, 100, 50)
# چندتا عدد زوج داریم؟
num_even = np.sum(arr % 2 == 0) # True معادل ۱ و False معادل ۰ محاسبه می‌شه
print(f"تعداد اعداد زوج: {num_even}")

# میانگین فقط اعداد بزرگتر از ۵۰
mean_above_50 = arr[arr > 50].mean()
```

۵. جادوی np.clip()

مقادیر رو بین یک کف و سقف محدود می‌کنه.

```python
data = np.array([12, 45, -5, 78, 0, 102])
# محدود کردن بین ۰ و ۱۰۰
clipped_data = np.clip(data, 0, 100)
print(clipped_data) # [ 12 45 0 78 0 100]
```

---

یک تابع جادویی هم هست که واقعاً کاربردی و نسبتاً ناشناخته‌ست:

۶. الاکلنگ داده: np.unique() با return_counts

برای پیدا کردن عناصر یکتا و تعداد تکرارشون، ابزاری بی‌نظیره.

```python
# فرض کن این آرایه، شناسهٔ محصولاتی هست که فروش رفتن
purchases = np.array([101, 102, 101, 101, 103, 102, 104, 101])

# محصولات یکتا و تعداد فروششون یک‌جا
products, counts = np.unique(purchases, return_counts=True)
print(dict(zip(products, counts)))
# خروجی: {101: 4, 102: 2, 103: 1, 104: 1}
```

---

️ تمرین و حل تشریحی (برای عمیق‌تر شدن مفاهیم)

تمرین ۱: فیلتر هوشمند "سه‌دری"

هدف: درک قدرت ایندکس‌گذاری بولی.

یک آرایه ۵x۵ با اعداد تصادفی ۱ تا ۱۰۰ بساز. سپس:
۱. تمام اعداد فرد را به صفر تبدیل کن.
۲. میانگین اعداد زوج باقی‌مانده را حساب کن.

راه‌حل و تحلیل:

```python
import numpy as np

# 1. ساخت آرایه 5x5
arr = np.random.randint(1, 101, size=(5, 5))

# 2. ایجاد ماسک برای اعداد فرد
odd_mask = (arr % 2 != 0)

# 3. صفر کردن اعداد فرد (یک عملیات وکتوریزه)
arr[odd_mask] = 0

# 4. حساب میانگین اعداد زوج (اعداد غیرصفر بعد از تغییر)
# روش اول: ماسک جدید برای اعداد زوج
even_mask = (arr != 0)
average_even = arr[even_mask].mean()

print(f"ماتریس نهایی:\n{arr}")
print(f"میانگین اعداد زوج: {average_even:.2f}")
```

---

تمرین ۲: "سطر قصاب" - حذف سریع سطرها

هدف: تمرین np.delete() و ایندکس‌گذاری ترکیبی.

یک ماتریس ۶x۴ پر از اعداد ۰ تا ۲۳ بساز. سپس ستون سوم (ایندکس۲) و سطری که مجموع عناصرش بزرگتر از میانگین مجموع کل سطرهاست را پیدا و حذف کن.

راه‌حل و تحلیل:

```python
# 1. ساخت ماتریس (اعداد 0 تا 23)
matrix = np.arange(24).reshape(6, 4)
print(f"ماتریس اولیه:\n{matrix}")

# 2. حذف ستون سوم (ایندکس ۲) از ماتریس اولیه
temp_matrix = np.delete(matrix, 2, axis=1)

# 3. پیدا کردن سطری که باید حذف بشه (بر اساس ماتریس اولیه)
row_sums = matrix.sum(axis=1)
avg_row_sum = row_sums.mean()

# پیدا کردن ایندکس اولین سطری که شرط رو داره
index_to_delete = np.where(row_sums > avg_row_sum)[0][0] # اولین سطر

# 4. حذف آن سطر از ماتریس نهایی
final_matrix = np.delete(temp_matrix, index_to_delete, axis=0)

print(f"\nاندیس سطر حذف شده: {index_to_delete}")
print(f"ماتریس نهایی:\n{final_matrix}")
```

---

تمرین ۳: "کارخانه نرمالایزر" - استفاده از Broadcasting

هدف: درک یکی از مهم‌ترین مفاهیم NumPy: برادکستینگ.

یک ماتریس ۴x۵ با اعداد تصادفی (میانگین=۵۰، انحراف=۱۰) بساز. سپس هر ستون را با کم کردن میانگین و تقسیم بر انحراف معیار همان ستون، نرمالایز کن.

راه‌حل و تحلیل:

```python
# 1. داده تصادفی
np.random.seed(42) # برای تکرارپذیری
data = np.random.normal(loc=50, scale=10, size=(4, 5))

# 2. محاسبه میانگین و انحراف معیار هر "ستون" (axis=0 یعنی عمود بر سطرها)
col_means = data.mean(axis=0)
col_stds = data.std(axis=0)

# 3. نرمالایز کردن با قدرت Broadcasting!
# (4,5) با (5,) محاسبه می‌شود: NumPy خودش ابعاد را جفت می‌کند
normalized_data = (data - col_means) / col_stds

print(f"داده اولیه:\n{data}")
print(f"\nمیانگین ستون‌ها: {col_means}")
print(f"انحراف معیار ستون‌ها: {col_stds}")
print(f"\nداده نرمالایز شده:\n{normalized_data}")

# 4. بررسی صحت: میانگین جدید ستون‌ها باید صفر باشد
print(f"\nمیانگین جدید (باید نزدیک ۰ باشد):\n{normalized_data.mean(axis=0)}")
```

نکته طلایی خداحافظی:

پروفایل کردن را یاد بگیر. همیشه قبل از بهینه‌سازی، کدت را با timeit یا cProfile بررسی کن که آیا حلقه‌ات واقعاً bottleneck است یا خیر. NumPy جادو می‌کند، اما گاهی یک حلقه ساده خواناتر است و سرعتش هم برای حجم داده کم، قابل قبول.

سوال بعدی‌ت چیست؟
 

saalek110

Well-Known Member
عالیه! بیایید از صفرِ صفر شروع کنیم و一步一步 با هم کدنویسی کنیم. قول می‌دم هیچ مفهومی رو بدون توضیح ول نمیکنیم.

---

جلسه اول: "آرایه چیه و چرا عکس یک آرایه‌ست؟"

۱. اولین برخورد: آرایه رو لمس کن

بیا اولین کدها رو بزنیم ببینیم اصلاً NumPy چی به ما میده:

```python
import numpy as np

# ساده‌ترین آرایه ممکن: یه لیست معمولی رو تبدیل به آرایه NumPy می‌کنیم
my_list = [1, 2, 3, 4, 5]
my_array = np.array(my_list)

print("لیست پایتونی:", my_list)
print("آرایه NumPy:", my_array)
print("نوع آرایه:", type(my_array))
```

❓ چی شد؟
یه لیست معمولی رو دادیم به np.array() و اون بهمون یه شیء جدید برگردوند. این شیء جدید یه موجود ریاضی‌ایه، نه یه لیست ساده.

---

۲. فرق آرایه با لیست: چرا NumPy؟

```python
import numpy as np

# بیایید مقایسه کنیم
python_list = [1, 2, 3, 4, 5]
numpy_array = np.array([1, 2, 3, 4, 5])

# عملیات ریاضی روی لیست: ❌
try:
result = python_list * 2
print("لیست × ۲:", result) # [1, 2, 3, 4, 5, 1, 2, 3, 4, 5] !!! تکرار میشه!
except:
print("نمیشه عملیات ریاضی واقعی انجام داد")

# عملیات ریاضی روی آرایه: ✅
result = numpy_array * 2
print("آرایه × ۲:", result) # [2 4 6 8 10] !!! عملیات ریاضی واقعی
```

نکته حیاتی:

· لیست * 2 میشه تکرار لیست
· آرایه * 2 میشه ضرب ریاضی

---

۳. حالا عکس چیه؟ یه آرایه ۲ بعدی

بیایید یه "عکس" ساده ۳×۳ پیکسل بسازیم:

```python
import numpy as np

# یه عکس ۳×۳ که فقط اعداد روشنایی داره (عکس خاکستری)
# هر عدد نشون‌دهنده روشنایی اون پیکسله: ۰=سیاه، ۲۵۵=سفید
image = np.array([
[0, 128, 255], # سطر اول: سیاه، خاکستری، سفید
[50, 100, 200], # سطر دوم
[255, 0, 128] # سطر سوم
])

print("عکس ۳×۳ ما:")
print(image)
print("\nشکل عکس:", image.shape) # (3, 3) یعنی ۳ سطر، ۳ ستون
print("نوع داده:", image.dtype) # int64 یعنی اعداد صحیح
```

عکس واقعی = آرایه NumPy
وقتی با OpenCV عکس میخونی، دقیقاً همین ساختار رو داری، فقط بزرگتر:

· یه عکس ۱۰۰×۱۰۰ = آرایه NumPy با شکل (100, 100)
· یه عکس رنگی = آرایه NumPy با شکل (100, 100, 3) ← سه تا عدد برای هر پیکسل: آبی، سبز، قرمز

---

۴. بریم OpenCV رو لمس کنیم: اولین عکس واقعی

```python
import cv2
import numpy as np

# یه عکس ساده ۳۰۰×۳۰۰ با NumPy بسازیم (بدون دوربین)
print("=== ساختن یه عکس ساده با NumPy ===")

# آرایه ۳۰۰×۳۰۰ پر از صفر = عکس کاملاً سیاه
black_image = np.zeros((300, 300), dtype=np.uint8)
print("شکل عکس سیاه:", black_image.shape) # (300, 300)
print("مقدار یه پیکسل:", black_image[0, 0]) # 0

# حالا بیایید یه مستطیل سفید وسطش بکشیم
# با برش NumPy: سطرهای ۱۰۰ تا ۲۰۰ و ستون‌های ۱۰۰ تا ۲۰۰
black_image[100:200, 100:200] = 255 # سفید کن

# نمایش با OpenCV
cv2.imshow("عکس ساخته شده با NumPy", black_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
```

اینجا چی شد؟

· np.zeros((300, 300)) یه آرایه ۳۰۰×۳۰۰ پر از صفر ساخت (عکس سیاه)
· black_image[100:200, 100:200] = 255 با برش NumPy، یه مربع رو سفید کردیم
· OpenCV بدون هیچ زحمتی این آرایه رو به عنوان عکس نشون داد

---

۵. بیایید با ماتریس‌ها بازی کنیم (مثل عکس واقعی)

```python
import numpy as np

# یه عکس نمونه ۴×۴
sample = np.array([
[10, 20, 30, 40],
[50, 60, 70, 80],
[90, 100, 110, 120],
[130, 140, 150, 160]
])
print("عکس کامل:\n", sample)

# ۱. برش ساده: ۲ سطر اول، ۳ ستون اول
print("\n۱. برش [0:2, 0:3]:\n", sample[0:2, 0:3])
# یعنی از سطر ۰ تا ۱ (خود ۲ شامل نمیشه)، ستون ۰ تا ۲

# ۲. انتخاب یک ستون کامل
print("\n۲. ستون دوم (index=1):\n", sample[:, 1])
# یعنی تمام سطرها `:`، ستون شماره ۱

# ۳. انتخاب یه ناحیه از وسط
print("\n۳. وسط تصویر:\n", sample[1:3, 1:3])
# سطرهای ۱ و ۲، ستون‌های ۱ و ۲
```

این دقیقاً کاریه که توی پردازش تصویر میکنی:

· میگی "از عکس، فقط ناحیه صورت رو برش بده"
· میگی "ستون وسط عکس رو نشون بده"

---

۶. عملگرهای مقایسه‌ای: ماسک بولین (جادوی اصلی)

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

```python
import numpy as np

# عکس ساده ۳×۳
image = np.array([
[10, 150, 250],
[50, 200, 30],
[100, 80, 255]
])
print("عکس اصلی:\n", image)

# ۱. ماسک: کدوم پیکسل‌ها روشنتر از ۱۰۰ هستند؟
mask = image > 100
print("\n۱. ماسک (image > 100):\n", mask)
# True یعنی روشنتر از ۱۰۰، False یعنی تاریکتر

# ۲. از ماسک استفاده کنیم: فقط پیکسل‌های روشن رو نشون بده
bright_pixels = image[mask]
print("\n۲. فقط پیکسل‌های روشنتر از ۱۰۰:\n", bright_pixels)

# ۳. تعداد پیکسل‌های روشن
count_bright = np.sum(mask)
print("\n۳. تعداد پیکسل‌های روشن:", count_bright)

# ۴. مختصات پیکسل‌های روشن
coordinates = np.where(mask)
print("\n۴. مختصات (سطر, ستون):", coordinates)
print(" یعنی پیکسل‌های روشن در این موقعیت‌ها هستند:",
list(zip(coordinates[0], coordinates[1])))
```

این مغز خیلی از الگوریتم‌های پردازش تصویر:

· ماسک بساز (پیکسل‌های روشن، پیکسل‌های قرمز، ...)
· با اون ماسک کار انجام بده (بشمار، تغییر بده، پیدا کن)

---

۷. جمع‌بندی: حالا عکس سون سگمنت رو ساده می‌فهمی

```python
import cv2
import numpy as np

# فرض کن این تابع یه سگمنت از نمایشگر رو چک میکنه
def check_segment(segment_image):
"""
segment_image: یه برش NumPy از عکس اصلی که فقط یه سگمنت رو نشون میده
"""
# میپرسیم: چندتا پیکسل روشن (بیشتر از ۲۰۰) داریم؟
bright_pixels = np.sum(segment_image > 200)
total_pixels = segment_image.size # تعداد کل پیکسل‌ها

ratio = bright_pixels / total_pixels
print(f" پیکسل‌های روشن: {bright_pixels}/{total_pixels} = {ratio:.2f}")

return ratio > 0.5 # اگه بیش از نصفش روشنه، یعنی سگمنت فعاله

# === تست با یه عکس ساختگی ===
print("=== تست تشخیص سگمنت ===")

# یه سگمنت "روشن" (خیلی از پیکسل‌ها سفیدن)
segment_on = np.array([
[200, 255, 240, 255],
[250, 240, 255, 230],
[200, 255, 250, 240]
])
print("\nسگمنت روشن:")
result = check_segment(segment_on)
print(" نتیجه: سگمنت", "فعال ✅" if result else "غیرفعال ❌")

# یه سگمنت "خاموش" (اکثر پیکسل‌ها سیاهن)
segment_off = np.array([
[10, 15, 20, 5],
[30, 10, 25, 15],
[20, 5, 10, 25]
])
print("\nسگمنت خاموش:")
result = check_segment(segment_off)
print(" نتیجه: سگمنت", "فعال ✅" if result else "غیرفعال ❌")
```

---

تمرین‌های هفته (از ساده به سخت)

تمرین ۱ (آسون): برش و تغییر

```python
# یه آرایه ۵×۵ از اعداد ۱ تا ۲۵ بساز
# بعد، مربع ۳×۳ وسطش رو به ۹۹ تغییر بده
arr = np.arange(1, 26).reshape(5, 5)
print("اصلی:\n", arr)

# راهنمایی: مربع وسط از سطر ۱ تا ۴ و ستون ۱ تا ۴ هست
# کدت رو اینجا بنویس:
```

تمرین ۲ (متوسط): ماسک و آستانه‌گیری

```python
# یه عکس ۴×۴ با اعداد تصادفی بین ۰ تا ۲۵۵ بساز
# تمام پیکسل‌های بالای ۱۲۸ رو به ۲۵۵ و زیرش رو به ۰ تبدیل کن (بدون حلقه!)
np.random.seed(42)
image = np.random.randint(0, 256, size=(4, 4))
print("اصلی:\n", image)

# کدت رو اینجا بنویس (راهنمایی: از ماسک و ایندکس‌گذاری بولین استفاده کن)
```

تمرین ۳ (واقعی): با دوربین/وبکم تست کن

```python
import cv2
import numpy as np

# برنامه‌ای بنویس که:
# ۱. وبکم رو باز کنه
# ۲. تصویر رو خاکستری کنه
# ۳. فقط پیکسل‌های خیلی روشن (بالای ۲۰۰) رو سفید و بقیه رو سیاه کنه
# ۴. نشون بده

cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break

# تبدیل به خاکستری
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# اینجا با NumPy ماسک بزن و فقط نورهای قوی رو نگه دار
# کد NumPy خودت رو اینجا بنویس:
result = gray.copy()
# result = ???

cv2.imshow("Original", gray)
cv2.imshow("Only Bright", result)

if cv2.waitKey(1) & 0xFF == ord('q'):
break

cap.release()
cv2.destroyAllWindows()
```

---

چی یاد گرفتیم؟

۱. آرایه NumPy = ماتریس اعداد (و عکس هم یه ماتریسه)
۲. برش آرایه = انتخاب ناحیه از عکس
۳. ماسک بولین = پیدا کردن پیکسل‌های خاص
۴. np.sum, np.mean, np.where = ابزارهای تحلیل عکس

سوال بعدی‌ت چیه؟ میتونیم بریم سراغ یه پروژه واقعی‌تر (مثل تشخیص عدد با سون سگمنت واقعی) یا بیشتر روی مفاهیم NumPy عمیق بشیم.
 

جدیدترین ارسال ها

بالا