Asosiy qismga o'tish

Rang fazolari: BGR, kulrang va HSV

5-bob 5 kod bloki 1555 so'z

Nega BGR rang tanlash uchun yaramaydi

"Sariq kaskalarni top" degan vazifani BGR da yechish qiyin. Sababi: yorug'lik o'zgarsa, uchala kanal ham o'zgaradi. Soyada turgan sariq kaska bilan quyoshda turgan sariq kaskaning BGR qiymatlari butunlay boshqa.

HSV boshqacha ajratadi:

Kanal Ma'nosi Oralig'i (OpenCV)
H (Hue) Rangning o'zi: qizil, sariq, ko'k... 0–179 (daraja/2)
S (Saturation) To'yinganlik: kulrangmi yoki toza rangmi 0–255
V (Value) Yorqinlik 0–255

Yorug'lik o'zgarsa asosan V o'zgaradi, H deyarli o'sha bo'lib qoladi. Shuning uchun rang bo'yicha tanlash HSV da qilinadi.

python6 qator
img = cv2.imread(str(RASM / "qurilish_kichik.jpg"))
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
print("H oralig'i:", h.min(), "-", h.max(), "| S:", s.min(), "-", s.max(), "| V:", v.min(), "-", v.max())
ko_rsat(h, s, v, nom="hsv_kanallar.png", sarlavhalar=["H — rang turi", "S — to'yinganlik", "V — yorqinlik"],
        izoh="V kanali oddiy kulrang rasmga o'xshaydi. S da to'yingan ranglar (kaskalar, kiyim) yorqin ko'rinadi.")
Chiqish
H oralig'i: 0 - 179 | S: 0 - 255 | V: 1 - 255

V kanali oddiy kulrang rasmga o'xshaydi. S da to'yingan ranglar (kaskalar, kiyim) yorqin ko'rinadi.

V kanali oddiy kulrang rasmga o'xshaydi. S da to'yingan ranglar (kaskalar, kiyim) yorqin ko'rinadi.

Rangni tanlash: inRange

cv2.inRange ikki chegara orasidagi piksellarni 255, qolganini 0 qiladi — ya'ni maska yasaydi:

python13 qator
def rang_maska(hsv, past, yuqori):
    return cv2.inRange(hsv, np.array(past), np.array(yuqori))

maskalar = {
    "sariq":  rang_maska(hsv, (18, 90, 90), (35, 255, 255)),
    "ko'k":   rang_maska(hsv, (95, 80, 60), (130, 255, 255)),
    "qizil":  cv2.bitwise_or(rang_maska(hsv, (0, 90, 70), (8, 255, 255)),
                             rang_maska(hsv, (170, 90, 70), (179, 255, 255))),
}
show(pd.DataFrame([{"rang": k, "piksellar": int((m > 0).sum()), "ulush %": round(100 * (m > 0).mean(), 2)}
                   for k, m in maskalar.items()]))
ko_rsat(*maskalar.values(), nom="rang_maskalari.png", sarlavhalar=list(maskalar),
        izoh="Sariq va qizil maskalar kaskalarni topdi. Ko'k maska esa osmonni oldi — rasmning chorak qismi.")
rangpiksellarulush %
sariq3 6080.7
ko'k126 26324.36
qizil2 3240.45

Sariq va qizil maskalar kaskalarni topdi. Ko'k maska esa osmonni oldi — rasmning chorak qismi.

Sariq va qizil maskalar kaskalarni topdi. Ko'k maska esa osmonni oldi — rasmning chorak qismi.

Jadvalga qarang: sariq 3 608 piksel (0.7%), qizil 2 324 (0.45%), ko'k esa 126 263 piksel — 24.4%. Ko'k kaskalar buncha joy egallamaydi: maska osmonni olgan. Bu — rang bo'yicha tanlashning asosiy cheklovi: u "kaska" ni emas, "shu rangdagi hamma narsa" ni topadi.

Yechim uchta: (1) qidirish sohasini cheklash (osmon yuqorida — pastki yarmida qidirish), (2) o'lcham va shakl bo'yicha filtr (kaska kichik va dumaloq, osmon ulkan), (3) haqiqiy detektor ishlatish. Quyida ikkinchisini qo'llaymiz.

Qizil uchun ikkita oraliq kerak bo'ldi: H aylana bo'ylab yuradi va qizil 0 ning ikkala tomonida (0–8 va 170–179). Bu — HSV bilan ishlashdagi birinchi tuzoq.

Maskani tozalash va obyektlarni sanash

Maska ko'pincha "shovqinli" chiqadi: yakka piksellar, teshiklar. Morfologiya (9-bob) uni tozalaydi, keyin bog'langan komponentlarni sanash mumkin:

python14 qator
sariq = maskalar["sariq"]
yadro = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
toza = cv2.morphologyEx(sariq, cv2.MORPH_OPEN, yadro)
toza = cv2.morphologyEx(toza, cv2.MORPH_CLOSE, yadro)
n, yorliq, stat, markaz = cv2.connectedComponentsWithStats(toza, connectivity=8)
kattalari = [i for i in range(1, n) if stat[i, cv2.CC_STAT_AREA] >= 80]
print(f"tozalashdan oldin: {int((sariq > 0).sum())} piksel | keyin: {int((toza > 0).sum())} piksel")
print(f"bog'langan sohalar: {n - 1} ta, ulardan 80 pikseldan katta: {len(kattalari)} ta")
natija = img.copy()
for i in kattalari:
    x, y, w, hh, _ = stat[i]
    cv2.rectangle(natija, (x, y), (x + w, y + hh), (0, 255, 0), 2)
ko_rsat(sariq, toza, natija, nom="sariq_sanash.png", sarlavhalar=["xom maska", "tozalangan", "topilgan sohalar"],
        izoh="Rang + morfologiya + komponentlar: neyron tarmoqsiz obyekt topishning eng arzon usuli.")
Chiqish
tozalashdan oldin: 3608 piksel | keyin: 3276 piksel
bog'langan sohalar: 9 ta, ulardan 80 pikseldan katta: 8 ta

Rang + morfologiya + komponentlar: neyron tarmoqsiz obyekt topishning eng arzon usuli.

Rang + morfologiya + komponentlar: neyron tarmoqsiz obyekt topishning eng arzon usuli.

Bu usul model emas: u faqat rangga qaraydi. Sariq belgi, sariq kiyim yoki quyoshdagi devor ham tushadi. Lekin nazorat qilinadigan sharoitda (bir xil yorug'lik, ma'lum rang) u juda tez va ishonchli — konveyerda detal sanash, rangli belgi topish, ekran tekshirish.

Yorug'lik o'zgarsa nima bo'ladi

Tekshiramiz: rasmni sun'iy qorong'ilashtirib, o'sha maskani qayta qo'llaymiz.

python9 qator
qatorlar = []
for nom, koef in [("asl", 1.0), ("qorong'i (x0.6)", 0.6), ("juda qorong'i (x0.4)", 0.4), ("yorqin (x1.4)", 1.4)]:
    o = np.clip(img.astype(np.float32) * koef, 0, 255).astype(np.uint8)
    o_hsv = cv2.cvtColor(o, cv2.COLOR_BGR2HSV)
    bgr_maska = cv2.inRange(o, np.array([0, 150, 150]), np.array([120, 255, 255]))      # BGR da "sariq"
    hsv_maska = rang_maska(o_hsv, (18, 90, 90), (35, 255, 255))
    qatorlar.append({"holat": nom, "BGR maska, piksel": int((bgr_maska > 0).sum()),
                     "HSV maska, piksel": int((hsv_maska > 0).sum())})
show(pd.DataFrame(qatorlar))
holatBGR maska, pikselHSV maska, piksel
asl1 6483 608
qorong'i (x0.6)02 464
juda qorong'i (x0.4)0256
yorqin (x1.4)1 5833 516

HSV maskasi yorug'lik o'zgarganda ham ancha barqaror qoladi, BGR maskasi esa keskin o'zgaradi. Shuning uchun "rang bo'yicha top" vazifasi deyarli har doim HSV da yechiladi.

:::gotcha S va V ning pastki chegarasini tushirmang S ni 0 dan boshlasangiz, maskaga kulrang va oq piksellar ham tushadi (ularning "rangi" noaniq, H tasodifiy). V ni 0 dan boshlasangiz — qora joylar. Amalda S >= 80 va V >= 60 yaxshi boshlang'ich. :::

Boshqa foydali fazolar

python7 qator
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
ko_rsat(cv2.split(lab)[0], cv2.split(ycrcb)[0], cv2.cvtColor(img, cv2.COLOR_BGR2GRAY),
        nom="lab_ycrcb.png", sarlavhalar=["LAB: L (yorqinlik)", "YCrCb: Y (yorqinlik)", "oddiy kulrang"],
        izoh="Uchala kanal o'xshash, lekin L inson ko'zining sezgirligiga yaqinroq hisoblanadi.")
print("kulrang va LAB-L farqi (o'rtacha):",
      round(float(np.abs(cv2.split(lab)[0].astype(int) - cv2.cvtColor(img, cv2.COLOR_BGR2GRAY).astype(int)).mean()), 2))
Chiqish
kulrang va LAB-L farqi (o'rtacha): 7.93

Uchala kanal o'xshash, lekin L inson ko'zining sezgirligiga yaqinroq hisoblanadi.

Uchala kanal o'xshash, lekin L inson ko'zining sezgirligiga yaqinroq hisoblanadi.

  • LAB — yorqinlik (L) rangdan ajratilgan; CLAHE ni faqat L ga qo'llash rangni buzmaydi (11-bob).
  • YCrCb — video siqishda ishlatiladi; teri rangini topishda ham qulay.
  • Kulrang — 0.299R + 0.587G + 0.114B: yashil eng katta vazn oladi, chunki ko'z unga sezgirroq.

Xulosa

Tushuncha Asosiy fikr
HSV H — rang, S — to'yinganlik, V — yorqinlik. Rang tanlash HSV da
H oralig'i OpenCV da 0–179 (daraja emas, yarim daraja)
Qizil H aylanasining ikki chekkasida: ikkita inRange va bitwise_or
inRange Ikki chegara orasidagi piksellardan maska yasaydi
Maskani tozalash MORPH_OPEN + MORPH_CLOSE, keyin connectedComponentsWithStats
Yorug'lik HSV maskasi BGR maskasidan barqarorroq
LAB Yorqinlikni rangdan ajratadi — kontrastni tuzatish uchun

Talaba ishi

  1. Ko'k kaskalar uchun chegaralarni o'zingiz sozlang: S va V ning pastki chegarasini 40, 60, 90 qilib ko'ring. Qaysi qiymatda osmon maskaga tushib ketadi?
  2. shakllar.png dagi har bir rangni alohida maska bilan ajrating va har birining maydonini piksel va foizda chiqaring.
  3. Rasmni cv2.cvtColor(img, cv2.COLOR_BGR2HSV) bilan o'girib, faqat H kanalini 30 ga siljiting ((h + 30) % 180), keyin BGR ga qaytaring. Ranglar qanday o'zgardi?
  4. Yuqoridagi yorug'lik jadvalini 0.3 dan 1.6 gacha 6 qadamda takrorlang va HSV maskasining pikseli necha foizga o'zgarishini grafikda chizing. Qaysi nuqtada maska buzila boshlaydi?

Bu bobni bepul o'qidingiz.

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

Telegramda yozish Narxlar