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 عمیق بشیم.
 

saalek110

Well-Known Member
آرایه که میگی گیج کننده است ، آیا عکس سیاه و سفید یا عکس خاکستری یا عکس رنگی ، ارایه شان یک جور است؟

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

---

سه نوع عکس، سه نوع آرایه

بیایید با یه مثال عینی شروع کنیم: فرض کن یه عکس خیلی کوچیک داری که فقط ۲ پیکسل عرض و ۳ پیکسل ارتفاع داره (یعنی ۲×۳).

---

۱. عکس سیاه و سفید (Binary Image)

فقط دو رنگ داره: سیاه یا سفید. ۰ یا ۱ (یا ۰ یا ۲۵۵).

```python
import numpy as np

# عکس سیاه و سفید ۳×۲ (۳ سطر = ارتفاع، ۲ ستون = عرض)
binary_img = np.array([
[0, 255], # سطر ۰: پیکسل اول سیاه، پیکسل دوم سفید
[255, 0], # سطر ۱: پیکسل اول سفید، پیکسل دوم سیاه
[0, 255] # سطر ۲: پیکسل اول سیاه، پیکسل دوم سفید
])

print("✓ آرایهٔ عکس سیاه و سفید:")
print(binary_img)
print("⫸ shape:", binary_img.shape) # (3, 2)
print("⫸ ndim:", binary_img.ndim) # 2
print("⫸ هر پیکسل فقط ۱ عدد داره")
```

ساختار: (ارتفاع, عرض) ← یه جدول ساده ۲ بعدی

---

۲. عکس خاکستری (Grayscale Image)

هر پیکسل یک عدد بین ۰ تا ۲۵۵ (۲۵۶ طیف خاکستری).

```python
# عکس خاکستری ۳×۲
gray_img = np.array([
[0, 128], # سیاه، خاکستری متوسط
[255, 64], # سفید، خاکستری تیره
[192, 32] # خاکستری روشن، خاکستری خیلی تیره
])

print("✓ آرایهٔ عکس خاکستری:")
print(gray_img)
print("⫸ shape:", gray_img.shape) # (3, 2)
print("⫸ ndim:", gray_img.ndim) # 2
print("⫸ هر پیکسل فقط ۱ عدد داره")
```

ساختار: دقیقاً مثل عکس سیاه و سفید (ارتفاع, عرض) ← ۲ بعدی. فرقش فقط اینه که اعداد می‌تونن ۰ تا ۲۵۵ باشن، نه فقط ۰ و ۲۵۵.

---

۳. عکس رنگی (Color Image - RGB/BGR)

هر پیکسل ۳ تا عدد داره: یکی برای قرمز، یکی سبز، یکی آبی.

```python
# عکس رنگی ۳×۲ (OpenCV از ترتیب BGR استفاده می‌کنه)
color_img = np.array([
[[255, 0, 0], [0, 255, 0]], # سطر ۰: پیکسل آبی، بعدی سبز
[[0, 0, 255], [255, 255, 0]], # سطر ۱: پیکسل قرمز، بعدی آبی+سبز=فیروزه‌ای
[[128, 128, 128], [0, 0, 0]] # سطر ۲: پیکسل خاکستری، بعدی سیاه
])

print("✓ آرایهٔ عکس رنگی (BGR):")
print(color_img)
print("⫸ shape:", color_img.shape) # (3, 2, 3)
print("⫸ ndim:", color_img.ndim) # 3
print("⫸ هر پیکسل ۳ عدد داره: [آبی, سبز, قرمز]")
```

ساختار: (ارتفاع, عرض, ۳) ← یه مکعب مستطیل ۳ بعدی! هر پیکسل یه بردار ۳ تایی داره.

---

مقایسه بصری (با کد واقعی OpenCV)

بیایید با OpenCV این تفاوت رو کاملاً حس کنیم:

```python
import cv2
import numpy as np

# یه عکس رنگی از وب کم (یا یه فایل)
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cap.release()

if ret:
print("=" * 50)
print("۱. عکس رنگی (frame اصلی)")
print(" shape:", frame.shape) # مثلاً (480, 640, 3)
print(" ndim:", frame.ndim) # 3
print(" یه پیکسل نمونه:", frame[100, 200]) # [آبی, سبز, قرمز]

print("\n" + "=" * 50)
print("۲. تبدیل به خاکستری")
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
print(" shape:", gray.shape) # (480, 640)
print(" ndim:", gray.ndim) # 2
print(" یه پیکسل نمونه:", gray[100, 200]) # یه عدد
print(" (فقط ۱ عدد! نه ۳ تا)")

print("\n" + "=" * 50)
print("۳. تبدیل به سیاه و سفید (باینری)")
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
print(" shape:", binary.shape) # (480, 640)
print(" ndim:", binary.ndim) # 2
print(" یه پیکسل نمونه:", binary[100, 200]) # 0 یا 255
print(" (همون ۲ بعدی‌ست، فقط مقادیر ۰ یا ۲۵۵)")

print("\n" + "=" * 50)
print(" نتیجه: هر سه نوع عکس NumPy array هستن،")
print(" فقط تعداد ابعاد و نوع مقادیر فرق می‌کنه!")
```

---

جدول خلاصه

نوع عکس Shape ndim هر پیکسل مقادیر ممکن
سیاه و سفید (H, W) ۲ ۱ عدد ۰ یا ۱ (یا ۰ یا ۲۵۵)
خاکستری (H, W) ۲ ۱ عدد ۰ تا ۲۵۵
رنگی (H, W, 3) ۳ ۳ عدد هرکدوم ۰ تا ۲۵۵

---

نکته طلایی

سیاه و سفید و خاکستری دقیقاً هم‌شکل هستن! فقط نوع مقادیرشون فرق می‌کنه.

```python
# هر دو shape یکسان دارن، فقط محتوا فرق می‌کنه
binary = np.array([[0, 255], [255, 0]]) # فقط ۰ و ۲۵۵
gray = np.array([[64, 128], [192, 32]]) # هر عددی بین ۰ تا ۲۵۵

print(binary.shape) # (2, 2)
print(gray.shape) # (2, 2)
```

---

امتحان کن: تغییر نوع تصویر با NumPy

```python
import numpy as np

# یه عکس رنگی کوچیک ۲×۲
color = np.array([
[[255, 0, 0], [0, 255, 0]], # آبی، سبز
[[0, 0, 255], [128, 128, 128]] # قرمز، خاکستری
])
print("رنگی shape:", color.shape) # (2, 2, 3)

# حالا تبدیل به خاکستری (با فرمول ساده!)
gray = np.mean(color, axis=2).astype(np.uint8)
print("\nخاکستری shape:", gray.shape) # (2, 2)
print(gray)

# حالا تبدیل به باینری
binary = (gray > 80).astype(np.uint8) * 255
print("\nسیاه و سفید shape:", binary.shape) # (2, 2)
print(binary)
```

---

یادت باشه: NumPy به همه اینا میگه ndarray. تفاوتشون فقط در shape و ndim هست. کافیه همیشه shape رو چک کنی تا بدونی با چه نوع تصویری طرفی!

باز سوالی بود بپرس.
 

saalek110

Well-Known Member
خیلی خوبه که می‌خوای عمیق و ساده بفهمی! اینارو حفظ نکن، بچشون تا تو وجودت حل بشه.

---

شش نکته‌ی طلایی که باید تو وجودت حل بشه

نکته ۱: آرایه = قفسهٔ شماره‌دار

لیست پایتون مثل یه کیسه‌ست که هرچیزی می‌تونی توش بندازی. آرایه NumPy مثل یه قفسهٔ فلزی منظم می‌مونه که فقط یه جنس خاص (مثلاً فقط عدد) و فقط در خانه‌های هم‌اندازه جا می‌گیره. به خاطر همین نظمه که سرعتش بالاست.

```python
import numpy as np

# لیست: کیسه شلوغ
my_list = [1, "hello", 3.14, [5, 6]] # قاطی پاتی

# آرایه: قفسه منظم
my_array = np.array([1, 2, 3, 4]) # فقط عدد، فقط یه ردیف
```

---

نکته ۲: Shape رو اینجوری بخون: "تا" و "تا"

وقتی shape رو می‌بینی، از آخر شروع کن به خوندن.

· (3, 4) ← ۴ تا خونه‌ست که این کارو ۳ بار تکرار کردیم.
· (480, 640, 3) برای عکس رنگی ← ۳ تا عدد داریم که این کارو ۶۴۰ بار تو عرض و ۴۸۰ بار تو ارتفاع تکرار کردیم.

همین قانون برای برش زدن: آرایه رو از چپ می‌بری (بعد بیرونی) و آرگومان‌ها رو از راست اعمال می‌کنی.

---

نکته ۳: عکس = یه صفحه شطرنجی اعداد

یه عکس خاکستری رو مثل یه صفحه شطرنجی تصور کن. هر خونه (پیکسل) یه عدد داره بین ۰ تا ۲۵۵.

· ۰ یعنی الماس سیاه.
· ۲۵۵ یعنی الماس سفید.
· بقیه اعداد یعنی طیف‌های مختلف خاکستری. عدد بزرگتر = روشن‌تر.

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

```python
# ساخت عکس ۵×۵
image = np.array([
[0, 50, 100, 150, 200],
[25, 75, 125, 175, 225],
[50, 100, 150, 200, 250],
[75, 125, 175, 225, 255],
[100, 150, 200, 250, 255]
])
# هر عدد = روشنایی یک الماس در صفحه شطرنجی
```

---

نکته ۴: محورها (Axes) = دستور غذای برش زدن

· axis=0 یعنی "عملیات رو عمودی انجام بده" (روی هر ستون جداگانه). پس سطرها رو با هم ترکیب می‌کنیم.
· axis=1 یعنی "عملیات رو افقی انجام بده" (روی هر سطر جداگانه). پس ستون‌ها رو با هم ترکیب می‌کنیم.

ترفند انگشتی:

· انگشتت رو عمودی روی آرایه بکش axis=0 → سطرها رو با هم ترکیب کن.
· انگشتت رو افقی روی آرایه بکش axis=1 → ستون‌ها رو با هم ترکیب کن.

```python
arr = np.array([[1, 2, 3],
[4, 5, 6]])

print(np.sum(arr, axis=0)) # [5, 7, 9] → جمع ستون‌ها
print(np.sum(arr, axis=1)) # [6, 15] → جمع سطرها
```

---

نکته ۵: برش (Slicing) = قیچی

برش زدن توی NumPy شبیه کار با قیچی‌ست:

· image[0:100, 50:200] یعنی از تصویر، از سطر ۰ تا ۹۹ (ارتفاع) و از ستون ۵۰ تا ۱۹۹ (عرض) رو ببُر بده به من.

خیلی مهم: ترتیبش همیشه [ارتفاع, عرض] هست. عدد اول همیشه سطر (ارتفاع) هست، عدد دوم ستون (عرض).

```python
image = np.array([
[10, 20, 30, 40],
[50, 60, 70, 80],
[90, 100, 110, 120]
])

# برش: ۲ سطر اول، ۳ ستون آخر
crop = image[0:2, 1:4]
print(crop)
# [[20 30 40]
# [60 70 80]]
```

---

نکته ۶: ماسک = عینک واقعیت مجازی

ماسک (Boolean Mask) یه عینک جادویی‌ست. می‌زنی به چشم‌ت و فقط چیزایی رو می‌بینی که شرطت رو داشته باشن.

· image > 100 بهت یه عینک میده که فقط پیکسل‌های روشن‌تر از ۱۰۰ رو نشون میده.
· image == 255 بهت عینکی میده که فقط سفید مطلق‌ها رو نشون میده.

```python
arr = np.array([10, 150, 200, 50, 255])

mask = arr > 100
print(mask) # [False, True, True, False, True]
print(arr[mask]) # [150, 200, 255]
```

---

⚡ تمرین فوق‌العاده: همه نکته‌ها در ۳ خط کد

این سه خط رو دقیق نگاه کن. تمام نکته‌های بالا رو میشه توش دید:

```python
# یه عکس فرضی ۲۰۰×۲۰۰ خوندیم
gray = cv2.imread('image.jpg', 0)

# نکته ۵ (برش) + نکته ۶ (ماسک):
# از گوشه بالا-چپ، یه ناحیه ۵۰×۵۰ برش می‌دیم
# نکته ۳: با پیکسل‌ها مثل عدد بازی می‌کنیم
roi = gray[0:50, 0:50] # قیچی: سطر ۰ تا ۴۹، ستون ۰ تا ۴۹
bright_part = roi[roi > 150] # عینک: فقط اعداد بزرگتر از ۱۵۰ رو ببین

# نکته ۴ (محور) + نکته ۱ (قفسه):
# میانگین روشنایی رو تو این ناحیه حساب می‌کنیم
avg_brightness = np.mean(roi, axis=0) # میانگین هر ستون

print(f"ناحیه برش:\n{roi}")
print(f"پیکسل‌های روشن: {bright_part}")
print(f"میانگین روشنایی ستون‌ها: {avg_brightness}")
```

---

به خاطر بسپار: NumPy فقط یه سری فرمول پیچیده نیست. هستهٔ اصلی‌ش اینه:
۱. یک عالمه عدد داری.
۲. می‌خوای بدون حلقه، باهاشون بازی کنی.
۳. عکس هم چیزی جز یه عالمه عدد نیست.
 

saalek110

Well-Known Member
باشه، بیا خیلی خیلی خودمونی و ساده بگم. فرض کن یه بچه ۱۰ ساله کنارت نشسته.

---

عکس چیه؟ یه جدول شطرنجی از عددها

مرحله ۱: یه عکس رو تصور کن

یه عکس مربعی ۳×۳ رو تصور کن (۳ خونه عرض، ۳ خونه ارتفاع). مثل جدول زیر:

ستون ۰ ستون ۱ ستون ۲
سطر ۰ ۱۰ ۲۰ ۳۰
سطر ۱ ۴۰ ۵۰ ۶۰
سطر ۲ ۷۰ ۸۰ ۹۰

تمام! عکس خاکستری دقیقاً همینه. یه جدول که توی هر خونه‌ش یه عدد هست.

· عدد ۰ = سیاه مطلق
· عدد ۲۵۵ = سفید مطلق
· عدد ۱۲۸ = خاکستری وسط

```python
import numpy as np

# همون جدول بالا در پایتون:
image = np.array([
[10, 20, 30],
[40, 50, 60],
[70, 80, 90]
])

print(image)
```

---

مرحله ۲: عکس رنگی چیه؟ سه تا جدول روی هم

عکس رنگی = سه تا از این جدول‌ها که چسبیدن به هم:

· جدول اول: عددهای رنگ آبی
· جدول دوم: عددهای رنگ سبز
· جدول سوم: عددهای رنگ قرمز

مثل یه دفترچه که ۳ برگه داره، هر برگه یه رنگ!

```python
# عکس رنگی ۲×۲ (۲ ارتفاع، ۲ عرض، ۳ رنگ)
color_image = np.array([
[[255, 0, 0], [0, 255, 0]], # سطر اول
[[0, 0, 255], [128, 128, 128]] # سطر دوم
])

# پیکسل اول (سطر ۰، ستون ۰):
# [255, 0, 0] یعنی آبی=۲۵۵، سبز=۰، قرمز=۰ → رنگ آبی خالصه!
```

---

آرایه یعنی چی؟ یعنی "قفسه بندی"

لیست پایتون = کیسه خرید

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

آرایه NumPy = قفسه کتاب

· فقط یه جنس توش جا می‌گیره (فقط عدد)
· همه خونه‌ها هم‌اندازه‌ن
· خیلی سریع می‌تونی بگی "از خونه ۵ تا ۲۰ رو بده به من"

```python
# لیست پایتون (کیسه):
my_list = [1, "سلام", 3.14] # هر چی دوست داری

# آرایه NumPy (قفسه کتاب):
my_array = np.array([1, 2, 3]) # فقط عدد، فقط منظم
```

---

✋ با دست خودت عکس بساز و ببین

این کد رو بزن، خودت می‌بینی که عکس همون آرایه‌ست:

```python
import numpy as np
import cv2

# یه جدول ۳۰۰×۳۰۰ پر از صفر (عکس سیاه)
my_photo = np.zeros((300, 300))

# وسط عکس، یه مربع ۱۰۰×۱۰۰ سفید بکش
my_photo[100:200, 100:200] = 255

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

دیدی؟ my_photo یه آرایه NumPy معمولیه. OpenCV فقط بلده چطور این جدول اعداد رو به چشم ما آدم‌ها نشون بده.

---

کل ماجرا در ۴ خط

```python
# ۱. عکس رو میخونیم
img = cv2.imread('photo.jpg')

# ۲. img یه آرایه NumPy هست
print(type(img)) # <class 'numpy.ndarray'>

# ۳. شکلش رو می‌بینیم
print(img.shape) # مثلاً (600, 800, 3) یعنی ۶۰۰ سطر، ۸۰۰ ستون، ۳ رنگ

# ۴. هر پیکسل رو می‌تونیم مثل آرایه بخونیم
print(img[100, 200]) # خونه سطر ۱۰۰ و ستون ۲۰۰ رو نشون بده
```

---

یه بار برای همیشه

وقتی می‌گی یعنی
عکس سیاه و سفید جدول ۲ بعدی (سطر × ستون)
عکس خاکستری جدول ۲ بعدی (سطر × ستون)
عکس رنگی سه تا جدول ۲ بعدی چسبیده به هم
Shape = (480, 640) ۴۸۰ تا سطر، ۶۴۰ تا ستون
Shape = (480, 640, 3) ۴۸۰ سطر × ۶۴۰ ستون × ۳ رنگ
ndim = 2 جدول ساده (صفحه)
ndim = 3 جدول سه طبقه (مکعب)

---

حالا دیگه هر وقت img[y:y+h, x:x+w] رو دیدی، می‌دونی یعنی "از جدول، سطرهای y تا y+h و ستون‌های x تا x+w رو بده به من".

باز بگو کدوم قسمت هنوز گنگه، همون رو بازتر می‌کنم.
 

saalek110

Well-Known Member
شرح عکس رنگی به شکل ۳ برگ کاغذ

آفرین که اینقدر دقیق می‌خوای! بیا این "۳ برگه" رو طوری باز کنم که دیگه هیچوقت یادت نره.

---

عکس رنگی = یه دفترچه ۳ برگه‌ای

برگه اول: این برگه فقط رنگ آبی رو نشون میده

تصورش کن: یه برگه کاغذ که روش فقط اطلاعات رنگ آبی نوشته شده. هر خونه‌اش یه عدده بین ۰ تا ۲۵۵:

```
برگه آبی (Blue Channel):
┌───────────┬───────────┬───────────┐
│ ۲۵۵ │ ۰ │ ۰ │
│ آبی کامل │ بدون آبی │ بدون آبی │
├───────────┼───────────┼───────────┤
│ ۰ │ ۱۲۸ │ ۰ │
│ بدون آبی │ آبی متوسط│ بدون آبی │
└───────────┴───────────┴───────────┘
```

برگه دوم: این یکی فقط رنگ سبز رو نشون میده

یه برگه دیگه، کاملاً جداگانه، فقط برای سبز:

```
برگه سبز (Green Channel):
┌───────────┬───────────┬───────────┐
│ ۰ │ ۲۵۵ │ ۰ │
│ بدون سبز │ سبز کامل │ بدون سبز │
├───────────┼───────────┼───────────┤
│ ۰ │ ۱۲۸ │ ۲۵۵ │
│ بدون سبز │ سبز متوسط│ سبز کامل │
└───────────┴───────────┴───────────┘
```

برگه سوم: و اینم برگه مربوط به قرمز

```
برگه قرمز (Red Channel):
┌───────────┬───────────┬───────────┐
│ ۰ │ ۰ │ ۲۵۵ │
│ بدون قرمز│ بدون قرمز│ قرمز کامل│
├───────────┼───────────┼───────────┤
│ ۲۵۵ │ ۱۲۸ │ ۰ │
│ قرمز کامل│ قرمز متوسط│ بدون قرمز│
└───────────┴───────────┴───────────┘
```

---

حالا این ۳ تا برگه رو بذار روی هم... عکس رنگی ساخته میشه!

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

```
پیکسل گوشه بالا-چپ:
آبی = ۲۵۵ + سبز = ۰ + قرمز = ۰ = آبی خالص

پیکسل گوشه بالا-راست:
آبی = ۰ + سبز = ۰ + قرمز = ۲۵۵ = ❤️ قرمز خالص

پیکسل وسط:
آبی = ۱۲۸ + سبز = ۱۲۸ + قرمز = ۱۲۸ = خاکستری
```

---

با کد نشون بده!

```python
import numpy as np
import cv2

# یه عکس رنگی ۲×۲ (۲ سطر، ۲ ستون، ۳ برگه)
color_image = np.array([
# سطر ۰ - پیکسل‌ها
[[255, 0, 0], # پیکسل (0,0): آبی=۲۵۵، سبز=۰، قرمز=۰ → آبی خالص
[0, 255, 0]], # پیکسل (0,1): آبی=۰، سبز=۲۵۵، قرمز=۰ → سبز خالص

# سطر ۱ - پیکسل‌ها
[[0, 0, 255], # پیکسل (1,0): آبی=۰، سبز=۰، قرمز=۲۵۵ → قرمز خالص
[128, 128, 128]] # پیکسل (1,1): آبی=۱۲۸، سبز=۱۲۸، قرمز=۱۲۸ → خاکستری
])

print("عکس رنگی ۲×۲:")
print(color_image)
print("\n⫸ Shape:", color_image.shape) # (2, 2, 3)

# جدا کردن برگه‌ها
print("\n" + "="*50)
print(" برگه آبی (همه پیکسل‌ها، فقط رنگ آبی):")
print(color_image[:, :, 0]) # همه سطرها، همه ستون‌ها، برگه ۰ (آبی)

print("\n برگه سبز:")
print(color_image[:, :, 1]) # برگه ۱

print("\n برگه قرمز:")
print(color_image[:, :, 2]) # برگه ۲
```

خروجی رو نگاه کن:

```
برگه آبی (همه پیکسل‌ها، فقط رنگ آبی):
[[255 0] ← پیکسل اول آبی کامل (255)، دومی بدون آبی (0)
[ 0 128]] ← سطر دوم هم همینطور

برگه سبز:
[[ 0 255]
[ 0 128]]

برگه قرمز:
[[ 0 0]
[255 128]]
```

---

️ با یه عکس واقعی تست کن

```python
import cv2
import numpy as np

# یه عکس واقعی از وبکم
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cap.release()

if ret:
# جدا کردن برگه‌ها
blue = frame[:, :, 0] # فقط آبی
green = frame[:, :, 1] # فقط سبز
red = frame[:, :, 2] # فقط قرمز

# هر برگه رو جداگونه نشون بده
cv2.imshow("برگه آبی (Blue)", blue)
cv2.imshow("برگه سبز (Green)", green)
cv2.imshow("برگه قرمز (Red)", red)

# یه ترفند جالب: برگه‌های دیگه رو صفر کن، ببین چی میشه!
only_blue = frame.copy()
only_blue[:, :, 1] = 0 # سبز رو صفر کن
only_blue[:, :, 2] = 0 # قرمز رو صفر کن
cv2.imshow("فقط آبی", only_blue)

cv2.waitKey(0)
cv2.destroyAllWindows()
```

---

چرا اینقدر مهمه؟

وقتی توی OpenCV می‌خوای فقط اشیاء قرمز رو پیدا کنی، داری می‌گی:

```python
# ماسک: فقط پیکسل‌هایی که توی برگه قرمز عددشون بالای ۲۰۰ باشه
red_mask = frame[:, :, 2] > 200 # برگه سوم ← قرمز
```

وقتی می‌خوای عکس رو آبی‌تر کنی:

```python
# برگه آبی رو ۵۰ تا اضافه کن
frame[:, :, 0] = frame[:, :, 0] + 50
```

---

جدول یادگاری (OpenCV از BGR استفاده می‌کنه نه RGB!)

شماره برگه رنگ در OpenCV شاخص
۰ آبی (Blue) [:, :, 0]
۱ سبز (Green) [:, :, 1]
۲ ❤️ قرمز (Red) [:, :, 2]

پس همیشه یادت باشه:

· عکس رنگی = ۳ تا برگه ۲ بعدی کاملاً مجزا
· هر برگه = یه جدول ارتفاع × عرض
· ترکیب سه برگه = ارتفاع × عرض × ۳

حالا فهمیدی چرا shape عکس رنگی (480, 640, 3) هست؟ چون ۴۸۰ سطر داره، ۶۴۰ ستون، و ۳ برگه!

باز سوالی بود؟
 

saalek110

Well-Known Member
سوال خیلی خوبی پرسیدی! این دقیقاً همون چیزیه که باید بدونی تا بفهمی NumPy چرا انقدر تو پردازش تصویر مهمه. بیا ببینیم چه بلایی سر عکس (آرایه) میاریم:

---

️ کارهایی که با آرایهٔ عکس انجام میدیم

۱. نگاه کردن به پیکسل‌ها (خوندن)

می‌خوایم ببینیم توی یه قسمت خاص عکس چه خبره.

```python
import cv2
import numpy as np

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

# یه پیکسل خاص رو بخون
pixel = img[100, 200]
print(f"پیکسل سطر ۱۰۰، ستون ۲۰۰: {pixel}")

# یه ناحیه رو ببین
region = img[0:50, 0:50] # گوشه بالا-چپ
print(f"ناحیه ۵۰×۵۰:\n{region}")
```

---

۲. تغییر دادن پیکسل‌ها (نوشتن)

عکس رو تغییر میدیم، درست مثل پاک‌کن و مداد.

```python
# یه پیکسل رو قرمز کن
img[100, 200] = [0, 0, 255] # BGR: آبی=۰, سبز=۰, قرمز=۲۵۵

# یه ناحیه کامل رو سفید کن
img[0:100, 0:100] = [255, 255, 255]

# یه خط افقی بکش (همه ستون‌های سطر ۵۰ رو سیاه کن)
img[50, :] = [0, 0, 0]
```

---

۳. بریدن و جدا کردن (Crop)

فقط یه تیکه از عکس رو می‌خوایم.

```python
# بریدن صورت از عکس
face = img[100:300, 150:350] # [ارتفاع شروع:پایان, عرض شروع:پایان]

# نصف کردن عکس از وسط
half1 = img[:, :img.shape[1]//2] # نیمه چپ
half2 = img[:, img.shape[1]//2:] # نیمه راست
```

---

۴. چرخوندن و قرینه کردن (Flip)

```python
# قرینه افقی (آینه‌ای)
flipped = img[:, ::-1, :] # ستون‌ها برعکس

# قرینه عمودی
flipped_ud = img[::-1, :, :] # سطرها برعکس

# چرخش ۹۰ درجه با NumPy
rotated = np.rot90(img)
```

---

۵. فیلتر کردن با ماسک (پیدا کردن چیزای خاص)

این مهم‌ترین و قدرتمندترین کاره!

```python
# پیدا کردن پیکسل‌های قرمز
red_mask = img[:, :, 2] > 200 # کدوم پیکسل‌ها قرمزشون بالای ۲۰۰ هست؟

# پیدا کردن پیکسل‌های خیلی روشن
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bright_mask = gray > 200

# پیدا کردن پیکسل‌های خیلی تاریک
dark_mask = gray < 50

# ترکیب شرط‌ها
special = (gray > 100) & (gray < 200) # نه خیلی روشن، نه خیلی تاریک
```

---

۶. شمارش و آمار گرفتن

```python
# چندتا پیکسل قرمز داریم؟
red_pixels = np.sum(img[:, :, 2] > 200)
print(f"تعداد پیکسل‌های قرمز: {red_pixels}")

# میانگین روشنایی کل عکس
avg_brightness = np.mean(gray)
print(f"میانگین روشنایی: {avg_brightness:.2f}")

# تیره‌ترین و روشن‌ترین پیکسل
print(f"تیره‌ترین: {np.min(gray)}")
print(f"روشن‌ترین: {np.max(gray)}")

# چند درصد عکس سفیده؟
white_ratio = np.sum(gray == 255) / gray.size * 100
print(f"درصد سفیدی: {white_ratio:.2f}%")
```

---

۷. جمع و تفریق عکس‌ها (با هم)

```python
# دو عکس رو با هم ترکیب کن (مثل فتوشاپ لایه‌ها)
result = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)

# تفریق دو فریم (پیدا کردن حرکت)
diff = cv2.absdiff(frame1, frame2)

# کم کردن نویز با میانگین چند فریم
avg_frame = np.mean(frames_array, axis=0)
```

---

۸. تغییر اندازه (Resize)

```python
# نصف کردن اندازه
small = cv2.resize(img, (img.shape[1]//2, img.shape[0]//2))

# یا مستقیماً با برش NumPy (نمونه‌برداری)
small_np = img[::2, ::2, :] # یک پیکسل درمیان بردار
```

---

۹. جدا کردن کانال‌های رنگی

```python
# جدا کردن سه برگه
blue = img[:, :, 0]
green = img[:, :, 1]
red = img[:, :, 2]

# فقط کانال قرمز رو نگه دار، بقیه صفر
only_red = np.zeros_like(img)
only_red[:, :, 2] = red

# ترکیب دوباره (مثلاً جابجایی رنگ‌ها)
swapped = np.stack([red, green, blue], axis=2) # BGR → RGB
```

---

۱۰. تبدیل‌های جادویی

```python
# نرمال‌سازی (۰ تا ۱)
normalized = gray / 255.0

# منفی کردن (نگاتیو)
negative = 255 - gray

# افزایش کنتراست
high_contrast = np.clip(gray * 1.5, 0, 255).astype(np.uint8)

# باینری کردن (آستانه‌گیری)
binary = (gray > 127).astype(np.uint8) * 255
```

---

مثال واقعی: تشخیص سون سگمنت

بیایم همه اینارو یه جا ببینیم:

```python
import cv2
import numpy as np

# ۱. عکس رو میخونیم (آرایه میسازیم)
img = cv2.imread('display.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# ۲. عکس رو باینری می‌کنیم (اعداد رو به ۰ و ۲۵۵ تبدیل می‌کنیم)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# ۳. یه سگمنت خاص رو برش میدیم
segment = binary[50:150, 30:80] # Crop

# ۴. می‌شماریم چند درصدش سفیده
brightness = np.sum(segment == 255) / segment.size

# ۵. تصمیم می‌گیریم سگمنت روشنه یا نه
if brightness > 0.5:
print("این سگمنت روشنه! → عدد ۱")
else:
print("این سگمنت خاموشه! → عدد ۰")

# ۶. نتیجه رو نمایش میدیم
cv2.imshow('Segment', segment)
cv2.waitKey(0)
```

---

خلاصه: با آرایه عکس چیکار می‌کنیم؟

کار یعنی مثال
خوندن ببینم این پیکسل چیه img[50, 30]
نوشتن این پیکسل رو عوض کن img[50, 30] = 255
بریدن این تیکه رو جدا کن img[0:100, 0:100]
ماسک زدن فقط پیکسل‌های خاص رو ببین img[img > 200]
شمارش چندتا پیکسل روشن داریم؟ np.sum(img > 200)
آمار میانگین، ماکزیمم، مینیمم np.mean(img)
ترکیب دو عکس رو قاطی کن cv2.addWeighted()
تبدیل نگاتیو، نرمال، باینری 255 - img

---

یادت باشه: همه این کارا بدون NumPy نیاز به کلی حلقه for داره که کند و زشته. با NumPy، یه خط کافیه!
 

saalek110

Well-Known Member
باشه، برگردیم به همون مثال بچگانه. فرض کن عکس یه جدول نقاشی ۳×۳ هست. هر خونه یه عدده.

---

عکس ما = این جدول ۳×۳

فرض کن یه عکس داری که توی هر خونه‌ش یه عدد هست:

```
عکس (یه جدول ساده ۳×۳):
┌──────┬──────┬──────┐
│ ۱۰ │ ۲۰۰ │ ۵۰ │
├──────┼──────┼──────┤
│ ۲۵۵ │ ۰ │ ۱۸۰ │
├──────┼──────┼──────┤
│ ۹۰ │ ۲۲۰ │ ۳۰ │
└──────┴──────┴──────┘
```

---

️ ۵ تا کار اصلی که می‌تونیم بکنیم:

۱. نگاه کردن به یه خونه (خوندن)

"ببینم خونه وسط چند هست؟"

```python
import numpy as np

# جدول عکس رو می‌سازیم
img = np.array([
[10, 200, 50],
[255, 0, 180],
[90, 220, 30]
])

# خونه وسط رو نگاه کن
print(img[1, 1]) # میگه 0
```

یعنی: سطر ۱، ستون ۱ رو بده به من.

---

۲. تغییر دادن یه خونه (نوشتن)

"خونه وسط رو بکن ۱۰۰"

```python
img[1, 1] = 100 # خونه وسط حالا ۱۰۰ شد
print(img)
```

```
قبل: بعد:
┌───┬───┬───┐ ┌───┬───┬───┐
│۱۰ │۲۰۰│۵۰ │ │۱۰ │۲۰۰│۵۰ │
├───┼───┼───┤ ├───┼───┼───┤
│۲۵۵│ ۰ │۱۸۰│ ←── │۲۵۵│۱۰۰│۱۸۰│
├───┼───┼───┤ ├───┼───┼───┤
│۹۰ │۲۲۰│۳۰ │ │۹۰ │۲۲۰│۳۰ │
└───┴───┴───┘ └───┴───┴───┘
```

---

۳. بریدن یه تیکه (قیچی)

"فقط ۲ ستون سمت چپ رو بده به من"

```python
left_part = img[:, 0:2] # همه سطرها، ستون ۰ و ۱
print(left_part)
```

```
عکس اصلی: برش خورده:
┌───┬───┬───┐ ┌───┬───┐
│۱۰ │۲۰۰│۵۰ │ │۱۰ │۲۰۰│
├───┼───┼───┤ ←── ├───┼───┤
│۲۵۵│۱۰۰│۱۸۰│ │۲۵۵│۱۰۰│
├───┼───┼───┤ ├───┼───┤
│۹۰ │۲۲۰│۳۰ │ │۹۰ │۲۲۰│
└───┴───┴───┘ └───┴───┘
```

---

۴. پیدا کردن خونه‌های خاص (عینک جادویی)

"کدوم خونه‌ها روشن‌تر از ۱۵۰ هستن؟"

```python
# عینک جادویی رو می‌زنیم
mask = img > 150
print(mask)
```

```
عکس (اعداد): عینک (بله/خیر):
┌───┬───┬───┐ ┌───┬───┬───┐
│۱۰ │۲۰۰│۵۰ │ │خیر│بله│خیر│
├───┼───┼───┤ ←── ├───┼───┼───┤
│۲۵۵│۱۰۰│۱۸۰│ │بله│خیر│بله│
├───┼───┼───┤ ├───┼───┼───┤
│۹۰ │۲۲۰│۳۰ │ │خیر│بله│خیر│
└───┴───┴───┘ └───┴───┴───┘
```

"حالا فقط اونایی که بله هستن رو بده به من:"

```python
bright_ones = img[mask]
print(bright_ones) # [200, 255, 180, 220]
```

---

۵. شمردن (حساب کتاب)

"چندتا خونه روشن داریم؟"

```python
count = np.sum(mask) # بله‌ها رو جمع کن = ۴ تا
print(count) # 4
```

"میانگین اعداد چنده؟"

```python
avg = np.mean(img) # همه رو جمع کن ÷ تعداد
print(avg) # مثلاً ۱۲۸.۳۳
```

"بزرگترین و کوچکترین عدد؟"

```python
print(np.max(img)) # ۲۵۵
print(np.min(img)) # ۱۰
```

---

همه با هم تو یه داستان واقعی

"عکس یه لامپ داریم، می‌خوایم بفهمیم لامپ روشنه یا نه"

```python
# ۱. عکس لامپ (فرض کن ۴×۴ هست)
lamp = np.array([
[5, 10, 8, 3],
[240, 255, 250, 10],
[230, 245, 240, 8],
[6, 12, 5, 2]
])

# ۲. کدوم خونه‌ها روشن‌تر از ۲۰۰ هستن؟ (عینک)
bright_spots = lamp > 200

# ۳. چندتا خونه روشن داریم؟ (بشمار)
num_bright = np.sum(bright_spots)

# ۴. اگه بیش از ۵ تا خونه روشن بود، لامپ روشنه
if num_bright > 5:
print("لامپ روشنه! ")
else:
print("لامپ خاموشه! ")
```

همین! فقط همین کارا رو انجام می‌دیم:

1. می‌خونیم: img[1, 1]
2. می‌نویسیم: img[1, 1] = 100
3. می‌بُریم: img[:, 0:2]
4. عینک می‌زنیم: img > 200
5. می‌شماریم: np.sum(), np.mean()

همه پردازش تصویر، فقط ترکیب همین ۵ تاست!
 

saalek110

Well-Known Member
بیا اینقدر ساده بگم که حفظش کنی. با یه مثال جدید.

---

عکس = جدول عددها

تصور کن یه کاغذ شطرنجی ۲×۲ داری. توی هر خونه یه عدد نوشتی:

```
┌──────────┬──────────┐
│ ۱۰ │ ۲۰ │
├──────────┼──────────┤
│ ۳۰ │ ۴۰ │
└──────────┴──────────┘
```

همینه! عکس یعنی این. نه چیز دیگه. عدد بزرگتر = روشن‌تر. عدد کوچکتر = تاریک‌تر.

```python
import numpy as np

# همون جدول بالا در کامپیوتر
img = np.array([
[10, 20], # سطر ۰
[30, 40] # سطر ۱
])
```

---

️ فقط ۵ تا کار بلدیم

۱. خوندن: فلان خونه چنده؟

"بگو خونه پایین-چپ (سطر ۱، ستون ۰) چنده؟"

```python
print(img[1, 0]) # میگه ۳۰

# همیشه اول بگو کدوم سطر، بعد کدوم ستون
# img[سطر, ستون]
```

---

۲. نوشتن: فلان خونه رو عوض کن

"خونه بالا-راست رو بکن ۹۹"

```python
img[0, 1] = 99 # سطر ۰، ستون ۱ ← قبلاً ۲۰ بود، حالا ۹۹

print(img)
# [[10, 99],
# [30, 40]]
```

---

۳. بریدن: یه تیکه رو بده به من

"فقط سطر اول رو بده"

```python
print(img[0, :]) # سطر ۰، همه ستون‌ها ← [10, 99]
```

"فقط ستون دوم رو بده"

```python
print(img[:, 1]) # همه سطرها، ستون ۱ ← [99, 40]
```

---

۴. عینک زدن: کدوم خونه‌ها فلان شرط رو دارن؟

"کدوم خونه‌ها بزرگتر از ۲۵ هستن؟"

```python
mask = img > 25
print(mask)
# [[False, True], ← ۱۰ نه، ۹۹ آره
# [True, True]] ← ۳۰ آره، ۴۰ آره

# فقط اون خونه‌ها رو بده
print(img[mask]) # [99, 30, 40]
```

---

۵. شمردن: چندتا خونه فلان شرط رو دارن؟

"چندتا خونه بزرگتر از ۲۵ هست؟"

```python
print(np.sum(mask)) # ۳ تا (True=1, False=0 پس جمعش میشه ۳)
```

"میانگین کل خونه‌ها چنده؟"

```python
print(np.mean(img)) # (10+99+30+40) ÷ ۴ = ۴۴.۷۵
```

---

آزمایشگاه: همه رو با هم تست کن

```python
import numpy as np

# یه عکس ۳×۳ می‌سازیم
img = np.array([
[5, 50, 100], # سطر ۰
[150, 200, 250], # سطر ۱
[10, 20, 30] # سطر ۲
])

print("عکس اصلی:")
print(img)
print()

# ۱. خوندن: خونه وسط چنده؟
print("۱. خونه وسط:", img[1, 1]) # ۲۰۰

# ۲. نوشتن: خونه وسط رو صفر کن
img[1, 1] = 0
print("\n۲. بعد از صفر کردن وسط:\n", img)

# ۳. بریدن: ۲ سطر اول، ۲ ستون اول
crop = img[0:2, 0:2]
print("\n۳. برش ۲×۲ بالا-چپ:\n", crop)

# ۴. عینک: کدوم خونه‌ها بزرگتر از ۱۰۰ هستن؟
mask = img > 100
print("\n۴. ماسک (بزرگتر از ۱۰۰):\n", mask)

# ۵. شمردن: چندتا بزرگتر از ۱۰۰ داریم؟
count = np.sum(mask)
print("\n۵. تعداد بزرگتر از ۱۰۰:", count)

# ۵-ب: میانگین کل عکس
avg = np.mean(img)
print(" میانگین کل:", avg)

# ۵-ج: بزرگترین و کوچکترین
print(" بزرگترین:", np.max(img))
print(" کوچکترین:", np.min(img))
```

---

عکس رنگی چیه؟ ۳ تا از همین جدول‌ها

عکس رنگی همونه، فقط ۳ تا جدول داری (یکی برای آبی، یکی سبز، یکی قرمز):

```python
# عکس ۲×۲ رنگی
color = np.array([
[[255, 0, 0], [0, 255, 0]], # سطر ۰
[[0, 0, 255], [128, 128, 128]] # سطر ۱
])

# تفاوت فقط اینه: هر خونه به‌جای یه عدد، ۳ عدد داره
print(color[0, 0]) # [255, 0, 0] یعنی آبی خالص

# اما کارا همونه! عینک زدن:
# کدوم پیکسل‌ها قرمزشون بالای ۱۰۰ هست؟
red_mask = color[:, :, 2] > 100 # برگه قرمز رو چک کن
print(red_mask)
```

---

این ۳ جمله رو حفظ کن

کاری که می‌کنی چطور می‌گی
می‌خونی img[سطر, ستون]
می‌نویسی img[سطر, ستون] = عدد
می‌بُری img[سطر_شروع:پایان, ستون_شروع:پایان]
عینک می‌زنی img > عدد
می‌شاری np.sum(mask), np.mean(img)

---

حالا تو بگو: با این جدول، چه کاری می‌خوای بکنی تا من برات کدش رو بنویسم؟

```
عکس:
┌───┬───┬───┐
│۱۰ │۹۰ │۴۰ │
├───┼───┼───┤
│۶۰ │۲۵۵│۷۰ │
├───┼───┼───┤
│۲۰ │۸۰ │۵۰ │
└───┴───┴───┘
```

بگو مثلاً "می‌خوام خونه‌های بزرگتر از ۸۰ رو سفید کنم" یا "می‌خوام سطر وسط رو بده به من". هرچی دوست داری بگو تا کدشو بنویسم.
 

saalek110

Well-Known Member
بسیار عالی. این دقیقاً کار درستیه. بیا اصلاً قید عکس و OpenCV رو بزنیم. برگردیم به خودِ NumPy. می‌خوام ببینی NumPy فقط یه ماشین حساب غول‌پیکره.

---

NumPy چیه؟ یه ماشین حساب که به جای یه عدد، با میلیون‌ها عدد یکجا کار می‌کنه

تصور کن:

· پایتون معمولی: یه ماشین حساب جیبی داری. اعداد رو یکی‌یکی می‌دی بهش، جواب رو یکی‌یکی پس می‌گیری.
· NumPy: یه کارخانه داری. یه کانتینر پر از عدد می‌دی بهش، یه کانتینر پر از جواب تحویل می‌گیری. همه با هم.

---

NumPy دقیقاً چه کارایی می‌کنه؟ (۴ تا کار اصلی)

۱. ریاضی رو سریع می‌کنه (برداری)

فرض کن یه لیست از حقوق داری و می‌خوای ۲۰٪ به همه اضافه کنی.

پایتون معمولی (کند، با حلقه):

```python
salaries = [1000, 2000, 1500, 3000]
new_salaries = []
for s in salaries:
new_salaries.append(s * 1.2)
# طولانیه، به خصوص اگه ۱ میلیون حقوق داشته باشی
```

NumPy (سریع، بدون حلقه):

```python
import numpy as np

salaries = np.array([1000, 2000, 1500, 3000])
new_salaries = salaries * 1.2 # تموم! همه در یک لحظه محاسبه شدن

print(new_salaries) # [1200. 2400. 1800. 3600.]
```

اینجا NumPy چیکار کرد؟ به کارخانه‌اش گفت: "همه اعداد داخل این کانتینر رو بردار، ضربدر ۱.۲ کن، بذار کانتینر جدید." بدون اینکه برای تک‌تک اعداد وقت تلف کنه.

---

۲. جدول‌ها (ماتریس‌ها) رو مثل آب خوردن مدیریت می‌کنه

داده‌های واقعی معمولاً جدولی هستن. مثل جدول نمرات دانشجوها:

```
نمرات:
ریاضی فیزیک شیمی
علی ۱۸ ۱۵ ۱۷
مریم ۲۰ ۱۹ ۱۸
رضا ۱۲ ۱۴ ۱۱
```

NumPy این جدول رو یه جا می‌گیره و هرکاری می‌خوای باهاش می‌کنه:

```python
grades = np.array([
[18, 15, 17], # علی
[20, 19, 18], # مریم
[12, 14, 11] # رضا
])

# میانگین هر دانشجو (میانگین هر سطر)
print(grades.mean(axis=1)) # [16.66, 19., 12.33]

# میانگین هر درس (میانگین هر ستون)
print(grades.mean(axis=0)) # [16.66, 16., 15.33]

# بالاترین نمره کل جدول
print(grades.max()) # ۲۰

# نمرات علی (سطر اول)
print(grades[0, :]) # [18, 15, 17]

# نمرات فیزیک (ستون دوم)
print(grades[:, 1]) # [15, 19, 14]
```

اینجا NumPy چیکار کرد؟ بهش گفتی "این جدول رو بگیر، از یه بُعد خاص میانگین بگیر، یا یه سطر یا ستونش رو بده به من". همه رو بدون حلقه انجام داد.

---

۳. داده‌ها رو فیلتر می‌کنه (با شرط)

"از این همه عدد، فقط اونایی که فلان شرط رو دارن بده به من."

```python
temps = np.array([25, 32, 18, 40, 22, 38, 15])

# فقط روزایی که هوا گرمتر از ۳۰ درجه بوده
hot_days = temps[temps > 30]
print(hot_days) # [32, 40, 38]

# چند روز گرم داشتیم؟
print(np.sum(temps > 30)) # ۳ روز

# روزای گرم رو با یه شرط دیگه عوض کن
temps[temps > 30] = 99
print(temps) # [25, 99, 18, 99, 22, 99, 15]
```

اینجا NumPy چیکار کرد؟ یه ماسک (اون عینک جادویی) ساخت که فقط اعداد بزرگتر از ۳۰ رو نشون میده. بعد هر کاری خواستی باهاشون کرد.

---

۴. جبر و آمار و احتمال رو قورت می‌ده

NumPy کلی تابع آماده داره برای محاسبات سنگین:

```python
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

# آمار توصیفی
print(np.mean(data)) # میانگین: ۵.۵
print(np.median(data)) # میانه: ۵.۵
print(np.std(data)) # انحراف معیار: ۲.۸۷
print(np.var(data)) # واریانس: ۸.۲۵

# جبر خطی
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(A @ B) # ضرب ماتریسی

# تولید اعداد تصادفی
random_numbers = np.random.randn(1000) # ۱۰۰۰ عدد تصادفی از توزیع نرمال
```

---

جمع‌بندی نهایی: NumPy چیه واقعاً؟

NumPy یه "اعداد پشت سر هم" (آرایه) رو جایگزین "عدد تنها" می‌کنه.

کار بدون NumPy با NumPy
ورودی عدد آرایه (کانتینر عدد)
عملیات +, -, *, / روی تک عدد +, -, *, / روی کل آرایه
فیلتر if x > 5: arr[arr > 5]
آمار sum(list) arr.sum(), arr.mean()
جبر حلقه و لیست A @ B, np.linalg.inv(A)

شعار NumPy: "حلقه ننویس. بگو چه کاری می‌خوای روی کل داده‌ات انجام بشه."

---
 

saalek110

Well-Known Member
آفرین! بریم تو دل کارخانه NumPy رو ببینیم.

---

کارخانه NumPy چطور کار می‌کنه؟

۱. کانتینر مخصوص (آرایه)

کارخانه فقط یه جور کانتینر قبول می‌کنه: آرایه. یعنی همه چی باید هم‌شکل باشه.

```python
import numpy as np

# اینو نمیشه داد به کارخانه (قاطیه)
# bad = np.array([1, "hello", 3.14])

# اینو میشه داد (همه عددن)
good = np.array([1, 2, 3, 4, 5])
print(good) # [1 2 3 4 5]
```

---

۲. سه تا تکنیک اصلی کارخانه

تکنیک اول: پخش کردن (Broadcasting)

فرض کن می‌خوای به همه کارگرا ۱۰۰ تومن پاداش بدی. نمی‌ری تک‌تک بدی، یه بلندگو می‌گی: "همه ۱۰۰ تومن!"

```python
salaries = np.array([1000, 2000, 1500, 3000])

# عدد ۱۰۰ به همه خونه‌ها پخش میشه
new_salaries = salaries + 100
print(new_salaries) # [1100 2100 1600 3100]
```

یه مثال پیچیده‌تر:

```python
# قیمت ۳ تا محصول
prices = np.array([10, 20, 30])

# تعداد فروش هر محصول در ۴ روز
sales = np.array([
[1, 2, 1], # روز ۱
[2, 0, 3], # روز ۲
[1, 1, 1], # روز ۳
[0, 2, 2] # روز ۴
])

# درآمد هر روز = قیمت × تعداد فروش
# prices (3تا) به همه ۴ سطر پخش میشه
revenue = sales * prices
print(revenue)
# [[10, 40, 30],
# [20, 0, 90],
# [10, 20, 30],
# [ 0, 40, 60]]
```

---

تکنیک دوم: ماسک‌ها (فیلتر کردن)

نمی‌ری تک‌تک بپرسی "تو فلان شرط رو داری؟" یه غربال می‌ذاری، هرچی رد شد می‌ریزه توی سطل.

```python
scores = np.array([12, 18, 9, 20, 14, 7, 16])

# غربال: کدوم‌ها بالای ۱۵ هستن؟
mask = scores > 15
print(mask) # [False True False True False False True]

# فقط اونایی که از غربال رد شدن
good_scores = scores[mask]
print(good_scores) # [18 20 16]

# چندتا بودن؟
print(np.sum(mask)) # ۳ تا

# همشون رو ۲۰ کن
scores[mask] = 20
print(scores) # [12 20 9 20 14 7 20]
```

---

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

یه کیک داری، می‌خوای یه تیکه رو ببُری. با چاقو می‌بُری، نه اینکه دونه‌دونه با موچین جدا کنی.

```python
data = np.array([10, 20, 30, 40, 50, 60, 70, 80])

# از ایندکس ۲ تا ۵ (بدون ۵)
print(data[2:5]) # [30 40 50]

# از اول تا ۴
print(data[:4]) # [10 20 30 40]

# از ۴ تا آخر
print(data[4:]) # [50 60 70 80]

# یک درمیون
print(data[::2]) # [10 30 50 70]

# برعکس
print(data[::-1]) # [80 70 60 50 40 30 20 10]
```

برای جدول‌ها:

```python
table = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
])

# برش: سطرهای ۰ و ۱، ستون‌های ۱ و ۲
print(table[0:2, 1:3])
# [[2, 3],
# [6, 7]]

# برش: همه سطرها، ستون آخر
print(table[:, -1]) # [4, 8, 12]

# برش: سطر آخر، همه ستون‌ها
print(table[-1, :]) # [9, 10, 11, 12]
```

---

جعبه ابزار طلایی (توابعی که همیشه لازم میشه)

```python
arr = np.array([5, 2, 8, 2, 5, 1, 9, 5])

# ----- پیدا کردن -----
print(np.unique(arr)) # [1 2 5 8 9] - عناصر یکتا
print(np.unique(arr, return_counts=True)) # (array([1,2,5,8,9]), array([1,2,3,1,1]))

# ----- مرتب‌سازی -----
print(np.sort(arr)) # [1 2 2 5 5 5 8 9] - مرتب شده
print(np.argsort(arr)) # [5 1 3 0 4 7 2 6] - ایندکس‌های مرتب

# ----- آمار -----
print(np.mean(arr)) # میانگین
print(np.median(arr)) # میانه
print(np.percentile(arr, 50)) # صدک (میانه)
print(np.percentile(arr, 90)) # صدک ۹۰

# ----- کجاها؟ -----
print(np.where(arr > 5)) # (array([2, 6]),) - ایندکس‌ها
print(np.argmax(arr)) # ۲ - ایندکس بزرگترین
print(np.argmin(arr)) # ۵ - ایندکس کوچکترین

# ----- محدود کردن -----
print(np.clip(arr, 2, 7)) # [5 2 7 2 5 2 7 5] - بین ۲ تا ۷
```

---

خط تولید NumPy — قدم به قدم

```
مواد خام ماشین NumPy محصول نهایی
(لیست پایتون) (آرایه) (آرایه جدید)
═══════════ ═══════════ ════════════
[1,2,3,4,5] → np.array([...]) → [2 4 6 8 10]
× ۲
بدون حلقه!
```

---

یک مثال کامل برای جمع‌بندی

فرض کن دمای یک هفته رو داری:

```python
temps = np.array([22, 25, 19, 30, 28, 35, 18])

# ۱. چند روز گرمتر از ۲۵ درجه؟
hot = np.sum(temps > 25)
print(f"روزهای گرم: {hot}")

# ۲. میانگین دما
avg = np.mean(temps)
print(f"میانگین: {avg}")

# ۳. دمای روزهای گرم رو ۵ درجه کم کن (کولر روشن کن)
temps[temps > 25] = temps[temps > 25] - 5
print(f"بعد از کولر: {temps}")

# ۴. ۳ روز اول
print(f"۳ روز اول: {temps[:3]}")

# ۵. سردترین و گرمترین
print(f"سردترین: {np.min(temps)}، گرمترین: {np.max(temps)}")
```

---

باز می‌خوای یه بخش رو بازتر کنم یا تمرین بدی؟
 

saalek110

Well-Known Member
عالیه! حس می‌کنم داری می‌رسی به اون لحظه "آهااااان!" که همه چی یهو جا می‌افته. با ساده‌ترین حرفای دنیا.

---

NumPy = یه نجار با یه اره برقی

تصور کن یه نجار داری. قبلاً با اره دستی کار می‌کرد (پایتون معمولی). حالا یه اره برقی خریده (NumPy).

اره دستی: هر تخته رو یکی‌یکی می‌بری. ۱۰۰ تا تخته = ۱۰۰ بار برش.

اره برقی NumPy: ۱۰۰ تا تخته رو می‌ذاری روی هم، یه بار اره رو روشن می‌کنی، همه رو با هم می‌بُری!

```python
import numpy as np

# ۱۰۰ تا تخته (عدد)
boards = np.array([1, 2, 3, ..., 100]) # ولش کن اینو

# اره برقی: همه رو یکجا نصف کن
half = boards / 2 # تموم! ۱۰۰ تا تخته یکجا نصف شدن
```

---

آرایه = کارتون تخم‌مرغ

لیست پایتون = یه کیسه که هرچی توش می‌ریزی (تخم‌مرغ، سیب، کتاب).

آرایه NumPy = شانه تخم‌مرغ. فقط تخم‌مرغ توش جا می‌گیره، همه خونه‌ها هم اندازه‌ن، و می‌تونی با یه دست کل شانه رو برداری.

```python
# این شانه تخم‌مرغ ۶ تایی
eggs = np.array([1, 2, 3, 4, 5, 6])

# می‌خوای به همهشون یه دونه اضافه کنی؟
eggs = eggs + 1
print(eggs) # [2, 3, 4, 5, 6, 7] ← همه با هم یک دونه اضافه گرفتن
```

حالا جدول (عکس) = کارتون بزرگ که چندتا شانه توشه:

```python
# کارتون ۲×۳ (۲ سطر، ۳ ستون)
carton = np.array([
[1, 2, 3],
[4, 5, 6]
])

# همه تخم‌مرغ‌های سطر اول
print(carton[0, :]) # [1, 2, 3]

# همه تخم‌مرغ‌های ستون وسط
print(carton[:, 1]) # [2, 5]
```

---

سه تا کلمه جادویی NumPy

۱. "همه" = :

```python
arr = np.array([10, 20, 30, 40, 50])

print(arr[:]) # همه رو بده: [10, 20, 30, 40, 50]
print(arr[1:4]) # از ۱ تا ۴: [20, 30, 40]
print(arr[2:]) # از ۲ تا آخر: [30, 40, 50]
print(arr[:3]) # از اول تا ۳: [10, 20, 30]
```

۲. "کدوم‌ها" = >, <, ==

```python
ages = np.array([15, 22, 17, 30, 12])

# کدوم‌ها بزرگتر از ۱۸ هستن؟
print(ages > 18) # [False, True, False, True, False]

# فقط همون‌ها رو بده
print(ages[ages > 18]) # [22, 30]
```

۳. "چندتا" = np.sum() روی درست/غلط‌ها

```python
ages = np.array([15, 22, 17, 30, 12])

# چندتا بزرگتر از ۱۸ داریم؟
grown_ups = ages > 18 # [False, True, False, True, False]
count = np.sum(grown_ups) # True=1, False=0 → 2
print(count) # ۲ نفر
```

---

کنترل بازی با NumPy

دکمه فرمان NumPy معنی
arr + 10 به همه ۱۰ اضافه کن
arr * 2 همه رو دوبرابر کن
arr[2:5] از خونه ۲ تا ۵ رو بده
arr > 50 بگو کدوم‌ها بزرگتر از ۵۰ هستن
arr[arr > 50] فقط بزرگتر از ۵۰ها رو بده
np.sum(arr > 50) بشمر چندتا بزرگتر از ۵۰ هست
⚪ np.mean(arr) میانگین همه رو حساب کن

---

آزمایشگاه نهایی (همه رو قاطی کن)

```python
import numpy as np

# ۵ تا دانشجو، نمره‌هاشون
grades = np.array([12, 19, 8, 20, 15])

print("نمره‌ها:", grades)

# ۱. به همه ۲ نمره ارفاق
grades = grades + 2
print("بعد ارفاق:", grades)

# ۲. کدوم‌ها قبول شدن؟ (بالای ۱۰)
passed = grades > 10
print("قبول‌ها:", grades[passed])

# ۳. چند نفر قبول شدن؟
print("تعداد قبولی‌ها:", np.sum(passed))

# ۴. معدل کلاس
print("معدل:", np.mean(grades))

# ۵. بهترین و بدترین نمره
print("بهترین:", np.max(grades))
print("بدترین:", np.min(grades))

# ۶. نمره‌های قبولی رو ۲۰ کن
grades[passed] = 20
print("نهایی:", grades)
```

خروجی:

```
نمره‌ها: [12 19 8 20 15]
بعد ارفاق: [14 21 10 22 17]
قبول‌ها: [14 21 22 17]
تعداد قبولی‌ها: ۴
معدل: 16.8
بهترین: 22
بدترین: 10
نهایی: [20 20 10 20 20]
```

---

فقط این ۳ خط رو حفظ کن، کافیه

```python
# ۱. همه رو یه کاری کن
arr = arr + 5

# ۲. یه قسمت رو بردار
arr[2:5]

# ۳. شرط بذار
arr[arr > 10]
```

هرچی می‌خوای یاد بگیری، اول برگرد به همین ۳ تا. بقیه فقط ترکیب ایناس.

باز بگو چی رو باز کنم؟
 

saalek110

Well-Known Member
بیا همه چی رو از بیخ باز کنیم. انگار که هیچی نمی‌دونیم.

---

بخش ۱: NumPy اصلاً چی رو حل می‌کنه؟ (مشکل)

پایتون برای عددها کند و پرحرفه.

```python
# فرض کن ۵ تا عدد داری
a = [1, 2, 3, 4, 5]

# می‌خوای همه رو ۲ برابر کنی. مجبوری حلقه بزنی:
result = []
for x in a:
result.append(x * 2)

# ۵ خط برای ۵ تا عدد!
# حالا تصور کن ۵ میلیون عدد باشه...
```

NumPy اومد گفت: "داداش، بگو همه رو ۲ برابر کن، تموم."

```python
import numpy as np
a = np.array([1, 2, 3, 4, 5])
result = a * 2 # یه خط. برا ۵ میلیون هم یه خط.
```

---

بخش ۲: آرایه دقیقاً چیه؟ (قلب NumPy)

لیست = کیسه خرید

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

```python
bag = [1, "hello", 3.14, [5, 6]]
```

آرایه = شانه تخم‌مرغ

فقط عدد. فقط هم‌اندازه. فقط منظم.

```python
eggs = np.array([1, 2, 3, 4, 5])
```

چرا شانه تخم‌مرغ بهتره؟

چون می‌دونی همه خونه‌ها عین همن. پس می‌تونی بگی "همه رو ۲ برابر کن" و ماشین می‌دونه یعنی چه. برای کیسه خرید، باید بری تک‌تک ببینی هرچی داخلشه چی هست.

۳ قانون شانه تخم‌مرغ:

1. همه چی توش هم‌جنسه (فقط عدد)
2. هر خونه دقیقاً یه اندازه جا می‌گیره
3. شماره خونه‌ها از ۰ شروع میشه

---

بخش ۳: ابعاد (Dimension) یعنی چی؟

یک‌بعدی = یه ردیف

```
[10, 20, 30, 40, 50]
```

مثل قطار. فقط طول داره. ۵ تا واگن.

```python
train = np.array([10, 20, 30, 40, 50])
print(train.shape) # (5,) یعنی ۵ تا واگن
```

دوبعدی = یه جدول (سطر و ستون)

```
سطر ۰: [1, 2, 3]
سطر ۱: [4, 5, 6]
سطر ۲: [7, 8, 9]
```

مثل صفحه شطرنج. طول و عرض داره.

```python
table = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print(table.shape) # (3, 3) یعنی ۳ سطر، ۳ ستون
```

سه‌بعدی = جدول‌های روی هم

```
برگه ۰: برگه ۱:
[1, 2, 3] [10, 20, 30]
[4, 5, 6] [40, 50, 60]
```

مثل یه دفترچه. چندتا برگه، هر برگه یه جدول.

```python
book = np.array([
[[1, 2, 3], [4, 5, 6]], # برگه ۰
[[10, 20, 30], [40, 50, 60]] # برگه ۱
])
print(book.shape) # (2, 2, 3) یعنی ۲ برگه، هر برگه ۲ سطر، ۳ ستون
```

عکس رنگی = ۳ برگه روی هم (آبی، سبز، قرمز).

---

بخش ۴: خوندن از آرایه (Indexing)

قانون طلایی: اول سطر، بعد ستون.

```python
table = np.array([
[1, 2, 3], # سطر ۰
[4, 5, 6], # سطر ۱
[7, 8, 9] # سطر ۲
])
# ستون ۰ ۱ ۲
```

آدرس معنی جواب
table[1, 2] سطر ۱، ستون ۲ ۶
table[0, 0] سطر ۰، ستون ۰ ۱
table[2, 1] سطر ۲، ستون ۱ ۸

برای خوندن یه سطر کامل:

```python
print(table[0, :]) # سطر ۰، همه ستون‌ها → [1, 2, 3]
print(table[1, :]) # سطر ۱، همه ستون‌ها → [4, 5, 6]
```

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

```python
print(table[:, 0]) # همه سطرها، ستون ۰ → [1, 4, 7]
print(table[:, 2]) # همه سطرها، ستون ۲ → [3, 6, 9]
```

اشتباه رایج: table[0, :] با table[:, 0] فرق داره!

· table[0, :] = یه سطر افقی
· table[:, 0] = یه ستون عمودی

---

بخش ۵: برش زدن (Slicing)

فرمول: [شروع:پایان]

مهم: "پایان" خودش شامل نمیشه.

```python
arr = np.array([10, 20, 30, 40, 50, 60, 70])

# از ایندکس ۲ تا ۵ (یعنی ۳۰ تا ۶۰)
print(arr[2:6]) # [30, 40, 50, 60]
# چرا ۶؟ چون arr[6]=70 هست و ۷۰ رو نمی‌خوایم
```

برش معنی جواب
arr[0:3] از اول تا قبل از ۳ [10, 20, 30]
arr[3:6] از ۳ تا قبل از ۶ [40, 50, 60]
arr[:4] از اول تا قبل از ۴ [10, 20, 30, 40]
arr[4:] از ۴ تا آخر [50, 60, 70]
arr[:] همه [10, 20, ..., 70]
arr[::2] یک درمیون [10, 30, 50, 70]
arr[::-1] برعکس [70, 60, ..., 10]

برای جدول:

```python
table = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
])

# سطرهای ۰ و ۱، ستون‌های ۱ و ۲
print(table[0:2, 1:3])
# [[2, 3],
# [6, 7]]
```

---

بخش ۶: ماسک (عینک جادویی)

سه قدم همیشگی:

```python
temps = np.array([22, 35, 18, 40, 28])

# قدم ۱: یه عینک بساز که فقط بالای ۳۰ رو نشون بده
mask = temps > 30
print(mask) # [False, True, False, True, False]

# قدم ۲: با عینک نگاه کن
hot = temps[mask]
print(hot) # [35, 40]

# قدم ۳: بشمر
count = np.sum(mask)
print(count) # ۲
```

شرط‌های ترکیبی:

```python
# نه خیلی سرد، نه خیلی گرم: بین ۲۰ و ۳۰
good = temps[(temps >= 20) & (temps <= 30)]
print(good) # [22, 28]

# علامت & یعنی "و"
# علامت | یعنی "یا"
# علامت ~ یعنی "نقیض"
```

---

بخش ۷: پخش شدن (Broadcasting)

قانون: عدد تنها به همه خونه‌ها پخش میشه.

```python
arr = np.array([1, 2, 3, 4])

print(arr + 10) # [11, 12, 13, 14]
print(arr - 5) # [-4, -3, -2, -1]
print(arr * 3) # [3, 6, 9, 12]
print(arr / 2) # [0.5, 1., 1.5, 2.]
print(arr ** 2) # [1, 4, 9, 16]
```

یه ردیف به جدول پخش میشه:

```python
table = np.array([
[1, 2, 3],
[4, 5, 6]
])

# یه ردیف که می‌خوایم به همه سطرها اضافه بشه
row = np.array([10, 20, 30])

print(table + row)
# [[11, 22, 33],
# [14, 25, 36]]
```

یه ستون به جدول پخش میشه:

```python
# یه ستون که می‌خوایم به همه ستون‌ها اضافه بشه
col = np.array([[100], [200]])

print(table + col)
# [[101, 102, 103],
# [204, 205, 206]]
```

---

بخش ۸: توابعی که همیشه لازم میشه

آمار

```python
arr = np.array([5, 2, 8, 2, 5, 1, 9, 5])

np.mean(arr) # میانگین → ۴.۶۲۵
np.median(arr) # میانه → ۵
np.min(arr) # کوچکترین → ۱
np.max(arr) # بزرگترین → ۹
np.sum(arr) # جمع کل → ۳۷
np.std(arr) # انحراف معیار (تفرق)
np.var(arr) # واریانس
```

جستجو

```python
arr = np.array([5, 2, 8, 2, 5, 1, 9, 5])

np.unique(arr) # [1, 2, 5, 8, 9] — بدون تکرار
np.unique(arr, return_counts=True) # (مقادیر, تعداد هرکدوم)
np.argmax(arr) # ۶ — ایندکس بزرگترین
np.argmin(arr) # ۵ — ایندکس کوچکترین
np.where(arr > 5) # (array([2, 6]),) — ایندکس‌ها
np.sort(arr) # [1, 2, 2, 5, 5, 5, 8, 9]
```

تولید عدد

```python
np.zeros(5) # [0., 0., 0., 0., 0.]
np.ones(5) # [1., 1., 1., 1., 1.]
np.arange(0, 10, 2) # [0, 2, 4, 6, 8] — مثل range
np.linspace(0, 1, 5) # [0., 0.25, 0.5, 0.75, 1.] — ۵ عدد مساوی
np.random.rand(5) # ۵ عدد تصادفی بین ۰ و ۱
np.random.randint(1, 10, 5) # ۵ عدد صحیح تصادفی بین ۱ و ۱۰
```

---

بخش ۹: شکل (Shape) و تغییر شکل (Reshape)

Shape یعنی چی؟ تعداد خونه‌های هر بُعد.

```python
arr = np.array([1, 2, 3, 4, 5, 6])
print(arr.shape) # (6,) ← یه ردیف ۶ تایی

# تبدیل به جدول ۲×۳
table = arr.reshape(2, 3)
print(table)
# [[1, 2, 3],
# [4, 5, 6]]
print(table.shape) # (2, 3)

# تبدیل به جدول ۳×۲
table2 = arr.reshape(3, 2)
print(table2)
# [[1, 2],
# [3, 4],
# [5, 6]]

# خودت حساب کن: با -۱
auto = arr.reshape(2, -1) # یعنی ۲ سطر، بقیه رو خودت حساب کن
print(auto.shape) # (2, 3)
```

---

بخش ۱۰: جمع و میانگین روی محورها (Axis)

Axis یعنی جهت حرکت.

· axis=0 = عمودی (ستون‌ها رو با هم ترکیب کن)
· axis=1 = افقی (سطرها رو با هم ترکیب کن)

```python
table = np.array([
[1, 2, 3],
[4, 5, 6]
])

# جمع روی axis=0 (عمودی: سطرها رو با هم جمع کن)
print(np.sum(table, axis=0)) # [5, 7, 9]
# توضیح: 1+4=5, 2+5=7, 3+6=9

# جمع روی axis=1 (افقی: ستون‌ها رو با هم جمع کن)
print(np.sum(table, axis=1)) # [6, 15]
# توضیح: 1+2+3=6, 4+5+6=15
```

ترفند انگشتی:

· انگشتت رو عمودی بکش ← axis=0 ← سطرها ترکیب میشن
· انگشتت رو افقی بکش ← axis=1 ← ستون‌ها ترکیب میشن

---

کل NumPy در یک برگه

```
┌──────────────────────────────────────────────────┐
│ NumPy = کار با آرایه │
│ │
│ آرایه = شانه تخم‌مرغ (فقط عدد، منظم، هم‌اندازه) │
│ │
│ کارها: │
│ ┌─────────────────────────────────────────────┐ │
│ │ خوندن arr[2, 5] │ │
│ │ نوشتن arr[2, 5] = 99 │ │
│ │ بریدن arr[0:3, 1:4] │ │
│ │ فیلتر arr[arr > 100] │ │
│ │ ریاضی arr + 10, arr * 2 │ │
│ │ آمار np.mean(arr), np.sum(arr) │ │
│ │ شکل arr.shape, arr.reshape(2,3) │ │
│ └─────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
```

---
 

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

بالا