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

    Vindicar
    @Vindicar
    RTFM!
    Т.е. размер искомого объекта известен заранее, поворотов и прочих искажений нет? Положение отпечатков на скриншоте всегда одинаковое? Вытаскиваешь их со скрина срезами (slice), тривиальная задача в opencv.
    А дальше Template matching в помощь, его тут должно хватить. Template matching составляет для изображения карту похожести. Чем больше значение в карте, тем больше окрестность этого пикселя похожа на заданный образец.
    Так что берешь каждый кусок отпечатка, делаешь template matching с самим собой (чтобы понять, какое значение похожести считать идеальным), потом делаешь template matching с отпечатком. Ищешь в карте похожести максимум. Если этот максимум сравним с идеальным (разница в пределах N%, придётся подбирать), значит, такой кусок на отпечатке есть. Если этот максимум значительно меньше, значит, такого куска на отпечатке нет.
    Скриншоты и мышетыканье в окно - это отдельные модули, за ними в гугл. Хотя поначалу можно просто выводить в консоль номера кусков отпечатка, которые нашлись.

    P.S.: код не проси. Приходи со своим (а не чатгптшным!), тогда будет что обсуждать.
    Ответ написан
    1 комментарий
  • Методы для поиска объектов на изображениях?

    Vindicar
    @Vindicar
    RTFM!
    почитать подробно про методы

    Хотелось бы понять какой метод, для какой задачи больше походит

    Не, ну ты выбери что-то одно. Или ты въезжаешь в кишки одного метода, или ты ищешь инфу по верхам.

    Навскидку, ключевые вещи на которые нужно смотреть это трудоёмкость, инвариантность и поддержка множественных экземпляров. Первое определяет, насколько сложно подготовить детектор объектов этим методом. Второе определяет, сломается ли метод если искомый объект повернуть/увеличить/ярко осветить/и т.п. Третье определяет, сломается ли метод, если искомый объект присутсвует в нескольких экземплярах.

    Например, методы перебора с голосованием вроде алгоритма Хафа. Хорошо работает для геометрических примитивов, поддерживает несколько экземпляров. Но произвольные трансформации обрабатывает плохо, слишком много вариантов. Для задач вроде "найти кнопку на экране" подходит очень хорошо.

    Каскады Хаара. Требуют контрастных объектов, не справляются с поворотами, могут быть чувствительны к масштабы. Долго обучаются, но довольно быстро работают. Сейчас их редко применяют.

    Методы, основанные на локальных особенностях. Требуют "пёстрых" объектов с множеством заметных деталей (в идеале контрастных углов), и не справляются с деформируемыми объектами или очень разными ракурсами. Легко справляются с произвольными трансформациями, но ломаются на множественных экземплярах. Это придётся обходить, обрабатывая изображение по частям. Зато если объект простой (условно, обложка книги), им обычно хватает одного изображения.

    Свёрточные нейронки вроде семейства YOLO. Можно научить много на что, и скорость работы у них стабильная, но нужна большая размеченная база для обучения. Причём если в базе не было скажем, повёрнутых изображений, нейронка их не научится распознавать. Отчасти обучающую базу можно расширить джиттерингом, но готовить её всё равно придётся, причём речь идёт о сотнях и тысячах изображений.
    Ответ написан
    1 комментарий
  • Как найти паттерн на картинке с OpenCV?

    Vindicar
    @Vindicar
    RTFM!
    Во-первых, оформи код, нечитаемо. Кнопка </> в помощь.
    Во-вторых, matchTemplate(), насколько я знаю, не-инвариантна к поворотам и масштабу. Иными словами, поворот или изменение размера целевого объекта сломают сопоставление.
    В-третьих, на показанном кадре более одного экземпляра целевого объекта. Так предполагается или нет? Если предполагается, сколько экземпляров ожидается? Потому что разница очень большая с точки зрения методики.

    Варианта тут три.
    1. пытаться обучать под задачу нейронку. А лучше дообучить существующую, скажем, YOLOv5. Но тебе потребуется минимум несколько сотен размеченных изображений объекта в разных комбинациях, плюс в 2-3 раза больше похожих изображений без целевого объекта. Готовить такую базу будет утомительно, да и само обучение требует понимания что ты делаешь.
    2. попробовать зафиксировать угол поворота или масштаб (т.е. допустить, что он всегда одинаков). Тогда другой параметр можно будет подбирать. Например, мы фиксируем масштаб и делаем 16 изображений объекта в разных поворотах, а потом поочерёдно ищем каждый вариант на кадре. Потом анализируем силу откликов - сколько их, насколько они сильные и т.д. Скорее всего, будет медленно
    3. взять за основу поиск по локальным особенностям. Он справляется с масштабом и поворотом, но не справляется с несколькими экземплярами объекта. Это можно забороть, если использовать скользящее окно. Иными словами, находим на кадре узнаваемые точки - локальные особенности (желательно достаточно много и достаточно плотно), используя алгоритмы вроде ORB или SIFT. Затем выбираем те из них, которые попадают в прямоугольную рамку-окно. Затем сверяем эти особенности с особенностями объекта, используя RANSAC или подобный метод. Если получилось хороше совпадение - значит, в этой рамке есть объект или значительная его часть, и мы можем оценить его позицию в кадре в целом. Повторяем процесс, сдвигая рамку, пока оно не "обойдёт" всё изображение. Тоже может быть небыстро, так как нам требуется неоднократный поиск по картинке.
    Ответ написан
    Комментировать
  • Как изменить код для работы с видео?

    Vindicar
    @Vindicar
    RTFM!
    Тебе модель, скорее всего, отдаст экземпляр класса Detections.
    Если его посмотреть, там есть несколько полезных методов, например, render(), который возвращает список обработанных изображений с отрисованными объектами. А ещё у него есть свойства imgs, xywh и names, чтобы получить обработанные изображения, рамки и классы найденного. Экспериментируй с ними
    Не забываем, что модель рассчитана на подачу пачки изображений, просто эта пачка может содержать и только одно изображение. Отсюда и множественное число, и постоянные массивы.
    Ответ написан
    Комментировать
  • Как склеить 2 и более изображения с помощью поиска локальных особенностей?

    Vindicar
    @Vindicar
    RTFM!
    Можно сделать так:
    1. Вычисляешь матрицу преобразования, которому нужно подвергнуть изображение 2, чтобы склеить его с изображением 1 (далее, 2->1).
    2. Вычисляешь матрицу преобразования 3->2.
    3. Склеиваешь 3 с 2, используя матрицу 3->2.
    4. Склеиваешь сумму 3 и 2 с 1, используя матрицу 2->1.
    Альтернативно, ты можешь подвергнуть 3 преобразованию 3->2, а потом 2->1 (либо последовательно, либо перемножив их матрицы), чтобы перевести его в систему отсчёта изображения 1, и склеить их непосредственно.

    Таким образом можно построить дерево преобразований, где все изображения приводятся к ракурсу "корневого" изображения. Большой плюс этого подхода в том, что нам не требуется физически соединять все изображения в одно огромное полотно - если мы рассчитали матрицу преобразования для каждого изображения, мы можем преобразовывать каждое изображение тогда, когда оно требуется. Но можно и соединить, почему бы нет.

    Ещё я не вполне понял, что ты имеешь ввиду под "панорамное изображение".
    Но я подозреваю, это может быть вызвано тем, что на выбранном корневом (первом) изображении ракурс отличается от "нормального" - строго перпендикулярного целевой плоскости. Тогда тебе нужно выбрать такое изображение, на котором ты можешь более-менее точно определить целевую плоскость. ТУт может помочь какой-нибудь маркер типо QR-кода, aruco-маркера, да хоть банальный шахматный шаблон (с ним, кстати, проще всего). Главное, чтобы его размер был известен, и он был прямоугольный. Тогда можно будет рассчитать преобразование для этого изображения, которое исправит перспективу. Мы будем "смотреть прямо" на плоскость, где расположен этот шаблон. Это исправленное изображение и будет для нас корневым, к которому мы будем "пристёгивать" остальные.
    Ответ написан
    Комментировать
  • Хочу написать python Бота который играет в сапер за меня, и наверное мне нужно наставление более опытного?

    Vindicar
    @Vindicar
    RTFM!
    1. Ввод данных
    Окей, гугл, как сделать скриншот в питоне

    2. Предобработка данных
    Используя что-то типа opencv matchTemplate(), превращаешь скриншот в двухмерный массив, описывающий игровое поле.

    3. Принятие решения
    Имея двухмерный массив, описывающий поле, определи, где надо ставить мину. Если решение принять не удаётся - определи, какую клетку надо открывать.

    4. Реализация решения
    Зная номер клетки, выполнить щелчок по ней. См. pyautogui.
    Ответ написан
    Комментировать
  • Распознавание капчи на python, как улучшить результат?

    Vindicar
    @Vindicar
    RTFM!
    Ну так ты хреначишь BGR2GRAY+пороговое преобразование с фиксированным порогом, и думаешь что оно само сработает? Волшебную кнопку ждёшь?
    Попробуй перегнать в HSV и поэкспериментируй с каналами, посмотри, какой наиболее информативный. Используй алгоритм Otsu для определения порога.
    Попробуй разбить текст на символы, например, через connected components with stats. Если символы не касаются друг друга, должно сработать. Если касаются, то будет сложнее - нужно будет как-то разделять их ДО порогового преобразования.
    Потом уже пробуй распознать каждый символ. Если шрифт всегда один и тот же, то может и pytesseract не понадобится, просто собери образцы символов и ищи их через generalized Hough-Guil.
    Ответ написан
    Комментировать
  • Как выделить элемент не останавливая воспроизведение видео (OPENCV)?

    Vindicar
    @Vindicar
    RTFM!
    Ну а как ты себе представляешь быстрое задание И позиции И примерного размера объекта?
    А оно должно быть быстрым, так как объект может двигаться по кадру.

    Ты можешь притормаживать видео, пока пользователь держит зажатой левую клавишу мыши.
    Тогда у тебя будет реакция на нажатие левой клавиши (останавливаем видео, фиксируем одну вершину прямоугольника, содержащего объект) и на отпускание левой клавиши (фиксируем противоположную вершину, извлекаем область, содержащую объект, начинаем его отслеживать и продолжаем видео).
    Ответ написан
    Комментировать
  • Как решить module 'cv2' has no attribute 'TrackerCSRT_create'?

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

    Vindicar
    @Vindicar
    RTFM!
    for i in range(len(zones)):
                        pin = i + 2  # Номер пина соответствует номеру зоны + 1
                        if i+1 in in_zones:
                            # Если объект находится в зоне, зажигаем светодиод
                            board.digital[pin].write(1)
                        else:
                            pin = i + 2
                            # Если объект не находится в зоне, гасим светодиод  <--- НАПРАСНО
                            board.digital[pin].write(0)

    Косяк вот тут. Если текущий объект не находится в зоне, это не значит что никакой другой, ранее найденный объект не находится в этой зоне.
    Сделай массив bool по числу зон, в начале итерации выставь все элементы в false. По ходу итерации выставляй элемент в true если в зоне найден человек.
    В конце итерации выставляй светодиоды по элементам массива.
    Ответ написан
    1 комментарий
  • Можно ли задать условия для работы opencv?

    Vindicar
    @Vindicar
    RTFM!
    Ну и в чём вопрос? У тебя в коде уже есть проверка на силу совпадения (сравнение найденного максимума силы с некоторым порогом). Если тебе нужно выполнять другое действие, то добавь ветку else туда.
    Если тебе нужно просто крутить цикл, и выполнять действие, когда изображение найдётся, можешь завернуть в цикл while тело red() или даже просто вызывать её саму в цикле. Условие завершения цикла обдумай сам, я без понятия что ты хочешь сделать.
    Ответ написан
    Комментировать
  • Как распознать тип движения с помощью opencv?

    Vindicar
    @Vindicar
    RTFM!
    Можешь познакомиться с этой лекцией, там есть интересные идеи.
    Ответ написан
    Комментировать
  • Ошибка: cv2.error: OpenCV(4.8.0) :-1: error: (-5:Bad argument) in function 'cvtColor', как исправить?

    Vindicar
    @Vindicar
    RTFM!
    Почитать документацию на cvtColor() и осознать, что она принимает на вход объект изображения, а не VideoCapture(), который ты ей передаёшь. Так что тебе придётся преобразовывать в нужную цветовую систему каждый кадр отдельно.

    А еще почитать доки на VideoCapture(), в частности, про метод read(). Пример кода там есть.
    Ответ написан
    Комментировать
  • Как произвольно трансформировать изображение в Python?

    Vindicar
    @Vindicar
    RTFM!
    Скажи спасибо, что я делал такую лабораторную работу X)
    Код
    # -*- coding: utf-8 -*-
    import sys
    import numpy  # pip install numpy
    import cv2  # pip install opencv-python
    
    def loadImg(fname : str) -> numpy.ndarray:  # грузит файл
        data = numpy.fromfile(fname, dtype=numpy.uint8)
        img = cv2.imdecode(data, cv2.IMREAD_COLOR)
        if img is None:
            raise IOError("Not an image file")
        return img
    
    class Clicker:  # класс для выбора точек на экране
        def __init__(self, name: str, image: numpy.ndarray):
            self.wnd = name
            self.image = image
            self.clicks = []
            self.markersize = 5
            self.markercolor = (255,0,255)
            cv2.namedWindow(self.wnd, cv2.WINDOW_AUTOSIZE)
            cv2.setMouseCallback(self.wnd, self._click)
        
        def draw(self):  # рисует точки на изображении и выводит их на экран
            copy = self.image.copy()
            color = self.markercolor
            radius = self.markersize
            for x,y in self.clicks:
                cv2.circle(copy, (x,y), radius, color, 1)
                cv2.line(copy, (x-radius,y), (x+radius,y), color, 1)
                cv2.line(copy, (x,y-radius), (x,y+radius), color, 1)
            cv2.imshow(self.wnd, copy)
        
        def _click(self, event, x, y, flags, param):
            if event == cv2.EVENT_LBUTTONDOWN:  # левый клик - поставить точку
                self.clicks.append((x,y))
            elif event == cv2.EVENT_RBUTTONDOWN:  # правый клик - сбросить последнюю точку
                if self.clicks:
                    del self.clicks[-1]
            else:
                return
            self.draw()
        
        def close(self):
            cv2.destroyWindow(self.wnd)
        
        def __enter__(self):
            self.draw()
            return self
        
        def __exit__(self, exctype, excvalue, traceback):
            self.close()
    
    try:
        image = loadImg('times-square.jpg')  # изображение, внутрь которого вписываем другое
        poster = loadImg('lena.png')  # изображение, которое вписываем в первое
    except IOError:
        print('Ошибка загрузки файла.')
        sys.exit(1)
    # эта часть только для ручного ввода координат
    # если они уже есть, то это не нужно.
    with Clicker('Select area', image) as clicker:
        # четыре точки ставятся строго по часовой, начиная слева-сверху 
        while len(clicker.clicks) < 4:  # пока не получили четыре точки - угла
            if cv2.waitKey(100) == 27:
                print('Отменено')
                sys.exit(0)
        pts = numpy.array(clicker.clicks, dtype=numpy.float32)  # координаты углов тут
    # вписываем изображение
    height, width = poster.shape[:2]
    srcpoints = numpy.array([  # углы вставляемого изображения в том же порядке по часовой
        (0,0),
        (width-1, 0),
        (width-1, height-1),
        (0, height-1),
    ], dtype=numpy.float32)
    # матрица преобразования сопоставляет четыре точки второго изображения с точками первого
    # по сути, она позволяет перейти от второго изображения к первому
    matrix = cv2.getPerspectiveTransform(srcpoints, pts)  # порядок аргументов важен, иначе переход будет наоборот
    # применяем матрицу ко второму изображению. Но теперь надо убрать чёрные поля.
    warped = cv2.warpPerspective(poster, matrix, (image.shape[1], image.shape[0]))
    # делаем маску для переноса пикселей с warped на image
    # мы хотим перенести только пиксели, на которые пришлись пиксели второго изображения
    mask = numpy.zeros(image.shape, dtype=numpy.uint8)  # рисовать можно только на обычном изображении
    # закрашиваем пиксели внутри выбранного ранее четырёхугольника
    cv2.fillPoly(mask, pts.reshape(1, -1, 2).astype(numpy.int32), (1,1,1))
    mask.dtype = bool  # а для переноса нам нужна логическая маска
    # маска готова, переносим. numpy рулит, правда ведь?
    image[mask] = warped[mask]
    # показываем результат
    cv2.imshow('Result', image)
    cv2.waitKey()


    Если коротко: находишь точки, которым надо сопоставить углы "вставыша". Перечисляешь их в том же порядке, что и эти углы. Находишь матрицу перспективного преобразования. Применяешь матрицу к вставышу, получаешь чёрное изображение, на котором вставыш расположен в нужном месте. Переносишь пиксели с этого изображения на картинку с экраном.
    Ответ написан
    3 комментария
  • Почему возникает ошибка при работе с Python и OpenCV?

    Vindicar
    @Vindicar
    RTFM!
    1. Не принимать предупреждения за ошибки.
    2. Работать на машине, где видяха поддерживает одну из указанных библиотек, и поставить на неё эту библиотеку.
    Ответ написан
    Комментировать
  • Как создать триггер cv2 Python?

    Vindicar
    @Vindicar
    RTFM!
    1. Выясни, что возвращает haar_cascade.detectMultiScale(), если в кадре нет лица - None или пустой массив?
    2. Храни флаг "на прошлом кадре было лицо", обновляй его в конце тела цикла while True
    3. После детекта лица проверяй, если на прошлом кадре лица не было, а на новом есть - делай отправку уведомления.

    А вот как подружить ТГ бота с этим циклом - уже второй вопрос. Я бы запустил приведённый код в потоке и использовал queue.Queue для связи потока с анализом видео и потока с ботом. Т.е. когда обнаружил лицо, кидаешь кадр в очередь. А в основном потоке периодически проверяешь очередь на предмет наличия новых кадров.
    Альтернативно, если бот асинхронный, можно переделать цикл на корутину, добавив небольшую задержку через await asyncio.sleep() и заменив requests на aiohttp. Не очень изящное решение, но может и сойдёт.
    Ответ написан
    Комментировать
  • Что делать если при открытии png файла с прозрачным фоном через OpenCV появляются гличи?

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

    Vindicar
    @Vindicar
    RTFM!
    if time <= time_15:

    По логике должно быть if time > time_15:
    Ответ написан
    Комментировать
  • Почему не работает код?

    Vindicar
    @Vindicar
    RTFM!
    В твоём коде показано, как определить класс объекта. Смотри, как формируется prediction_text.
    А дальше просто. Храни в глобальной переменной время, когда был сохранён последний снимок объекта с желаемым классом.
    Если у тебя на текущем кадре есть объект с желаемым классом, проверь текущее время. Если прошло 30 секунд с последнего сохранения - сохрани новый снимок, и обнови время последнего сохранения на текущее.
    Ответ написан
    Комментировать
  • Как настроить нейронную сеть на python?

    Vindicar
    @Vindicar
    RTFM!
    Почему ты делаешь np.mean(result)?
    Если я верно помню, softmax-слой даст наибольший отклик в элементе, соответствующем выбранному классу. Т.е. нужно сделать argmax по этому слою, чтобы узнать ответ сети.

    P.S.: обалдеть, я и не знал что в питоне есть оператор @.
    Ответ написан