Задать вопрос
Ответы пользователя по тегу OpenCV
  • Как создать свой каскад для распознавания объектов?

    Vindicar
    @Vindicar
    RTFM!
    Я создавал лабораторную по этой теме, могу привести инструкцию.
    1. Загрузите набор утилит opencv(гугл-диск, но я советую поискать самостоятельно), в частности opencv_createsamples и opencv_traincascade, а также необходимые им DLL-библиотеки. Распакуйте их в рабочий каталог в корне диска, без русских букв и пробелов в названии. Здесь и далее предполагается, что C:\MyDirName - ваш рабочий каталог.
    2. Подготовьте фото вашего объекта. Используйте контрастный объект без движущихся частей, и желательно не дающий бликов. Для этой цели хорошо подходят логотипы.
    3. Подготовьте отрицательные примеры (не менее 100 изображений). Для этого можно снять короткое видео помещения, затем написать программу, которая разделяет это видео на отдельные кадры. Рекомендуется поместить их в отдельный подкаталог negatives.
    4. Подготовьте файлы, содержащие список файлов в этом каталоге. Их можно сгенерировать следующей парой команд в терминале:
      dir C:\MyDirName\negatives\*.jpg /B /S >C:\MyDirName\negatives\negatives_abs.txt

      dir C:\MyDirName\negatives\*.jpg /B >C:\MyDirName\negatives\negatives_rel.txt

    5. Создайте пустые подкаталоги C:\MyDirName\positives и C:\MyDirName\training. Поместите ваше изображение - положительный пример в каталог C:\MyDirName\ и назовите его positive.jpg. В качестве положительного примера желательно разместить ваш объект на светлом фоне, если он тёмный, и наоборот.
    6. Сгенерируйте положительные примеры с помощью утилиты opencv_createsamples. Команда будет выглядеть примерно следующим образом:
      C:\MyDirName\opencv_createsamples.exe -info positives\info.lst -img positive.jpg -bg negatives\negatives_rel.txt -maxxangle 0.1 -maxyangle 0.1 -maxzangle 0.1 -bgcolor 0 -bgthresh 0 -w 50 -h 50 -num 100

      Параметры:
      -info - выходной файл.
      -img - входное изображение - положительный пример
      -bg - фоновые изображения. Положительный пример будет наложен на них (в оттенках серого).
      -max?angle - допустимые углы поворота примера. Утилита выполнит перспективное преобразование примера перед наложением.
      -bgcolor и -bgthresh задают яркость (среднее и диапазон изменения) для "прозрачного цвета". Например, если ваш объект на белом фоне, задайте эти параметры равными 240 и 15 (диапазон яркости 225-255). Задав оба параметра равными 0, вы отключите эту функцию и все цвета будут непрозрачными.
      -w и -h задают минимальный размер для размещаемой копии вашего образца.
      -num - количество примеров, которые стоит генерировать. Не должно превышать количество изображений в каталоге.
      Утилита должна вывести ряд сообщений вида "Open background image", а в конце вывести "Done".
    7. Сгенерируйте vec файл следующей командой:
      C:\MyDirName\opencv_createsamples.exe -info positives\info.lst -num 100 -w 20 -h 20 -vec positives\positives.vec

      где info.lst был сгенерирован в ходе пункта 6.
      -w и -h задают минимальный размер для объекта, распознаваемого в ходе работы каскада.
      -num - количество сгенерированных примеров. Столько же, сколько и в пункте 6.
    8. Проведите обучение каскада с помощью утилиты opencv_traincascade. Команда будет иметь примерно следующий вид:
      C:\MyDirName\opencv_traincascade.exe -data training -vec positives\positives.vec -bg negatives\negatives_abs.txt -numStages 100 -numPos 100 -numNeg 100 -featureType haar -w 20 -h 20 -minHitRate 0.999 -maxFalseAlarmRate 0.4 -precalcValBufSize 4048 -precalcIdxBufSize 4048 -numThreads 24 -acceptanceRatioBreakValue 10e-5

      -data - каталог для рабочих данных, который вы создали в пункте 5.
      -vec - индекс, который был создан в пункте 7.
      -bg - файл со списком отрицательных примеров (используйте абсолютные пути!)
      -numPos и -numNeg - количество положительных примеров (пункт 6) и отрицательных примеров (пункт 3).
      -numStages - максимальное количество этапов каскада. Итоговый каскад может содержать меньшее количество этапов.
      -featureType - определяет тип признаков. Признаки Хаара обучаются медленнее, но зато более точны.
      -w и -h задают минимальный размер для объекта, распознаваемого в ходе работы каскада. Должны строго совпадать с заданными в пункте 7.
      -minHitRate и -maxFalseAlarmRate задают качество работы одного каскада.
      -acceptanceRatioBreakValue определяет момент, когда каскад перестаёт обучаться.
      -precalcValBufSize и -precalcIdxBufSize задают потребление памяти процессом.
      -numThreads определяет число рабочих потоков.
    9. По итогам обучения в каталоге training должен появиться файл cascade.xml, который можно загружать так же, как типовые каскады, поставляемые с opencv. Обратите внимание, что если вы хотите запустить обучение с начала, нужно очистить содержимое каталога training, иначе утилита будет дообучать существующий каскад.
    Ответ написан
    5 комментариев
  • Как бот должен понимать что нужно нажимать кнопку во время qte?

    Vindicar
    @Vindicar
    RTFM!
    Template matching попробуй.
    Ответ написан
    Комментировать
  • Почему не работает detectMultiScale python?

    Vindicar
    @Vindicar
    RTFM!
    face_cascade = "C:\mine\haarcascade_frontalface_alt.xml"
    ...
    face_cascade.detectMultiScale(

    У тебя face_cascade - это строка. Чего ты ожидаешь-то от неё? Класс строки понятия не имеет ни про какие каскады Хаара.
    Сдаётся мне, ты пропустил этап собственно загрузки каскада из указанного файла. А именно, вызов конструктора cv2.CascadeClassifier().
    Ответ написан
    1 комментарий
  • OpenCV не видит камеру. Что делать?

    Vindicar
    @Vindicar
    RTFM!
    Сколько камер на том компе, где не работает?
    Потому что параметр VideoCapture() - это, условно, номер камеры в списке камер. Если на компе только одна камера, то номер должен быть 0, если две, то номера будут 0 и 1, и так далее.
    Способа открыть камеру по имени сам opencv не предоставляет, хотя вроде есть сторонние пакеты, которые это исправляют - в плане получения списка камер в том же порядке, в каком их индексы будут использоваться VideoCapture().
    Ответ написан
    1 комментарий
  • Почему возникает ошибка error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor'?

    Vindicar
    @Vindicar
    RTFM!
    _, image = cap.read()
    Не _, а success_code, то бишь признак успешности чтения. Проверь, читается ли у тебя вообще кадр с камеры.
    Ответ написан
    Комментировать
  • Как поменять начало координат на выделеной области cv2?

    Vindicar
    @Vindicar
    RTFM!
    Не очень понятно, что ты имеешь ввиду. cv2 всегда сообщает клики в координатах окна. Они, как правило, совпадают с координатами внутри показанного в окне изображения: та же точка отсчёта, то же направление осей, масштаб 1:1. Единственное отличие - если ты увеличил размер окна, клик может оказаться за пределами показанного изображения.

    Если тебе нужна другая координатная система, пересчитывай координаты сам.
    Ответ написан
    Комментировать
  • Как сопоставить два изображения чтобы убрать сдвиг?

    Vindicar
    @Vindicar
    RTFM!
    cv2.goodFeaturesToTrack() чтобы найти "узнаваемые точки" на каждом изображении.
    cv2.calcOpticalFlowPyrLK() чтобы понять, насколько они сдвинулись. Далее выбираешь точки вокруг интересующего объекта, вычитаешь из их позиций их предыдущие позиции, усредняешь, получаешь вектор среднего смещения за кадр. На основании этого вектора уже что-то делаешь с изображением.
    Например, если тебе нужно сглаживать резкие рывки, может иметь смысл отслеживать значение среднего смещения от кадра к кадру. Если смещение в каком-то кадре резко изменилось (заметно отличается от среднего за предыдущие N кадров), значит, кадр нужно сдвинуть.
    Ответ написан
  • Как наложить одно изображение на другое без размытия, смешивания и прозрачности?

    Vindicar
    @Vindicar
    RTFM!
    Если нужно заменить прямоугольник пикселей, то это делается тривиально:
    img1[top1:bottom1, left1:right1] = img2[top2:bottom2, left2:right2]

    Единственное требование - прямоугольники должны иметь одинаковый размер.
    Как следствие, если вторая картинка может заезжать за край первой, то задача усложняется.

    Если же нужно работать с альфа-каналом, то для начала его неплохо бы прочитать.
    image = cv2.imread('image.png', cv2.IMREAD_UNCHANGED)

    UNCHANGED не преобразует в BGR, а грузит как есть, в том числе альфа канал.
    И тогда нужно будет сделать что-то типа
    mask = image[..., 3] > 0  # если считаем, что чем меньше - тем прозрачнее
    background[top:bottom, left:right][mask] = image[mask]  # не забываем про равенство размера!
    Ответ написан
  • Как сделать чтобы он рисовал один прямоугольник до отпускания, а не рисовал кучу?

    Vindicar
    @Vindicar
    RTFM!
    Еще один шикарный пример вопроса не по теме. В заголвоке вопроса лаги, а по делу
    Как сделать чтобы он рисовал один прямоугольник до отпускания, а не рисовал кучу?


    Потому что ты рисуешь множество прямоугольников, не стирая их.
    Когда ты рисуешь прямоугольник - ты изменяешь изображение. И следующий рисуешь уже на изменённом изображении. Вот и получается множество прямоугольников.

    Тебе нужно делать копию оригинального изображения, рисовать на ней, и показывать эту изменённую копию.
    import cv2
    import sys
    import matplotlib.pyplot as plt
    original = cv2.imread(sys.argv[1])
    ix = -1
    iy = -1
    drawing = False
    
    def draw_reactangle_with_drag(event, x, y, flags, param):
        global ix, iy, drawing, original
        if event == cv2.EVENT_LBUTTONDOWN:
            drawing = True
            ix = x
            iy = y
        elif event == cv2.EVENT_MOUSEMOVE:
            if drawing == True:
                img = original.copy()
                cv2.rectangle(img, pt1=(ix,iy), pt2=(x, y),color=(0,255,255),thickness=10)
                cv2.imshow("Title of Popup Window", img)
        elif event == cv2.EVENT_LBUTTONUP:
            drawing = False
            img = original.copy()
            cv2.rectangle(img, pt1=(ix,iy), pt2=(x, y),color=(0,255,255),thickness=10)
            print(ix, iy, x, y)
            cv2.imshow("Title of Popup Window", img)
    
    cv2.namedWindow(winname= "Title of Popup Window")
    cv2.setMouseCallback("Title of Popup Window", draw_reactangle_with_drag)
    cv2.imshow("Title of Popup Window", original)
    while True:
        if cv2.waitKey(10) == 27:
            break
    cv2.destroyAllWindows()


    А вообще, если ты хочешь сделать выделение области рамкой, cv2.selectROI() в помощь.
    Ответ написан
    3 комментария
  • Прозрачный цвет цветовых пикселей. как сделать?

    Vindicar
    @Vindicar
    RTFM!
    cv2_inwrite(/content/2 (1).jpeg, im)
    Во-первых, куда кавычки подевал?
    Во-вторых, jpeg не поддерживает прозрачность.
    В-третьих, обычное изображение - это массив вида (H, W, 3), где W и H - ширина и высота в пикселях, а 3 - каналы RGB.
    Тебе нужно создать изображение вида (H, W, 4), скопировать в него твоё изображение в первые три канала, затем заполнить последний канал значениями прозрачности (255 для совсем непрозрачных, 0 для совсем прозрачных).
    Так как cv2 хранит писксели в массиве numpy, читай туториалы по работе с массивами numpy, чтобы понять, как это сделать.
    Затем сохрани изображение в формате, поддерживающем прозрачность, например в PNG.
    Ответ написан
    4 комментария
  • Как получить все 3 канала изображения?

    Vindicar
    @Vindicar
    RTFM!
    По умолчанию каналы изображения в opencv идут в порядке blue, green, red.
    Так что 0 - это blue, ну и так далее.
    Ответ написан
  • Как дать имя отдельным секторам в изображении?

    Vindicar
    @Vindicar
    RTFM!
    Вообще ответ зависит от конкретной задачи.
    У тебя преобразование каждого кусочка идёт независимо от остальных?
    Если да, то всё сильно упрощается. Опиши функцию вида:
    def process_one_part(part: numpy.ndarray) -> numpy.ndarray:
        ...

    Которая будет обрабатывать один фрагмент изображения.
    А дальше собрать их абсолютно тривиально, точно также, как ты их резал:
    # пустое изображение такого же размера, как исходное, с тремя каналами по 8 бит на канал
    # если на выходе у тебя другое число каналов или тип данных, поправишь
    result = numpy.zeros(image.shape[:2] + (3,), numpy.uint8)
    
    for i in range(img_h // bl_h):
      for j in range(img_w // bl_w):
        cropped = image[i*bl_h:(i+1)* bl_h, j*bl_w:(j+1)*bl_w]
        processed = process_one_part(cropped)
        # нужно, чтобы присваиваемый фрагмент имел такой же размер, как "окно" присваивания
        result[i*bl_h:(i+1)* bl_h, j*bl_w:(j+1)*bl_w] = processed
    # дальше делаешь с result что тебе нужно


    Ну и да... причём тут вообще имя?
    Ответ написан
  • Как определить квадрат, прямоугольник и пустой фон OpenCV?

    Vindicar
    @Vindicar
    RTFM!
    Можешь попробовать найти контур, а потом использовать cv2.minAreaRect() для поиска минимального повёрнутого ограничивающего прямоугольника. minAreaRect() тебе вернёт кортеж вида (cx, cy), (w, h), angle, где cx, cy - координаты центра, w, h - размеры прямоугольника, angle - угол поворота в градусах.
    Имей ввиду, что отношение w/h будет близко к единице для квадратов, но не обязательно равно единице. Тебе придётся выбрать какой-то порог отсечения.

    А ещё посоветую ознакомиться вот с этой статьёй, там тоже интересный подход.
    Ответ написан
    1 комментарий
  • Как сигнализировать когда объект выходит за границы?

    Vindicar
    @Vindicar
    RTFM!
    Вопрос и впрямь не по питону, алгоритм легко портируется.
    Если нужно детектить именно пересечение любой из точек границы, и именно для круга и квадрата, то это очень просто. Уменьши квадрат, сдвинь каждую сторону внутрь на радиус круга.
    Например, у тебя был квадрат от (0;0) до (100;100), круг радиусом 10 (диаметром 20). Новый квадрат будет от (10;10) до (90;90).
    После этого проверяй, входит ли центр круга внутрь нового квадрата. Если входит - круг внутри исходного квадрата. Если центр на стороне - круг касается стороны исходного квадрата. Если центр вне нового квадрата - круг вышел за границу исходного.
    Проверка вхождения точки внутрь ортогонального (стороны параллельны осям координат) прямоугольника выполняется тривиально, сам догадаешься как.

    Есть второй способ, базируется на массивах numpy (python-opencv их использует для хранения массивов пикселей изображения).
    Делаешь два изображения-маски (одноканальных, одного размера), одно для одного объекта, другое для другого. В твоём случае одно (A) будет содержать белый круг на чёрном фоне, а другое (B) - чёрный квадрат на белом фоне.
    Тогда можно будет сделать так:
    intersection = numpy.logical_and(A, B)
    if intersection.any():
        print('Collision!')

    logical_and() вернёт логический массив того же размера, что A и B. Элемент массива будет истиннен только если соотвествующие элементы в A и B будут ненулевыми.
    Таким образом, если два объекта пересекаются, то logical_and() вернёт True для пересёкшихся пикселей.
    А метод any() вернёт True если любой элемент массива истинен, т.е. если есть хоть один пересёкшийся пиксель.

    Этот метод куда более ресурсоёмкий, чем то что я описал в выше,но зато работает для объектов произвольной формы. Только нарисуй их.
    Кроме того, можно сделать numpy.count_nonzero(intersection), чтобы узнать, насколько велико пересечение (сколько пикселей в нём). Это тоже может быть полезно если ты хочешь "прощать" небольшие пересечения.
    Ответ написан
    2 комментария
  • Как правильно отобразить окна на разных экранах?

    Vindicar
    @Vindicar
    RTFM!
    Гуглить пробовал?
    Первая же ссылка выводит на пакет screeninfo.
    Его пробовал использовать?
    Ответ написан
  • Как обновлять изображение OpenCV Python?

    Vindicar
    @Vindicar
    RTFM!
    1. Если интервал обновления известен, и некоторая задержка между обновлением файла и обновлением видимой картинки не критична, то просто заворачиваешь код в цикл while с нужной задержкой. Для задержки можешь использовать параметр waitKey(), это задержка в миллисекундах.
    2. Если обновление нерегулярное, а обновлять изображение нужно немедленно по изменению файла, то ставь пакет watchdog, он позволяет реагировать на изменение файла.
    Ответ написан
    Комментировать
  • Как вытащить все белые объекты и измерить их белизну OpenCV?

    Vindicar
    @Vindicar
    RTFM!
    Преобразуй кадр в цветовую систему HSV, ищи пиксели, у которых канал Saturation ниже заданного порога (т.е. они более-менее серые), а канал Value выше заданного порога (т.е. они более-менее яркие). По полученной маске уже отбирай пиксели для анализа.

    Либо можно схитрить, если использовать более сложный эталон, например, шахматную доску. cv2.findChessboardCorners() позволит найти координаты углов *внутри* доски известного размера, например, для доски 8х4 нужно указывать размер 7х3. Найди крайние угловые точки, извлеки этот кусок кадра. На нём точно будут только светлые и тёмные пиксели твоего эталона, чей цвет ты контролируешь. Прогони пороговое преобразование алгоритмом Otsu (есть в опенцв из коробки), получишь маску светлых пикселей. Их уже анализируешь.
    Ответ написан
    5 комментариев
  • Имеется скрипт на Python с OpenCV как транслировать результат(сделать источником видео) в skype, zoom или любую другую программу в реальном времени?

    Vindicar
    @Vindicar
    RTFM!
    Это НЕ простая задача, и сделать её самостоятельно малореально. Про кросплатформенность можно забыть, портируемость обеспечить тоже будет не столь тривиально.
    В качестве костыльного решения можно попробовать установить пакет pyvirtualcam, но у него нетривиальные зависимости. Может потребоваться установить OBS и плагин OBS Virtual Сamera в придачу.
    Ответ написан
    Комментировать
  • Как сделать выбор координат на клик в OpenCV?

    Vindicar
    @Vindicar
    RTFM!
    Сделай список, добавляй в него кортежи (x, y).
    Если по клику список достиг полной длины, уже действуй дальше.
    Ответ написан