Chekka topish: Sobel, Laplacian va Canny
Chekka nima
Chekka — yorqinlik keskin o'zgaradigan joy. Matematikada bu hosila: qo'shni piksellar farqi katta bo'lsa, o'sha yerda chekka bor. Shuning uchun chekka topish har doim kulrang rasmda bajariladi — rang emas, yorqinlik o'zgarishi muhim.
Chekka nima uchun kerak: kontur topish (10-bob), hujjat burchaklarini aniqlash (17-bob), shakl o'lchash, sifat nazorati (detalda chiziq bormi).
Sobel: yo'nalish bo'yicha hosila
Sobel gorizontal va vertikal o'zgarishni alohida o'lchaydi:
img = cv2.imread(str(RASM / "shakllar.png"), cv2.IMREAD_GRAYSCALE) sx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) # x bo'yicha: vertikal chekkalar sy = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) # y bo'yicha: gorizontal chekkalar kuch = cv2.magnitude(sx, sy) print(f"Sobel x: min {sx.min():.0f}, max {sx.max():.0f} (manfiy ham bor — shuning uchun CV_64F)") ko_rsat(np.abs(sx).astype(np.uint8), np.abs(sy).astype(np.uint8), np.clip(kuch, 0, 255).astype(np.uint8), nom="sobel.png", sarlavhalar=["Sobel x (vertikal chekka)", "Sobel y (gorizontal chekka)", "kuch = sqrt(x² + y²)"], izoh="x bo'yicha hosila tik chiziqlarni, y bo'yicha yotiq chiziqlarni ko'rsatadi.")
Sobel x: min -596, max 596 (manfiy ham bor — shuning uchun CV_64F)

x bo'yicha hosila tik chiziqlarni, y bo'yicha yotiq chiziqlarni ko'rsatadi.
:::gotcha CV_64F ni unutmang
cv2.Sobel(img, cv2.CV_8U, 1, 0) deb yozsangiz, manfiy hosilalar nolga aylanadi — oq-dan-qora o'tish
ko'rinadi, qora-dan-oq o'tish esa yo'qoladi. Chekkaning yarmi yo'qoladi va buni sezish qiyin. Har doim
CV_64F (yoki CV_16S) da hisoblang, keyin np.abs va uint8 ga o'tkazing.
:::
Laplacian: ikkinchi hosila
Laplacian ikki yo'nalishni birga oladi — alohida x va y kerak emas:
lap = cv2.Laplacian(img, cv2.CV_64F, ksize=3) lap_u8 = np.clip(np.abs(lap), 0, 255).astype(np.uint8) shovqinli = cv2.imread(str(RASM / "shovqinli.png"), cv2.IMREAD_GRAYSCALE) lap_shovqin = np.clip(np.abs(cv2.Laplacian(shovqinli, cv2.CV_64F)), 0, 255).astype(np.uint8) ko_rsat(lap_u8, lap_shovqin, nom="laplacian.png", sarlavhalar=["toza rasmda Laplacian", "shovqinli rasmda Laplacian"], izoh="Ikkinchi hosila shovqinga juda sezgir: o'ngdagi rasm deyarli butunlay 'chekka' bo'lib ketdi.") print("chekka deb belgilangan piksellar (>40): toza", f"{100 * (lap_u8 > 40).mean():.1f}%", "| shovqinli", f"{100 * (lap_shovqin > 40).mean():.1f}%")
chekka deb belgilangan piksellar (>40): toza 1.9% | shovqinli 44.1%

Ikkinchi hosila shovqinga juda sezgir: o'ngdagi rasm deyarli butunlay 'chekka' bo'lib ketdi.
Shuning uchun Laplacian yolg'iz kam ishlatiladi. Uning eng foydali qo'llanishi — keskinlikni o'lchash
(7-bobda ishlatdik): Laplacian(...).var() katta bo'lsa rasm keskin, kichik bo'lsa xira. Avtofokus va
"bu surat xiramikan?" tekshiruvi shunday ishlaydi.
Canny: amaliy standart
Canny bitta funksiya emas, besh qadamli algoritm: (1) Gauss bilan silliqlash, (2) Sobel gradienti, (3) non-maximum suppression — chekkani bir piksel qalinlikka siqish, (4) ikki chegara, (5) gisterezis — kuchsiz chekka kuchli chekkaga ulangan bo'lsagina qoldiriladi.
qurilish = cv2.imread(str(RASM / "qurilish_kichik.jpg"), cv2.IMREAD_GRAYSCALE) variantlar = {} for past, yuqori in [(50, 150), (100, 200), (150, 300)]: variantlar[f"{past}/{yuqori}"] = cv2.Canny(qurilish, past, yuqori) show(pd.DataFrame([{"chegaralar": k, "chekka piksellar %": round(100 * (v > 0).mean(), 2)} for k, v in variantlar.items()])) ko_rsat(*variantlar.values(), nom="canny_chegara.png", sarlavhalar=list(variantlar), izoh="Chegara past bo'lsa mayda tafsilot ham chekka bo'ladi; yuqori bo'lsa faqat eng kuchli chekkalar qoladi.")
| chegaralar | chekka piksellar % |
|---|---|
| 50/150 | 14.95 |
| 100/200 | 10.42 |
| 150/300 | 7.13 |

Chegara past bo'lsa mayda tafsilot ham chekka bo'ladi; yuqori bo'lsa faqat eng kuchli chekkalar qoladi.
Ikki chegara qanday tanlanadi? Amaliy qoida: yuqori chegara pastdan 2–3 barobar katta. Aniq sonlar rasmga bog'liq, shuning uchun ko'pincha medianadan hisoblanadi:
def avto_canny(gray, sigma=0.33): med = float(np.median(gray)) past = int(max(0, (1.0 - sigma) * med)) yuqori = int(min(255, (1.0 + sigma) * med)) return cv2.Canny(gray, past, yuqori), past, yuqori for nom, rasm in [("qurilish", qurilish), ("shakllar", img), ("hujjat", cv2.imread(str(RASM / "hujjat.jpg"), cv2.IMREAD_GRAYSCALE))]: chekka, p, y = avto_canny(rasm) print(f"{nom:10} median {np.median(rasm):5.0f} -> chegaralar {p:3d}/{y:3d} | chekka piksellar {100 * (chekka > 0).mean():.2f}%")
qurilish median 100 -> chegaralar 67/133 | chekka piksellar 14.31% shakllar median 245 -> chegaralar 164/255 | chekka piksellar 0.85% hujjat median 195 -> chegaralar 130/255 | chekka piksellar 1.85%
Bu usul har rasm uchun o'zi moslashadi va amalda qo'lda tanlashdan ko'ra ishonchliroq.
Shovqin chekkani buzadi — avval silliqlang
qatorlar = [] for nom, rasm in [("shovqinli, filtrsiz", shovqinli), ("shovqinli + Gauss 5x5", cv2.GaussianBlur(shovqinli, (5, 5), 0)), ("shovqinli + Median 5", cv2.medianBlur(shovqinli, 5)), ("toza rasm (haqiqat)", img)]: c = cv2.Canny(rasm, 100, 200) qatorlar.append({"holat": nom, "chekka piksellar %": round(100 * (c > 0).mean(), 2)}) show(pd.DataFrame(qatorlar)) ko_rsat(cv2.Canny(shovqinli, 100, 200), cv2.Canny(cv2.medianBlur(shovqinli, 5), 100, 200), cv2.Canny(img, 100, 200), nom="canny_shovqin.png", sarlavhalar=["filtrsiz — soxta chekkalar", "median dan keyin", "toza rasm"], izoh="Shovqinli rasmda Canny minglab soxta chekka topadi. Filtrdan keyin natija toza rasmnikiga yaqinlashadi.")
| holat | chekka piksellar % |
|---|---|
| shovqinli, filtrsiz | 16.72 |
| shovqinli + Gauss 5x5 | 2.81 |
| shovqinli + Median 5 | 0.89 |
| toza rasm (haqiqat) | 0.85 |

Shovqinli rasmda Canny minglab soxta chekka topadi. Filtrdan keyin natija toza rasmnikiga yaqinlashadi.
Toza rasmdagi 0.85% — bizning "haqiqat"imiz. Filtrsiz Canny 16.72% topdi, ya'ni yigirma barobar ko'p: o'sha ortiqchaning deyarli hammasi shovqin. Gauss filtri uni 2.81% ga tushirdi, median esa 0.89% ga — haqiqatdan atigi 0.04 punkt farq bilan.
Bu 7-bobdagi xulosani tasdiqlaydi: shovqin turi tuz-qalampir bo'lsa, median filtr boshqalardan aniq ustun. Va bu yerda farq "chiroyliroq ko'rinadi" emas, keyingi qadam uchun hal qiluvchi: 16% chekka pikselda kontur topish mumkin emas, 0.89% da esa mumkin.
Qoida: Canny dan oldin silliqlang. Canny ichida Gauss bor, lekin u kichik; kuchli shovqinda yetmaydi.
Amaliy misol: varaqning chekkalarini topish
17-bobdagi skaner loyihasining birinchi qadami:
hujjat = cv2.imread(str(RASM / "hujjat.jpg")) gray = cv2.cvtColor(hujjat, cv2.COLOR_BGR2GRAY) silliq = cv2.GaussianBlur(gray, (5, 5), 0) chekka = cv2.Canny(silliq, 50, 150) yopiq = cv2.morphologyEx(chekka, cv2.MORPH_CLOSE, np.ones((5, 5), np.uint8)) # uzilgan chiziqlarni ulash ko_rsat(chekka, yopiq, nom="hujjat_chekka.png", sarlavhalar=["Canny", "MORPH_CLOSE dan keyin"], izoh="Varaqning to'rt cheti aniq ko'rinadi. Keyingi qadam — shu chiziqlardan to'rtburchak yasash (10- va 17-boblar).") print("chekka piksellar:", int((chekka > 0).sum()), "| yopilgandan keyin:", int((yopiq > 0).sum()))
chekka piksellar: 14775 | yopilgandan keyin: 31047

Varaqning to'rt cheti aniq ko'rinadi. Keyingi qadam — shu chiziqlardan to'rtburchak yasash (10- va 17-boblar).
Xulosa
| Tushuncha | Asosiy fikr |
|---|---|
| Chekka | Yorqinlikning keskin o'zgarishi = hosila |
| Sobel | x va y bo'yicha alohida; CV_64F da hisoblang |
| Laplacian | Ikkinchi hosila, shovqinga juda sezgir; keskinlik o'lchash uchun zo'r |
| Canny | Amaliy standart: 5 qadam, ikki chegara, gisterezis |
| Chegara nisbati | Yuqori ≈ 2–3 × past; medianadan avtomatik hisoblash mumkin |
| Shovqin | Canny dan oldin filtrlang, aks holda minglab soxta chekka |
| Uzilgan chiziq | MORPH_CLOSE bilan ulanadi |
Talaba ishi
avto_cannyningsigmasini 0.1 dan 0.6 gacha o'zgartiring. Qaysi qiymatda hujjatning to'rt cheti to'liq chiqadi va ortiqcha chiziq kam bo'ladi?- Sobel ni
ksize=1, 3, 5, 7bilan sinang. Yadro kattalashganda chekka qanday o'zgaradi? cv2.Scharrni Sobel bilan solishtiring (u 3x3 da aniqroq hisoblanadi). Farq sezilarlimi?- Rasmni 90° ga burib, Sobel x va y natijalarini qayta oling. Nima kutgan edingiz va nima chiqdi?
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.