Saralash, qidirish va rasm — bu ham array
Sahna: "eng yaxshi uchtasi qaysi?"
Har hafta bir xil savollar keladi: eng ko'p sotilgan 3 mahsulot qaysi? Qaysi mahsulotlar hech sotilmadi? Mijozlar qaysi shaharlardan? Bu bobning birinchi yarmi — saralash va qidirish. Ikkinchi yarmida esa NumPy ni kutilmagan joyda ko'ramiz: rasm ham — sonlar jadvali.
sort va argsort
import numpy as np mahsulotlar = np.array(["non", "sut", "guruch", "yog'", "choy", "shakar", "un"]) sotildi = np.array([340, 125, 210, 95, 260, 180, 300]) print(np.sort(sotildi)) tartib = np.argsort(sotildi) print(tartib) print("eng ko'p sotilgan 3 tasi:", mahsulotlar[tartib[::-1][:3]], sotildi[tartib[::-1][:3]])
[ 95 125 180 210 260 300 340] [3 1 5 2 4 6 0] eng ko'p sotilgan 3 tasi: ['non' 'un' 'choy'] [340 300 260]
np.sort — saralangan qiymatlar. Lekin "qaysi mahsulot?" degan savolga u javob bermaydi: saralangan sonlar ismlaridan ajralib qoldi.
np.argsort — saralangan tartibdagi indekslar: "eng kichigi 3-o'rinda, keyingisi 1-o'rinda..." Shu indekslar bilan ism ham, son ham bir xil tartibda olinadi. [::-1] — teskari (kattadan kichikka), [:3] — birinchi uchtasi. Bu juftlik — "top-N" savollarining universal javobi.
2D da axis bilan ishlaydi:
haftalar = np.array([[340, 125, 210], [310, 150, 190], [360, 110, 230]]) print(np.sort(haftalar, axis=1)) print(np.argsort(-haftalar, axis=1)[:, 0])
[[125 210 340] [150 190 310] [110 230 360]] [0 0 0]
-haftalar — kamayish tartibi uchun eng oddiy hiyla: manfiy sonlar teskari saralanadi. Har qatorning [0] i — o'sha haftaning eng yaxshi mahsuloti indeksi.
unique: nimalar bor va necha marta
shaharlar = np.array(["Toshkent", "Samarqand", "Toshkent", "Buxoro", "Toshkent", "Samarqand", "Namangan"]) nomlar, soni = np.unique(shaharlar, return_counts=True) for n, s in zip(nomlar, soni): print(f"{n:<10} {s}") print("eng ko'p:", nomlar[soni.argmax()])
Buxoro 1 Namangan 1 Samarqand 2 Toshkent 3 eng ko'p: Toshkent
np.unique takrorlarni olib tashlab, saralangan noyob qiymatlarni beradi. return_counts=True — har biri necha marta uchragani. pandas da shuning qulayroq varianti bor — value_counts (10-bob).
isin va where: qaysilari, qayerda
aksiya = ["sut", "choy", "qahva"] print(np.isin(mahsulotlar, aksiya)) print("aksiyadagi mahsulotlar savdosi:", sotildi[np.isin(mahsulotlar, aksiya)].sum()) print("200 dan kam sotilganlar indeksi:", np.where(sotildi < 200)[0])
[False True False False True False False] aksiyadagi mahsulotlar savdosi: 385 200 dan kam sotilganlar indeksi: [1 3 5]
np.isin — har element berilgan ro'yxatda bormi ("qahva" do'konda yo'q — hech narsa buzilmaydi). np.where(shart) bitta argument bilan — shart rost bo'lgan indekslar (3-bobdagi nonzero bilan bir xil).
Rasm — sonlar jadvali
Endi kutilmagan qism. Kompyuter uchun rangli rasm — 3 o'lchamli array: balandlik × kenglik × 3 rang kanali (qizil, yashil, ko'k). Har katak — 0 dan 255 gacha butun son: qanchalik yorqin.
Bu yerda dasturlash tarixining afsonasi — Grace Hopper suratini ishlatamiz (AQSh harbiy-dengiz flotining rasmi, ochiq foydalanishda; Matplotlib bilan birga keladi).
rasm = plt.imread(DATA / "grace_hopper.jpg") print(type(rasm).__name__, rasm.shape, rasm.dtype) print("chap yuqori piksel (R, G, B):", rasm[0, 0]) print("eng qorong'i va eng yorqin:", rasm.min(), rasm.max()) plt.imshow(rasm) plt.axis("off") plt.show()
ndarray (600, 512, 3) uint8 chap yuqori piksel (R, G, B): [21 24 77] eng qorong'i va eng yorqin: 0 255

plt.imread rasmni oddiy NumPy array qilib qaytaradi: shakli (600, 512, 3) — 600 piksel balandlik, 512 kenglik, 3 kanal. dtype — uint8: 0..255 oralig'idagi butun son (2-bobda ko'rgan "kichik" tur — har piksel kanali atigi 1 bayt).
Rasm array bo'lgani uchun oldingi 6 bobdagi hamma narsa unga ishlaydi.
Kesish — rasmni qirqish
yuz = rasm[60:340, 140:400] print(yuz.shape) plt.imshow(yuz) plt.axis("off") plt.show()
(280, 260, 3)

3-bobdagi slicing: qatorlar 60–340, ustunlar 140–400, kanallar — hammasi. Natija — view: rasm ko'chirilmadi.
Kanallar — rang qatlamlari
fig, axlar = plt.subplots(1, 3, figsize=(10, 3.6)) for i, (ax, nom) in enumerate(zip(axlar, ["qizil", "yashil", "ko'k"])): faqat_bitta = np.zeros_like(rasm) faqat_bitta[:, :, i] = rasm[:, :, i] ax.imshow(faqat_bitta) ax.set_title(f"{nom} kanal, o'rtacha {rasm[:, :, i].mean():.0f}") ax.axis("off") plt.show()

rasm[:, :, 0] — faqat qizil kanal: 2 o'lchamli jadval. Uni ko'rsatish uchun zeros_like bilan bo'sh rasm yasab, faqat bitta kanalni qaytardik — qolgan ikkitasi 0. Har rasmda yorqin joy — o'sha rang ko'p bo'lgan joy. Chap yuqoridagi yulduzli ko'k maydonga qarang: qizil kanalda u qorong'i, ko'k kanalda yorqin. Oq yulduzlar esa uchala kanalda ham yorqin — chunki oq rang uchala kanalning to'liq qiymati (255, 255, 255).
Kulrang rasm — matritsa ko'paytirish
Rangli rasmni kulrang qilishning to'g'ri usuli — kanallarni teng emas, og'irlik bilan qo'shish: inson ko'zi yashilni eng yorqin, ko'kni eng xira sezadi.
ogirlik = np.array([0.299, 0.587, 0.114]) kulrang = rasm @ ogirlik print(rasm.shape, "@", ogirlik.shape, "->", kulrang.shape) oddiy_ortacha = rasm.mean(axis=2) fig, (chap, ong) = plt.subplots(1, 2, figsize=(8, 4.4)) chap.imshow(kulrang, cmap="gray") chap.set_title("@ og'irlik bilan") ong.imshow(oddiy_ortacha, cmap="gray") ong.set_title("oddiy o'rtacha") for ax in (chap, ong): ax.axis("off") plt.show() print("eng katta farq (yorqinlik birligida):", np.abs(kulrang - oddiy_ortacha).max().round(1))
(600, 512, 3) @ (3,) -> (600, 512) eng katta farq (yorqinlik birligida): 31.6

6-bobdagi @: (600, 512, 3) @ (3,) — har pikselning uchta kanali og'irliklarga ko'paytirilib, yig'iladi. Natija — (600, 512). Ko'zga oddiy o'rtacha (mean(axis=2), 5-bob) bilan deyarli bir xil ko'rinadi, lekin ayrim piksellarda farq 30 birlikdan oshadi (shkala 0..255). Fotosuratni qayta ishlash dasturlari og'irlikli usulni ishlatadi, chunki u ko'z sezgan yorqinlikka yaqinroq.
Teskari aylantirish va yorqinlik tuzog'i
oyna = rasm[:, ::-1] teskari = rasm[::-1] yorqin_xato = rasm + 80 yorqin_togri = np.clip(rasm.astype(int) + 80, 0, 255).astype(np.uint8) qorongi = (yorqin_xato < rasm).sum() print(f"+80 dan keyin qorong'ilashib ketgan qiymatlar: {qorongi} ({qorongi / rasm.size:.0%})") print("clip bilan qorong'ilashganlar:", (yorqin_togri < rasm).sum()) fig, axlar = plt.subplots(1, 4, figsize=(12, 3.6)) for ax, r, nom in zip(axlar, [oyna, teskari, yorqin_xato, yorqin_togri], ["oynadagi aks [:, ::-1]", "teskari [::-1]", "+80 (uint8, xato)", "+80 clip bilan"]): ax.imshow(r) ax.set_title(nom, fontsize=10) ax.axis("off") plt.show()
+80 dan keyin qorong'ilashib ketgan qiymatlar: 151110 (16%) clip bilan qorong'ilashganlar: 0

[:, ::-1] — ustunlar teskari: oynadagi aks. [::-1] — qatorlar teskari: rasm boshi bilan pastga.
Yorqinlikda 2-bobdagi overflow qaytib keladi: uint8 255 dan oshsa, indamay 0 dan qayta boshlanadi. Shuning uchun yorqin piksellar +80 dan keyin qorong'i bo'lib qoldi — rasmdagi g'alati dog'lar shu. To'g'ri usul: avval katta turga o'tkazish (astype(int)), qo'shish, np.clip bilan 0..255 oralig'ida "qisib" qo'yish, keyin uint8 ga qaytarish.
Yorqinlik taqsimoti
fig, ax = plt.subplots(figsize=(8, 3)) for i, rang in enumerate(["#c5221f", "#137333", "#1a73e8"]): ax.hist(rasm[:, :, i].ravel(), bins=64, color=rang, alpha=0.45) ax.set_xlabel("yorqinlik (0 — qora, 255 — oq)") ax.set_ylabel("piksellar soni") ax.set_title("Har kanal bo'yicha piksellar taqsimoti") plt.show()

ravel (6-bob) 2D kanalni bitta qatorga aylantirdi, hist esa "qaysi yorqinlikda nechta piksel" degan savolga javob berdi. Rasm tahlilining — OpenCV va kompyuter ko'rishining — birinchi qadami aynan shunday histogramma.
1-qism xulosasi: NumPy
Etti bobda bitta g'oyaga keldik: ma'lumot — bu shakli bor sonlar jadvali, va uning ustidagi amallar sikl yozmasdan, birdaniga bajariladi. Jadval do'kon savdosi bo'ladimi, uylar narxi bo'ladimi, rasm bo'ladimi — farqi yo'q.
| Bob | Asosiy g'oya |
|---|---|
| 1 | array tez: bitta tur, ketma-ket xotira, sikl C da |
| 2 | pasport: shape, dtype; default_rng; overflow |
| 3 | indexing, slicing, view/copy, mask |
| 4 | arifmetika, broadcasting, jim xato |
| 5 | aggregatsiya, axis, median, nan |
| 6 | reshape, birlashtirish, @ |
| 7 | argsort, unique, rasm = array |
Keyingi qismda — pandas: NumPy ustiga qurilgan, lekin har ustunning o'z nomi va o'z turi bor jadval. Real fayllar, iflos ma'lumot, guruhlash.
Mashqlar
sotildidan eng kam sotilgan 2 mahsulot nomini toping.- Rasmning faqat yuqori yarmini kulrangga aylantiring, pastki yarmi rangli qolsin (maslahat:
np.stackbilan kulrangni 3 kanalga aylantiring). - Rasmni 2 barobar kichraytiring — har ikkinchi qator va ustunni olib. Yangi shakl qanday?
- Rasmning negativi:
255 - rasm. Nega bu yerda overflow bo'lmaydi?
Javoblar
mahsulotlar[np.argsort(sotildi)[:2]]— yog' va sut.natija = rasm.copy(); yuqori = (rasm[:300] @ ogirlik).astype(np.uint8); natija[:300] = np.stack([yuqori] * 3, axis=2).rasm[::2, ::2]—(300, 256, 3).255 - xhar doim 0..255 oralig'ida qoladi: hech qachon manfiy yoki 255 dan katta bo'lmaydi.
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.