$ sudo teach|
    $ sudo teach|
    IT school
  • Telegram
  • Партнёрам
  • Все курсы
$ sudo teach IT
OOO "SALEPROFIT"Контакты и реквизитыIT-Park Logo

Школа

  • Блог
  • Проверить сертификат

Сотрудничество

  • Стать учителем
  • Партнёрская программа
  • О проекте

Право

  • Оферта
  • Политика конфиденциальности

© 2023–2026 $ sudo teach IT™. All Rights Reserved. Public user contributions licensed under CC BY-SA 4.0 license with attribution required
TelegramGitHubYouTube
ГлавнаяБлогКак работает компьютерное зрение: от пикселя до распознавания объектов

Как работает компьютерное зрение: от пикселя до распознавания объектов

$ sudo teach IT
·16 июля 2026 г.·9 мин·66
Как работает компьютерное зрение: от пикселя до распознавания объектов

Обзорная статья о ключевых концепциях CV — фильтрации, детекции краёв, contours и базовом распознавании — с примерами на OpenCV и Python.

Содержание
Что такое изображение с точки зрения машиныПредобработка: зачем нужна фильтрацияРазмытие и сглаживаниеПреобразование в оттенки серогоДетекция краёв: где заканчивается один объект и начинается другойОператор СобеляАлгоритм КэнниКонтуры: от краёв к геометрии объектовПоиск и отрисовка контуровАнализ формы через контурыПороговая сегментация и морфологические операцииАдаптивная пороговая обработкаМорфологические операцииБазовое распознавание объектов: каскады ХаараПрактический пайплайн: собираем всё вместеТипичные ошибки и подводные камниКуда двигаться дальшеИтог

Когда смартфон мгновенно распознаёт лицо на фотографии, а беспилотный автомобиль определяет пешехода на дороге — за этим стоит одна и та же дисциплина: компьютерное зрение. Для стороннего наблюдателя это выглядит как магия. Для инженера — это цепочка конкретных математических операций над массивами чисел.

В этой статье мы разберём, как именно машина «видит»: от представления изображения в памяти до детекции объектов. Никакой магии — только механика.


Что такое изображение с точки зрения машины

Прежде чем говорить об алгоритмах, нужно понять, с чем они работают.

Цифровое изображение — это двумерный массив пикселей. Каждый пиксель хранит числовое значение интенсивности. В случае градаций серого это одно число от 0 (чёрный) до 255 (белый). Цветное изображение в формате RGB — это три таких массива, наложенных друг на друга: красный канал, зелёный и синий.

В Python с помощью OpenCV это выглядит так:

code
import cv2
import numpy as np

# Загрузка изображения
img = cv2.imread('photo.jpg')

# Форма массива: (высота, ширина, количество каналов)
print(img.shape)  # например, (480, 640, 3)

# Значение конкретного пикселя (строка 100, столбец 200)
pixel = img[100, 200]
print(pixel)  # например, [120 85 60] — BGR-значения

Важная деталь: OpenCV по умолчанию читает изображения в формате BGR, а не RGB. Это историческое решение, которое регулярно сбивает с толку новичков при визуализации через Matplotlib.

Понимание изображения как числового массива — это фундамент. Все дальнейшие операции компьютерного зрения — это, по сути, математические преобразования этого массива.


Предобработка: зачем нужна фильтрация

Реальные изображения редко бывают идеальными. Шум от матрицы камеры, неравномерное освещение, артефакты сжатия — всё это мешает алгоритмам работать корректно. Поэтому перед анализом изображение, как правило, проходит предобработку.

Размытие и сглаживание

Самый распространённый инструмент предобработки — свёртка (convolution). Идея проста: мы берём небольшую матрицу-ядро (kernel) и «прокатываем» её по изображению, заменяя каждый пиксель взвешенной суммой его соседей.

Гауссово размытие — один из стандартных методов подавления шума:

code
# Гауссово размытие с ядром 5x5
blurred = cv2.GaussianBlur(img, (5, 5), sigmaX=0)

Размер ядра и параметр sigma определяют степень размытия. Чем больше ядро — тем сильнее сглаживание, но и тем больше теряется деталей.

Медианное размытие работает иначе: каждый пиксель заменяется медианным значением из окрестности. Оно особенно эффективно против «соль и перец» — случайных белых и чёрных точек:

code
median_blurred = cv2.medianBlur(img, 5)

Преобразование в оттенки серого

Многие алгоритмы работают с одноканальными изображениями. Перевод в градации серого — стандартный шаг:

code
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

Это не просто «усреднение» каналов. OpenCV использует взвешенную формулу, которая учитывает восприятие яркости человеческим глазом: зелёный канал вносит наибольший вклад, синий — наименьший.


Детекция краёв: где заканчивается один объект и начинается другой

Края — это места резкого изменения интенсивности пикселей. Именно они несут основную структурную информацию об объектах на изображении.

Оператор Собеля

Оператор Собеля вычисляет градиент яркости по горизонтали и вертикали. Там, где градиент велик — есть граница.

code
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Градиент по X и Y
sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)

# Итоговая величина градиента
magnitude = cv2.magnitude(sobel_x, sobel_y)

Алгоритм Кэнни

Canny Edge Detection — один из самых известных алгоритмов в компьютерном зрении. Он был предложен Джоном Кэнни в 1986 году и до сих пор остаётся стандартом де-факто для многих задач.

Алгоритм работает в несколько этапов:

  1. Гауссово размытие для подавления шума
  2. Вычисление градиента (на основе оператора Собеля)
  3. Подавление немаксимумов — оставляем только «гребни» градиента
  4. Двойная пороговая фильтрация — сильные края, слабые края и шум
  5. Трассировка краёв по гистерезису — слабые края сохраняются, только если соединены с сильными
code
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)

# Два порога: нижний и верхний
edges = cv2.Canny(blurred, threshold1=50, threshold2=150)

Выбор порогов — это искусство, которое приходит с опытом. Распространённое эмпирическое правило: верхний порог примерно в 2–3 раза больше нижнего. Но для каждой конкретной задачи значения нужно подбирать.


Контуры: от краёв к геометрии объектов

Детекция краёв даёт нам карту границ. Следующий шаг — объединить эти границы в связные контуры, которые описывают форму объектов.

Поиск и отрисовка контуров

code
# Бинаризация изображения — необходимое условие для findContours
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# Поиск контуров
contours, hierarchy = cv2.findContours(
    thresh,
    cv2.RETR_EXTERNAL,   # только внешние контуры
    cv2.CHAIN_APPROX_SIMPLE  # сжатое представление
)

# Отрисовка всех контуров
output = img.copy()
cv2.drawContours(output, contours, -1, (0, 255, 0), 2)

Параметр cv2.RETR_EXTERNAL возвращает только внешние контуры, игнорируя вложенные. Если нужна иерархия — используйте cv2.RETR_TREE.

Анализ формы через контуры

Контуры — это не просто красивые линии. Из них можно извлечь полезную геометрическую информацию:

code
for cnt in contours:
    # Площадь
    area = cv2.contourArea(cnt)
    
    # Периметр
    perimeter = cv2.arcLength(cnt, closed=True)
    
    # Ограничивающий прямоугольник
    x, y, w, h = cv2.boundingRect(cnt)
    
    # Аппроксимация формы полигоном
    epsilon = 0.02 * perimeter
    approx = cv2.approxPolyDP(cnt, epsilon, closed=True)
    
    # Если 4 вершины — скорее всего прямоугольник
    if len(approx) == 4:
        cv2.rectangle(output, (x, y), (x+w, y+h), (255, 0, 0), 2)

cv2.approxPolyDP реализует алгоритм Дугласа-Пекера: он упрощает контур до полигона с заданной точностью. Это мощный инструмент для классификации форм — треугольники, прямоугольники, многоугольники.


Пороговая сегментация и морфологические операции

Прежде чем искать контуры, изображение нужно бинаризовать — разделить пиксели на «объект» и «фон».

Адаптивная пороговая обработка

Простая пороговая обработка с фиксированным значением плохо работает при неравномерном освещении. Адаптивный порог вычисляет пороговое значение локально, для каждого небольшого региона:

code
# Адаптивный порог на основе среднего по окрестности
adaptive_thresh = cv2.adaptiveThreshold(
    gray, 255,
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
    cv2.THRESH_BINARY,
    blockSize=11,
    C=2
)

Морфологические операции

После бинаризации изображение часто содержит мелкие артефакты. Морфологические операции позволяют их устранить:

code
kernel = np.ones((5, 5), np.uint8)

# Эрозия — уменьшает белые области, убирает мелкий шум
eroded = cv2.erode(thresh, kernel, iterations=1)

# Дилатация — расширяет белые области, заполняет пробелы
dilated = cv2.dilate(thresh, kernel, iterations=1)

# Opening = эрозия + дилатация (убирает шум)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

# Closing = дилатация + эрозия (заполняет дыры)
closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

Базовое распознавание объектов: каскады Хаара

Один из классических подходов к детекции объектов — метод каскадных классификаторов Виолы-Джонса, предложенный в 2001 году. Он основан на признаках Хаара и до сих пор используется для быстрой детекции лиц в реальном времени.

OpenCV поставляется с набором предобученных каскадов:

code
# Загрузка предобученного каскада для детекции лиц
face_cascade = cv2.CascadeClassifier(
    cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Детекция лиц
faces = face_cascade.detectMultiScale(
    gray,
    scaleFactor=1.1,   # масштаб пирамиды изображений
    minNeighbors=5,    # минимум соседних детекций для подтверждения
    minSize=(30, 30)
)

for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)

Параметр scaleFactor определяет, насколько уменьшается изображение на каждом шаге пирамиды. Значение 1.1 означает уменьшение на 10% — это точнее, но медленнее. minNeighbors контролирует количество ложных срабатываний: чем выше значение, тем меньше ложных детекций, но и тем больше риск пропустить реальный объект.

Каскады Хаара хорошо работают для фронтальных лиц при хорошем освещении. Для более сложных сценариев — повороты, частичное перекрытие, разное освещение — нужны современные подходы на основе глубокого обучения: YOLO, SSD, Faster R-CNN.


Практический пайплайн: собираем всё вместе

Рассмотрим типичный пайплайн для подсчёта объектов на изображении — например, монет или деталей на конвейере:

code
import cv2
import numpy as np

def count_objects(image_path):
    # 1. Загрузка и предобработка
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (11, 11), 0)
    
    # 2. Бинаризация
    _, thresh = cv2.threshold(
        blurred, 0, 255,
        cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU  # метод Оцу
    )
    
    # 3. Морфологическая очистка
    kernel = np.ones((3, 3), np.uint8)
    cleaned = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
    
    # 4. Поиск контуров
    contours, _ = cv2.findContours(
        cleaned, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
    )
    
    # 5. Фильтрация по площади (убираем мелкий шум)
    min_area = 500
    valid_contours = [c for c in contours if cv2.contourArea(c) > min_area]
    
    # 6. Визуализация
    result = img.copy()
    cv2.drawContours(result, valid_contours, -1, (0, 255, 0), 2)
    
    print(f"Найдено объектов: {len(valid_contours)}")
    return result, len(valid_contours)

Метод Оцу (cv2.THRESH_OTSU) автоматически находит оптимальное пороговое значение на основе гистограммы изображения — это избавляет от необходимости подбирать порог вручную.

Именно такие пайплайны — основа промышленного компьютерного зрения. Если хочется разобраться в них системно, а не собирать знания по кускам из документации, стоит обратить внимание на структурированные курсы. Например, курс по OpenCV на платформе «$ sudo teach IT» охватывает именно этот практический пласт: от базовых операций с изображениями до построения полноценных CV-пайплайнов.


Типичные ошибки и подводные камни

За годы работы с OpenCV у разработчиков накапливается список граблей, на которые наступают снова и снова.

BGR вместо RGB. OpenCV читает изображения в BGR. Если передать такое изображение в Matplotlib или PIL без конвертации — цвета будут искажены. Решение: cv2.cvtColor(img, cv2.COLOR_BGR2RGB) перед отображением.

Тип данных после операций. После cv2.Sobel с флагом cv2.CV_64F результат содержит отрицательные значения и числа с плавающей точкой. Прямая конвертация в uint8 обрежет отрицательные значения. Правильный подход — взять абсолютное значение и нормализовать.

Неправильный порядок аргументов. В OpenCV координаты часто задаются как (x, y), а индексы массива numpy — как [row, col], то есть [y, x]. Путаница здесь — источник трудноуловимых багов.

Размер ядра должен быть нечётным. Ядра свёртки в OpenCV должны иметь нечётные размеры (3, 5, 7...). Чётное значение вызовет ошибку.

Контуры ищутся только на бинарных изображениях. Передача в findContours цветного или серого изображения без предварительной бинаризации даст непредсказуемый результат.


Куда двигаться дальше

Классическое компьютерное зрение, которое мы разобрали — фильтрация, детекция краёв, контуры, каскадные классификаторы — это фундамент. Он не устарел: эти методы работают быстро, требуют мало ресурсов и хорошо интерпретируемы.

Но современные задачи — распознавание объектов в сложных условиях, семантическая сегментация, трекинг в видео — решаются с помощью глубокого обучения. Свёрточные нейронные сети (CNN) научились автоматически извлекать признаки, которые раньше приходилось задавать вручную.

Путь от пикселя до распознавания объектов сегодня выглядит так: классический CV даёт понимание основ и инструменты для быстрых решений, а нейронные сети берут на себя сложные сценарии. Опытный инженер умеет работать с обоими подходами и выбирать нужный в зависимости от задачи.


Итог

Компьютерное зрение — это не магия, а последовательное применение математических операций к числовым массивам. Свёртка сглаживает шум. Градиент находит границы. Контуры описывают форму. Классификатор принимает решение.

Каждый из этих шагов понятен и воспроизводим. OpenCV предоставляет готовые реализации, но понимание того, что происходит «под капотом», принципиально важно — иначе настройка параметров превращается в гадание на кофейной гуще.

Если вы хотите выстроить эти знания системно — от базовых операций до практических проектов — курс по OpenCV может стать хорошей отправной точкой. Но даже без него: экспериментируйте с кодом из этой статьи, меняйте параметры, смотрите на результат. Компьютерное зрение лучше всего изучается руками.

Войдите, чтобы поставить лайк и оставить комментарий.

Автор

$ sudo teach IT

OpenCV

Курс по теме

OpenCV

Превратите изображения в данные. OpenCV — ключ к компьютерному зрению. От первых пикселей до собственных проектов.

Открыть курс

Продолжите обучение

Все курсы
Python – для начинающих!

Python – для начинающих!

С нуля до профессионального уровня. Подходит для всех. Учитесь каждый день и овладейте самым популярным языком программирования.

Перейти к курсу
Простыми словами о защищенном соединении

Простыми словами о защищенном соединении

Базовый курс для обычных людей: что такое защищённое соединение, как оно устроено, что оно умеет и чего не умеет, как выбрать сервис и настроить его на своих устройствах.

Перейти к курсу
Ботостроение Telegram

Ботостроение Telegram

Лёгкий, быстрый и доступный способ познакомиться с миром ботостроения в Telegram. Видео, конспекты, практика и помощь – всё у нас на курсе.

Перейти к курсу
Сервис, который не падает - как построить безопасную зашифрованную сеть

Сервис, который не падает - как построить безопасную зашифрованную сеть

Практический курс по безопасности сети: как собрать собственный сервис защищённого доступа - от пустого сервера до подписки с автовыбором - и, что важнее, как потом не уронить его своими руками.

Перейти к курсу

Другие статьи

Компьютерное зрение на практике: детектируем объекты на видео с помощью OpenCV и Python
компьютерное

Компьютерное зрение на практике: детектируем объекты на видео с помощью OpenCV и Python

Шаг за шагом строим пайплайн обработки видеопотока: захват кадров, фоновое вычитание, трекинг объектов. Весь код — рабочий, с объяснением каждого параметра.

18 июля 2026 г.
670
OpenCV: калибровка пайплайна — как добиться стабильности детекта на разных освещениях
opencv

OpenCV: калибровка пайплайна — как добиться стабильности детекта на разных освещениях

Разберём предобработку (масштаб, шум, освещение), выбор порогов и контроль качества результатов. Научитесь делать мини-наборы для тестов, чтобы изменения не ломали детект.

26 июля 2026 г.
560
Создание Telegram бота в 2026 легко и просто! Полный курсы!
создание

Создание Telegram бота в 2026 легко и просто! Полный курсы!

19 июня 2026 г.
1431
Как выбрать, куда идти в IT: веб, боты, данные — без хаоса
выбрать

Как выбрать, куда идти в IT: веб, боты, данные — без хаоса

Разберём самые понятные направления для новичка (веб, боты, аналитика/данные) и чем они отличаются по шагам обучения. В конце вы получите простой план, как проверить, что вам подходит, и какой стартовый путь выбрать.

5 октября 2026 г.
580
Путь от README до демо: как собрать портфолио разработчика, чтобы его хотели смотреть
путь

Путь от README до демо: как собрать портфолио разработчика, чтобы его хотели смотреть

Разберём структуру репозитория, как упаковать проект в понятную историю (проблема → решение → запуск → метрики качества) и какие артефакты повышают доверие: скринкасты, архитектурная схема, чек-лист продакшн-готовности.

17 сентября 2026 г.
1090
Как понять, какой язык программирования учить первым: простой тест и выбор
понять

Как понять, какой язык программирования учить первым: простой тест и выбор

Помогу новичку выбрать первый язык без стресса: объясню варианты по целям (веб, боты, анализ данных), что учить в первую очередь и как не потратить месяцы впустую. В конце — краткий план старта на ближайшие недели.

2 октября 2026 г.
630

Комментарии

Станьте первым в обсуждении

Поделитесь мнением о статье или задайте вопрос автору

Содержание

Что такое изображение с точки зрения машиныПредобработка: зачем нужна фильтрацияРазмытие и сглаживаниеПреобразование в оттенки серогоДетекция краёв: где заканчивается один объект и начинается другойОператор СобеляАлгоритм КэнниКонтуры: от краёв к геометрии объектовПоиск и отрисовка контуровАнализ формы через контурыПороговая сегментация и морфологические операцииАдаптивная пороговая обработкаМорфологические операцииБазовое распознавание объектов: каскады ХаараПрактический пайплайн: собираем всё вместеТипичные ошибки и подводные камниКуда двигаться дальшеИтог