Asosiy qismga o'tish

Saralash, qidirish va rasm — bu ham array

7-bob 10 kod bloki 1828 so'z

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

python9 qator
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]])
Chiqish
[ 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:

python3 qator
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])
Chiqish
[[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

python5 qator
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()])
Chiqish
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

python4 qator
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])
Chiqish
[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).

python7 qator
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()
Chiqish
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

python5 qator
yuz = rasm[60:340, 140:400]
print(yuz.shape)
plt.imshow(yuz)
plt.axis("off")
plt.show()
Chiqish
(280, 260, 3)

3-bobdagi slicing: qatorlar 60–340, ustunlar 140–400, kanallar — hammasi. Natija — view: rasm ko'chirilmadi.

Kanallar — rang qatlamlari

python8 qator
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.

python14 qator
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))
Chiqish
(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

python16 qator
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()
Chiqish
+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

python7 qator
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

  1. sotildi dan eng kam sotilgan 2 mahsulot nomini toping.
  2. Rasmning faqat yuqori yarmini kulrangga aylantiring, pastki yarmi rangli qolsin (maslahat: np.stack bilan kulrangni 3 kanalga aylantiring).
  3. Rasmni 2 barobar kichraytiring — har ikkinchi qator va ustunni olib. Yangi shakl qanday?
  4. Rasmning negativi: 255 - rasm. Nega bu yerda overflow bo'lmaydi?

Javoblar

  1. mahsulotlar[np.argsort(sotildi)[:2]] — yog' va sut.
  2. natija = rasm.copy(); yuqori = (rasm[:300] @ ogirlik).astype(np.uint8); natija[:300] = np.stack([yuqori] * 3, axis=2).
  3. rasm[::2, ::2] — (300, 256, 3).
  4. 255 - x har 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.

Telegramda yozish Narxlar