OpenCV bilan tanishuv: o'qish, ko'rsatish, saqlash
Nega OpenCV
Kompyuterga rasmni "ko'rsatish" — bu unga sonlar massivini berish. OpenCV o'sha massiv ustida ishlaydigan kutubxona: o'qish, o'zgartirish, o'lchash, videodan kadr olish. Yadrosi C++ da yozilgan, shuning uchun tez — real vaqtda, kameradan sekundiga 30 kadr kelayotganda ham ulguradi.
Kutubxona Apache-2.0 litsenziyasida: tijorat mahsulotida ham bepul ishlatiladi, faqat mualliflik yozuvini saqlash kerak. Bu — chuqur o'rganish modellari bilan solishtirganda muhim farq (ba'zi modellar tijoratga ruxsat bermaydi).
OpenCV nimani yaxshi qiladi va nimani qilmaydi:
| Yaxshi qiladi | Boshqa vosita kerak |
|---|---|
| Rasmni o'qish, o'lchash, kesish, burish | Rasmda "bu mushukmi yoki itmi" degan savol — neyron tarmoq |
| Rang, chekka, kontur, shakl — geometriya | Matnni o'qish (OCR) — Tesseract yoki maxsus model |
| Videodan kadr olish, kamerani boshqarish | Katta hajmli modelni o'qitish — PyTorch |
| Tezkor tayyorlash (preprocessing) | Murakkab semantik tahlil |
Amalda OpenCV ko'pincha quvurning birinchi qismi bo'ladi: rasmni tozalaydi, kerakli joyini kesadi, keyin model ishlaydi. Shuning uchun uni o'rganish — modelni o'rganishdan oldingi qadam.
O'rnatish: uchta paket, bittasini tanlang
pip install opencv-python # asosiy; deyarli hamma kerakli narsa shu yerda pip install opencv-contrib-python # asosiy + qo'shimcha modullar (SIFT, tracker lar, aruco) pip install opencv-python-headless # oynasiz: server va Docker uchun (imshow ishlamaydi)
Uchalasini birga o'rnatmang — ular bir-birining ustiga yozadi va tushunarsiz xatolar beradi. Serverda (masalan, Django ichida) headless ni oling: u oyna kutubxonalarini talab qilmaydi va tasvir hajmi kichik.
Tekshiramiz:
import cv2 print("OpenCV versiyasi:", cv2.__version__) print("Haar fayllari papkasi bormi:", bool(cv2.data.haarcascades))
OpenCV versiyasi: 4.10.0 Haar fayllari papkasi bormi: True
Birinchi dastur: o'qish, o'lchash, saqlash
img = cv2.imread(str(RASM / "qurilish_kichik.jpg")) print("turi:", type(img).__name__, "| shakli:", img.shape, "| dtype:", img.dtype) print("balandlik:", img.shape[0], "| kenglik:", img.shape[1], "| kanallar:", img.shape[2]) print("jami piksel:", img.shape[0] * img.shape[1], "| xotirada:", img.nbytes // 1024, "KB") cv2.imwrite(str(RASM / "_nusxa.jpg"), img, [cv2.IMWRITE_JPEG_QUALITY, 80]) print("saqlandi, hajmi:", (RASM / "_nusxa.jpg").stat().st_size // 1024, "KB")
turi: ndarray | shakli: (540, 960, 3) | dtype: uint8 balandlik: 540 | kenglik: 960 | kanallar: 3 jami piksel: 518400 | xotirada: 1518 KB saqlandi, hajmi: 104 KB
Uch narsaga e'tibor bering. Birinchisi: imread oddiy NumPy massivi qaytaradi — demak OpenCV bilmagan har
qanday amalni NumPy bilan qilish mumkin. Ikkinchisi: shakl (balandlik, kenglik, kanal) tartibida, ya'ni
avval qator, keyin ustun — matematikadagi jadval tartibi, (x, y) emas. Uchinchisi: dtype — uint8,
har kanal 0 dan 255 gacha.
Saqlashda sifat ham muhim: yuqorida JPEG sifati 80 ga qo'yildi va fayl asl hajmidan kichrayadi. PNG uchun
cv2.IMWRITE_PNG_COMPRESSION (0–9) bor; PNG yo'qotishsiz, JPEG esa yo'qotish bilan siqadi.
Eng ko'p uchraydigan birinchi xato: fayl topilmasa
yoq = cv2.imread(str(RASM / "bunday_fayl_yoq.jpg")) print("natija:", yoq) print("xato chiqdimi?", "yo'q — jim None qaytdi")
natija: None xato chiqdimi? yo'q — jim None qaytdi
imread fayl topilmasa xato bermaydi, None qaytaradi. Keyingi qatorda img.shape yozsangiz,
AttributeError: 'NoneType' object has no attribute 'shape' chiqadi va yangi boshlovchi uni "OpenCV buzuq"
deb tushunadi. Har doim tekshiring:
img = cv2.imread(yol) if img is None: raise FileNotFoundError(yol)
Sabablari: noto'g'ri yo'l, kirill yoki bo'shliqli papka nomi, fayl haqiqatan rasm emas, yoki ruxsat yo'q.
BGR tuzog'i
OpenCV rangni BGR tartibida saqlaydi (ko'k, yashil, qizil), matplotlib va deyarli hamma boshqa kutubxona esa RGB kutadi. Shuning uchun OpenCV bilan o'qilgan rasmni to'g'ridan-to'g'ri matplotlib ga bersangiz, ranglar almashib ketadi:
import matplotlib.pyplot as plt f, ax = plt.subplots(1, 2, figsize=(11, 3.4)) ax[0].imshow(img); ax[0].set_title("to'g'ridan-to'g'ri (BGR) — ranglar noto'g'ri", fontsize=10); ax[0].axis("off") ax[1].imshow(img[:, :, ::-1]); ax[1].set_title("[:, :, ::-1] bilan RGB — to'g'ri", fontsize=10); ax[1].axis("off") fig("bgr_rgb.png", "Bitta rasm, ikki xil tartib. Chapda ko'k va qizil almashgan: osmon va kiyimlarga qarang.")

Bitta rasm, ikki xil tartib. Chapda ko'k va qizil almashgan: osmon va kiyimlarga qarang.
Tuzatishning ikki yo'li bor: img[:, :, ::-1] (kanallarni teskari o'qish, nusxa olmaydi) yoki
cv2.cvtColor(img, cv2.COLOR_BGR2RGB) (aniq va o'qilishi oson). Ikkalasi bir xil natija beradi.
Nega shunday? OpenCV 2000-yillarda yozilgan, o'sha paytdagi kameralar va BMP formati BGR ishlatardi. Keyin o'zgartirish mumkin emas edi: dunyodagi millionlab qator kod buzilardi.
:::gotcha Rasmni faylga saqlaganda teskari qilmang
cv2.imwrite o'zi BGR kutadi. Agar siz matplotlib uchun RGB ga o'girgan massivni imwrite ga bersangiz,
saqlangan faylda ranglar almashgan bo'ladi. Qoida: ichkarida BGR, faqat ko'rsatishdan oldin RGB.
:::
Ekranda ko'rsatish: imshow va kitobdagi usul
Kompyuterda ishlaganda rasmni alohida oynada ko'rsatish qulay:
cv2.imshow("Rasm", img) # oyna ochiladi cv2.waitKey(0) # 0 = tugma bosilguncha kutadi; 25 = 25 ms kutadi (video uchun) cv2.destroyAllWindows() # oynalarni yopadi
waitKey ni unutsangiz oyna qotib qoladi — bu klassik boshlang'ich xato. Server yoki Docker ichida esa
imshow umuman ishlamaydi (oyna tizimi yo'q), shuning uchun bu kitobda hamma rasm faylga saqlanadi va
matplotlib bilan ko'rsatiladi. Kitob kodini serverda ham, noutbukda ham ishlatish mumkin bo'lsin.
Keyingi boblarda ko'p rasmni yonma-yon solishtiramiz, shuning uchun kichik yordamchi ishlatamiz:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ko_rsat(img, gray, nom="rangli_va_kulrang.png", sarlavhalar=["rangli (3 kanal)", "kulrang (1 kanal)"], izoh="ko_rsat() — kitobdagi yordamchi: BGR ni o'zi RGB ga o'giradi, kulrang rasmni gray palitrada chizadi.") print("rangli:", img.shape, img.nbytes // 1024, "KB | kulrang:", gray.shape, gray.nbytes // 1024, "KB")
rangli: (540, 960, 3) 1518 KB | kulrang: (540, 960) 506 KB

ko_rsat() — kitobdagi yordamchi: BGR ni o'zi RGB ga o'giradi, kulrang rasmni gray palitrada chizadi.
Kulrang rasm uch barobar kam joy oladi: uchta kanal o'rniga bitta. Shuning uchun chekka topish, kontur va shablon qidirish kabi amallar deyarli har doim kulrang rasmda bajariladi — natija bir xil, hisob uch barobar tez.
Xulosa
| Tushuncha | Asosiy fikr |
|---|---|
| Rasm = massiv | imread NumPy massivi qaytaradi: (balandlik, kenglik, kanal), uint8 |
| Uch paket | opencv-python, -contrib- (qo'shimcha modullar), -headless (server) — faqat bittasi |
imread jim |
Fayl yo'q bo'lsa None, xato emas. Har doim tekshiring |
| BGR | OpenCV ichida BGR; ko'rsatishdan oldin RGB ga o'giring, saqlashdan oldin o'girmang |
imshow |
Faqat oyna bor muhitda; serverda faylga saqlang |
| Kulrang | Uch barobar kam xotira, ko'p amal uchun yetarli |
Talaba ishi
- O'z telefoningizdagi bitta suratni o'qing va shakli,
dtypeva xotiradagi hajmini chiqaring. 12 MP surat xotirada necha MB joy oladi? Fayl hajmi bilan solishtiring — nega farq bor? - Shu suratni JPEG sifati 95, 60 va 25 bilan saqlang. Fayl hajmlari qanday o'zgaradi? 25 sifatda qaysi joylarda buzilish ko'rinadi (osmon, matn, teri)?
cv2.imread(yol, cv2.IMREAD_GRAYSCALE)bilan o'qing vacvtColorbilan kulrangga o'girilgan variantni solishtiring: natijalar bir xilmi? (np.array_equalbilan tekshiring.)- Kirill yoki bo'shliqli papka nomi bilan sinab ko'ring:
imreadishladimi? Xatoni qanday tutasiz?
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.