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

    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).
    Если по клику список достиг полной длины, уже действуй дальше.
    Ответ написан
  • Детектор движения отдельных объектов OpenCV на Python, как можно реализовать?

    Vindicar
    @Vindicar
    RTFM!
    Такой вопрос уже был, повторю свой ответ: создай изображение-маску, и по этой маске закрашивай одним цветом неинтересные тебе части кадра перед их отправкой на сравнение. В закрашенных частях движения не будет по определению.
    Ответ написан
    Комментировать
  • Как в OpenCV сделать постройку грида с обновляемыми фото?

    Vindicar
    @Vindicar
    RTFM!
    Изображение в opencv-python - это numpy массив, там можно обновлять области с помощью срезов.
    Например, прямоугольная область с левым верхним углом (X;Y) и размером W x H обновляется тривиально:
    image[Y:Y+H, X:X+W] = new_content
    При этом подразумевается что new_content имеет размер W x H и такое же число каналов.

    Т.е. можно для каждого изображения в сетке хранить его позицию, и обновлять его область отдельно.
    Ответ написан
    Комментировать
  • Возникает проблема с фреймворком opencv python, почему?

    Vindicar
    @Vindicar
    RTFM!
    Проверяй значение ret. Если оно не истинно, то кадр получить не удалось. Что в этом случае будет в img - хороший вопрос.
    Может быть, камера занята каким-то другим процессом. Например, предыдущей копией твоей программы.
    Ответ написан
    Комментировать
  • Как заменить цвет пикселей cv2?

    Vindicar
    @Vindicar
    RTFM!
    В cv2 изображения - это массивы numpy, так что все трюки с индексацией из numpy работают. Очень советую их изучить.
    find = 1,2,3 # какие значения заменять
    replace = 4,5,6 # на какие значения заменять
    mask = (bgr == find)[..., 0]
    bgr[mask] = replace
    Ответ написан
    8 комментариев
  • Python, OpenCV, tkinter все окна в одном, как реализовать?

    Vindicar
    @Vindicar
    RTFM!
    Ну так собери изображения в одно, в чём проблема?
    Пусть ты хочешь сделать такую сетку:
    A B
    C D

    Тогда ширина итогового изображения R будет max(A.shape[1]+B.shape[1], C.shape[1]+D.shape[1]), а высота max(A.shape[0]+C.shape[0], B.shape[0]+D.shape[0])
    Отступ по X для изображений B и D будет max(A.shape[1], C.shape[1]), отступ по Y для C и D будет max(A.shape[0], B.shape[0]).
    Ну а перенос прямоугольной области из массива в массив в numpy делается тривиально.
    R[0:A.shape[0], 0:A.shape[1]] = A
    R[0:B.shape[0], X:X+B.shape[1]] = B
    R[Y:Y+C.shape[0], 0:C.shape[1]] = C
    R[Y:Y+D.shape[0], X:X+D.shape[1]] = D
    Ответ написан
    Комментировать
  • Детектор движения на Python?

    Vindicar
    @Vindicar
    RTFM!
    Выбирать область, в которой может быть сдвиг?

    Формируете маску игнорируемых областей, по этой маске заливаете "ненужные" пиксели одним цветом, а потом уже обрабатываете. В залитых пикселях движения точно не будет. =)

    Задача- у статичной студии выявлять не двинул ли ведущий декорации,

    Т.е. нужно обнаружить сам факт движения, а не выделить область, где оно произошло?
    Я бы прошелся небольшим blur'ом по эталонному кадру и по текущему, а потом попиксельно вычел. Остаток прогнать через пороговое преобразование, если есть заметное смещение - значит, что-то не так.
    Но будет работать только если освещение не меняется, а в анализируемую зону не падает тень от ведущего.
    Если декорации цветные, то это можно отчасти нивелировать, работая в системе цветности HSV по каналу Hue (оттенок), игнорируя Saturation (насыщенность) и Value (яркость).
    Ответ написан
    2 комментария
  • Как определять движение в движущейся камере python?

    Vindicar
    @Vindicar
    RTFM!
    В общем и целом решения нет, так как отличить движение объекта от эффекта параллакса затруднительно, да и опираться на координаты тоже будет проблематично.
    Ты можешь поэкспериментировать с оптическим потоком, чтобы попытаться понять, в каком направлении сместилась камера, и пытаться либо произвести контр-смещение кадра перед использованием mean of gaussians, либо отсеивать объекты, у которых величина собственного смещения слишком близка к найденному движению камеры (со знаком минус). Первое реально работает только при съёмке с рук стоящего человека, т.е. когда смещения сравнительно малы. Если нужно ловить движение, когда камера тоже движется в одном направлении, шансов очень мало.
    Так или иначе, тебе наверняка придётся самому реализовывать тот или иной алгоритм background subtraction, чтобы иметь возможность вмешаться в его работу для компенсации движения.
    Ответ написан
    1 комментарий