Asosiy qismga o'tish

Rasm ichida nima bor: piksel, kanal, ROI

2-bob 7 kod bloki 1532 so'z

Bitta piksel — uchta son

Rangli rasm — bu uch o'lchamli massiv. Har bir katak (piksel) uchta sondan iborat: ko'k, yashil, qizil. Bittasini ochib ko'ramiz:

python5 qator
img = cv2.imread(str(RASM / "qurilish_kichik.jpg"))
piksel = img[270, 480]
print("img[270, 480] =", piksel, "-> B =", piksel[0], "G =", piksel[1], "R =", piksel[2])
print("faqat qizil kanal:", img[270, 480, 2])
print("eng chap yuqori piksel:", img[0, 0], "| eng o'ng past:", img[-1, -1])
Chiqish
img[270, 480] = [82 68 56] -> B = 82 G = 68 R = 56
faqat qizil kanal: 56
eng chap yuqori piksel: [121 117  89] | eng o'ng past: [75 62 54]

Indeks tartibi — img[qator, ustun], ya'ni avval y, keyin x. Bu deyarli har bir yangi boshlovchining birinchi xatosi: img[x, y] deb yozib, boshqa joyning rangini oladi yoki IndexError oladi.

Qiymatlar 0–255 oralig'ida (uint8). 0 — qorong'i, 255 — yorqin. Uchala kanal teng bo'lsa — kulrang tus: [200, 200, 200] och kulrang, [30, 30, 30] deyarli qora.

Kanallarni ajratish

python5 qator
b, g, r = cv2.split(img)
print("har kanal shakli:", b.shape, "| dtype:", b.dtype)
print(f"o'rtacha qiymat -> ko'k {b.mean():.0f}, yashil {g.mean():.0f}, qizil {r.mean():.0f}")
ko_rsat(b, g, r, nom="kanallar.png", sarlavhalar=["ko'k kanal", "yashil kanal", "qizil kanal"],
        izoh="Har kanal alohida kulrang rasm. Osmon ko'k kanalda yorqin, o'simlik yashilda, sariq kaskalar qizil va yashilda.")
Chiqish
har kanal shakli: (540, 960) | dtype: uint8
o'rtacha qiymat -> ko'k 122, yashil 114, qizil 103

Har kanal alohida kulrang rasm. Osmon ko'k kanalda yorqin, o'simlik yashilda, sariq kaskalar qizil va yashilda.

Har kanal alohida kulrang rasm. Osmon ko'k kanalda yorqin, o'simlik yashilda, sariq kaskalar qizil va yashilda.

Har kanal — alohida bir kanalli rasm. Qaysidir kanalda kerakli obyekt yaxshiroq ajralib tursa, keyingi ish o'sha kanalda qilinadi. Masalan sariq kaska qizil va yashil kanalda yorqin, ko'kda qorong'i.

Teskarisi — cv2.merge([b, g, r]). Kanallarni ataylab almashtirib ko'ramiz:

python5 qator
almashgan = cv2.merge([r, g, b])                      # qizil va ko'kni joyini almashtirdik
farq = int(np.abs(img.astype(int) - almashgan.astype(int)).mean())
print("o'rtacha farq (0-255):", farq)
ko_rsat(img, almashgan, nom="almashgan.png", sarlavhalar=["asl (BGR)", "R va B almashgan"],
        izoh="Bu — 1-bobdagi BGR tuzog'ining aynan o'zi, faqat bu safar ataylab qilindi.")
Chiqish
o'rtacha farq (0-255): 16

Bu — 1-bobdagi BGR tuzog'ining aynan o'zi, faqat bu safar ataylab qilindi.

Bu — 1-bobdagi BGR tuzog'ining aynan o'zi, faqat bu safar ataylab qilindi.

ROI: rasmning bir qismi

ROI (region of interest) — qiziqish sohasi. NumPy kesimi bilan olinadi va bu nusxa emas, o'sha massivning bir qismi:

python6 qator
roi = img[150:330, 300:560]                            # [y1:y2, x1:x2]
print("ROI shakli:", roi.shape, "| asl rasmning", f"{100 * roi.size / img.size:.1f}%")
nusxa = img.copy()
nusxa[150:330, 300:560] = cv2.GaussianBlur(roi, (0, 0), 8)     # faqat shu joyni xiralashtirdik
ko_rsat(roi, nusxa, nom="roi.png", sarlavhalar=["ROI: kesib olingan qism", "shu qism xiralashtirilgan"],
        izoh="ROI ni o'zgartirish butun rasmni o'zgartiradi — chunki u nusxa emas, ko'rinish (view).")
Chiqish
ROI shakli: (180, 260, 3) | asl rasmning 9.0%

ROI ni o'zgartirish butun rasmni o'zgartiradi — chunki u nusxa emas, ko'rinish (view).

ROI ni o'zgartirish butun rasmni o'zgartiradi — chunki u nusxa emas, ko'rinish (view).

Bu xususiyat foydali ham, xavfli ham. Foydali: yuzni xiralashtirish, raqamni yashirish, faqat bitta zonani qayta ishlash. Xavfli: asl rasmni saqlab qo'ymoqchi bo'lsangiz, img.copy() yozishni unutmang — aks holda asl ma'lumot yo'qoladi.

:::tip Nusxa qachon kerak b = a — ikkala nom bitta massivga qaraydi. b = a.copy() — haqiqiy nusxa. Kesim (a[10:20]) ham nusxa emas. Funksiyaga rasm berayotganda, funksiya uni o'zgartirishi mumkinligini o'ylang. :::

Rasm yaratish va to'ldirish

Rasm oddiy massiv bo'lgani uchun uni noldan yasash mumkin:

python7 qator
tuval = np.zeros((200, 400, 3), np.uint8)              # qora tuval
tuval[:, :200] = (255, 0, 0)                           # chap yarmi — ko'k (BGR!)
tuval[:, 200:] = (0, 165, 255)                         # o'ng yarmi — to'q sariq
oq = np.full((200, 400, 3), 255, np.uint8)
ko_rsat(tuval, oq, nom="tuval.png", sarlavhalar=["np.zeros bilan yasalgan", "np.full(255) — oq"],
        izoh="(255, 0, 0) — ko'k, chunki tartib BGR. RGB da o'ylab yozsangiz, rang boshqa chiqadi.")
print("tuval dtype:", tuval.dtype, "| min:", tuval.min(), "| max:", tuval.max())
Chiqish
tuval dtype: uint8 | min: 0 | max: 255

(255, 0, 0) — ko'k, chunki tartib BGR. RGB da o'ylab yozsangiz, rang boshqa chiqadi.

(255, 0, 0) — ko'k, chunki tartib BGR. RGB da o'ylab yozsangiz, rang boshqa chiqadi.

dtype tuzog'i: 250 + 10 = 4

Piksel uint8 — 0 dan 255 gacha. 255 dan oshsa, hisob boshidan boshlanadi (o'ralib ketadi):

python8 qator
a = np.uint8([250])
print("NumPy bilan 250 + 10 =", (a + 10)[0], "  <- o'ralib ketdi (260 - 256)")
print("cv2.add bilan      =", cv2.add(a, 10)[0], "  <- 255 da to'xtadi (to'yingan qo'shish)")
yorqin_numpy = img + 60
yorqin_cv2 = cv2.add(img, 60)
ko_rsat(yorqin_numpy, yorqin_cv2, nom="uint8_tuzoq.png",
        sarlavhalar=["img + 60 (NumPy) — dog'lar paydo bo'ldi", "cv2.add(img, 60) — to'g'ri"],
        izoh="Yorqin joylar 255 dan oshib, qora dog'ga aylandi. Yorug'likni o'zgartirishda cv2.add ishlating.")
Chiqish
NumPy bilan 250 + 10 = 4   <- o'ralib ketdi (260 - 256)
cv2.add bilan      = [260.]   <- 255 da to'xtadi (to'yingan qo'shish)

Yorqin joylar 255 dan oshib, qora dog'ga aylandi. Yorug'likni o'zgartirishda cv2.add ishlating.

Yorqin joylar 255 dan oshib, qora dog'ga aylandi. Yorug'likni o'zgartirishda cv2.add ishlating.

Chapdagi rasmda osmon va yorqin beton qora dog'lar bilan qoplangan: 255 dan oshgan piksellar nolga tushib ketgan. O'ngda cv2.add ishlatilgan — u 255 da to'xtaydi.

Qoida: yorug'lik va rang ustida ishlaganda OpenCV funksiyalarini ishlating (cv2.add, cv2.subtract, cv2.addWeighted). NumSharp arifmetikasi faqat siz o'ralishni xohlaganingizda to'g'ri.

Rasm haqida qisqa hisobot

Amalda har yangi rasm bilan ishlashdan oldin shu to'rt raqamga qaraladi:

python9 qator
def rasm_haqida(nom):
    im = cv2.imread(str(RASM / nom))
    g = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    return {"fayl": nom, "kenglik": im.shape[1], "balandlik": im.shape[0],
            "o'rtacha yorqinlik": round(float(g.mean()), 1),
            "kontrast (std)": round(float(g.std()), 1),
            "to'yingan piksel %": round(float(((g == 0) | (g == 255)).mean() * 100), 2)}

show(pd.DataFrame([rasm_haqida(n) for n in ["qurilish_kichik.jpg", "past_kontrast.jpg", "hujjat.jpg", "shakllar.png"]]))
faylkenglikbalandliko'rtacha yorqinlikkontrast (std)to'yingan piksel %
qurilish_kichik.jpg960540111.649.20
past_kontrast.jpg960540138.420.60
hujjat.jpg8001 000155.790.225.69
shakllar.png640480216.1520

Nima ko'rinadi: past_kontrast.jpg ning standart chetlanishi 20.6 — asl rasmning 49.2 sidan ikki barobardan ko'p kichik. Demak rasm "yuvilgan", tafsilot kam (11-bobda uni tuzatamiz). hujjat.jpg da esa kontrast eng katta (90.2): oq varaq va qora fon — ikki chekka. O'sha faylda to'yingan piksel 25.7%: chorak rasm 0 yoki 255 ga tiqilgan, ya'ni o'sha joylarda ma'lumot yo'q — na yorug'lashtirish, na qorong'ilashtirish uni tiklaydi.

Xulosa

Tushuncha Asosiy fikr
Indeks img[y, x] — avval qator, keyin ustun
Piksel 3 ta uint8: B, G, R. Teng bo'lsa — kulrang tus
split / merge Kanallarni ajratish va yig'ish; obyekt qaysi kanalda yaxshi ko'rinsa, o'sha kanalda ishlang
ROI img[y1:y2, x1:x2] — nusxa emas; o'zgartirsangiz asl rasm o'zgaradi
copy() Asl kerak bo'lsa — nusxa oling
uint8 o'ralishi img + 60 dog' beradi, cv2.add(img, 60) to'g'ri ishlaydi
Tez tekshiruv O'lcham, o'rtacha yorqinlik, kontrast, to'yingan piksel foizi

Talaba ishi

  1. qurilish.jpg (katta versiya) ning markazidagi 300x300 kvadratni kesib oling va alohida faylga saqlang. Markazni qanday hisoblaysiz — shape dan.
  2. Faqat qizil kanalni nolga tenglashtiring va natijani ko'ring. Rasm qanday o'zgardi? Qaysi obyektlar yo'qoldi?
  3. img - 60 va cv2.subtract(img, 60) ni solishtiring. Qorong'i joylarda nima farq bor?
  4. rasm_haqida funksiyasiga "eng ko'p uchraydigan rang" ustunini qo'shing (maslahat: np.unique yoki kanallarni 32 ga bo'lib guruhlash). shakllar.png uchun javob nima?

Bu bobni bepul o'qidingiz.

Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.

Telegramda yozish Narxlar