[Задача] Поиск картинки-фрагмента в картинке. (не актуально)

  • Автор темы Автор темы inilim
  • Дата начала Дата начала

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Реакции
171
Баллы
43
ТЗ оформлять я не умею, поэтому заранее приношу извинения.
Буду корректировать ТЗ по мере диалога с потенциальными исполнителями.

Описание:
Язык программирование не важно.

Входные данные:
  1. (STRING) Путь к файлу. Полноценная картинка. Примерные размеры 1280х720 (Возможно больше или меньше), форматы картинок может быть png jpeg.
  2. (STRING) Фрагмент, она же картинка. Размеры не превышают 150x150 пикселей, формат фрагмента base64.
Выходные данные:
  1. (Boolean/Array) True есть фрагмент в картинке. False нет фрагмента в картинке. Или координаты найденного фрагмента.
Нюансы:
  1. Полноценная картинка является скриншотом разных игр, размеры условно фиксированы 1280х720.
  2. Поиск по пикселям предположительно отпадает, ибо скрины одной игры почти всегда отличаются пикселями, даже если производить цветокоррекцию фрагмента и полноценной картинки. Могу конечно ошибаться.
  3. К примеру фрагмент размера 40х40 пикселей, полноценная картинка размера 1280х720, фрагмент есть на полноценной картинке, но она другого размера ??х??, есть ли алгоритмы вычислять такое хз. Решение предполагаю за машинным зрением типа OpenCV и др.
Хотелки:
  1. В идеале, решение хотелось бы сделать на PHP, но я думаю это фантастика.
  2. Функция должна управляться PHP скриптом, другими словами PHP скрипт будет решать какие изображение и фрагменты будут попадать во входные параметры, так же скрипт будет его запускать при помощи функции exec (https://www.php.net/manual/ru/function.exec). Если есть решения получше, буду рад выслушать.
  3. Скорость. Есть свое решение на PHP, но она очень прожорливая и долгая. 1000 итераций поиска обходится по времени 14 часов. Необходимо производить поиск по млн. картинок.
Бюджет: 10.000 rub
 

Вложения

  • img00009.jpg
    img00009.jpg
    71,3 KB · Просмотры: 328
  • search_fragments.zip
    search_fragments.zip
    45,1 KB · Просмотры: 156
Последнее редактирование:
Закрыто.
 
Последнее редактирование:
Помню такое делал на C#, с помощью математики можно схитрить и искать быстрее, чем просто попиксельно
 
задача класса Template matching
реализация на питоне - opencv
на шарпе либа - accord framework
завернуть все в rest api где мультипартом пост запросом кинул две пикчи

на пыхе imagick могет тоже

чтобы искалось норм нужно с грейскейлом работать, rgb > gray :-)
 
задача класса Template matching
реализация на питоне - opencv
на шарпе либа - accord framework
завернуть все в rest api где мультипартом пост запросом кинул две пикчи

на пыхе imagick могет тоже

чтобы искалось норм нужно с грейскейлом работать, rgb > gray :-)
Я быстренько пробежался по stackoverflow, там из решений был AForge вроде бы и по скорости описывали, что он пару секунд иногда ищет. Насчет нейросети не знаю
 
  • Спасибо
Реакции: inilim
если шаблонов поиска несколько, тогда канешь уже другие подходы юзать нужно.
нейронки тут избыточные будут. есть куда проще варианты, типа (Local Binary Patterns) LBP+SVM / Каскады Хаара
главное задачу внятно описать.
тогда уже и имплементацию легче подобрать и подумать над оптимизацией

1. Сколько классов обьектов для поиска? Мультиклассовая или мультилейбловая?
Такое на входе?
81824


81825
 
  • Спасибо
Реакции: Astraport
Сколько классов обьектов для поиска?
Может от 1 до десятков.

Такое на входе?
Не совсем, на входе маленькие скриншоты, они же фрагменты из других полноценных скриншотов.
Эти фрагменты и будут критерии поиска в других скриншотах.

Другими словами, сделал скриншот, нашел фрагмент на скриншоте, вырезал фрагмент из скриншота, и стал в цикле проверять есть ли данный фрагмент в других скриншотах.
Мультиклассовая или мультилейбловая?
Затрудняюсь ответить, но думаю мультиклассовая.
 
Это браузерная или десктоп игра?
В основном десктопные. Обращаю внимание, скриншоты делаю не я. Они берутся из интернета.

Игра не одна их будут сотни, соответственно фрагментов будет множество.

Это можно назвать как определение игры по скринам.
 
Интересно, можно таким способом на яндекс карте мониторить прохождение троллейбусом точки маршрута?

Скриншот 2021-08-28 10.22.09.png
 
Какими например?
Появление второй пиктограммы транспорта, заход одной пиктограммы на другую и тому подобное.
Если нужно следить за одним транспортом то на него нужно кликнуть, а если за всеми то бывает такая каша как на картинке.

81844
 
  • Спасибо
Реакции: one
Появление второй пиктограммы транспорта, заход одной пиктограммы на другую и тому подобное.
Если нужно следить за одним транспортом то на него нужно кликнуть, а если за всеми то бывает такая каша как на картинке.

Посмотреть вложение 81844
А ну да, каша из пиктограмм без масла. )))
 
Взялся бы кто в рамках конкурсной работы, точно бы 1-е место взял.
 
Поковырял функцию, она безобразна, дать ей любой фрагмент для поиска она все найдет, и при том что степень сходства не логичен. Там где фрагмента нет вес выше, где фрагмент есть вес ниже, и бывает наоборот.
 
Закрыто
 
Последнее редактирование:
а смысл, какое ее массовое практическое применение?
Вариантов применения масса.
Вот только заготовок рабочих для анскильных юзеров практически нет. Там каждый подгон под задачу, по сути, отдельный полноценный проект, с исследованием и аналитикой.
 
канвас - это кеш орисованного пикселя, причем тут поиск мини картинки в картинке?
очень интересно было бы увидеть ваше решение работы с канвасом, где нет обычных элементов, а есть только кеш орисованного пикселя . Например надо найти определенную кнопку в браузерной игре.
ну и конечно без поиска картинки в картинке :bk:
 
  • Спасибо
Реакции: Viking01
очень интересно было бы увидеть ваше решение работы с канвасом, где нет обычных элементов, а есть только кеш орисованного пикселя . Например надо найти определенную кнопку в браузерной игре.
ну и конечно без поиска картинки в картинке :bk:
Я скину чуть позже в этот топик решение что заказал.
 
Например надо найти определенную кнопку в браузерной игре.
ну вот это уже конкретные примеры)
что я и спрашивал)

ну и конечно без поиска картинки в картинке
да, у меня есть такое решение, основано на ML.Net *тут смайлик, показывающий язык :-)
изначально было для решения капчей)

Я скину чуть позже в этот топик решение что заказал.
да глобально интересно просто, зачем/для чего)
если не секрет конечно)
тем более вариантов реализации накидали массу)
 
Сам код. Требует сам python и библиотеку openCV

Python:
Развернуть Свернуть Копировать
import json
import argparse
import numpy as np
import base64
import cv2

parser = argparse.ArgumentParser(description='Finding templates on an image')
parser.add_argument('image', type=str, help='path to image file .jpg or .png')
parser.add_argument('temp', type=str, help='base64 fragment file')
args = parser.parse_args()


def edge(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    edged = cv2.Canny(gray, 30, 200)
    contours, hierarchy = cv2.findContours(edged,
                                           cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    return edged


def resize(img):
    scale_percent = 400  # percent of original size
    width = int(img.shape[1] * scale_percent / 100)
    height = int(img.shape[0] * scale_percent / 100)
    dim = (width, height)
    resized = cv2.resize(img, dim, interpolation=cv2.INTER_AREA)
    return resized


def increase_brightness(img, value=100):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(hsv)

    lim = 255 - value
    v[v > lim] = 255
    v[v <= lim] += value

    final_hsv = cv2.merge((h, s, v))
    img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
    return img


def check_similarity(img, temp):
    img = edge(img)
    temp = edge(temp)

    h1, w1 = img.shape
    h2, w2 = temp.shape

    q11 = img[0:int(h1 * 0.5), 0:int(w1 * 0.5)]
    q12 = img[0:int(h1 * 0.5), int(w1 * 0.5):w1]
    q13 = img[int(h1 * 0.5):h1, 0:int(w1 * 0.5)]
    q14 = img[int(h1 * 0.5):h1, int(w1 * 0.5):w1]

    q21 = temp[0:int(h2 * 0.5), 0:int(w2 * 0.5)]
    q22 = temp[0:int(h2 * 0.5), int(w2 * 0.5):w2]
    q23 = temp[int(h2 * 0.5):h2, 0:int(w2 * 0.5)]
    q24 = temp[int(h2 * 0.5):h2, int(w2 * 0.5):w2]

    coeff = 3
    if h1 * w1 < 800:
        coeff = 5

    wq1d = abs(np.sum(q11 == 255) * coeff - np.sum(q21 == 255) * coeff)
    wq2d = abs(np.sum(q12 == 255) * coeff - np.sum(q22 == 255) * coeff)
    wq3d = abs(np.sum(q13 == 255) * coeff - np.sum(q23 == 255) * coeff)
    wq4d = abs(np.sum(q14 == 255) * coeff - np.sum(q24 == 255) * coeff)

    return max(wq4d, wq3d, wq2d, wq1d)


def check_colors(image1, image2):
    hist1 = cv2.calcHist(image1, [0, 1, 2], None, [8, 8, 8],
                         [0, 256, 0, 256, 0, 256])

    hist2 = cv2.calcHist(image2, [0, 1, 2], None, [8, 8, 8],
                         [0, 256, 0, 256, 0, 256])
    hist1 = cv2.normalize(hist1, hist1).flatten()
    hist2 = cv2.normalize(hist2, hist2).flatten()
    d = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
    return d


# <-------------------------Read Images---------------------------->
with open(args.temp, "r") as f:
    text = f.read()
im_bytes = base64.b64decode(text)
im_arr = np.frombuffer(im_bytes, dtype=np.uint8)  # im_arr is one-dim Numpy array
template = cv2.imdecode(im_arr, flags=cv2.IMREAD_COLOR)
image = cv2.imread(args.image)
# <-------------------------Read Images---------------------------->

# <-------------------------Thresholds----------------------------->
contour_similarity_threshold = 35  # Разница картинок по площади контуров по квадрантам.
# Чем выше тем больше различие изображений. Исходя из тестов у похожих картинок он не превышает 150

color_similarity_threshold = 0.1  # Порог расхождения цветовой гистограммы по методу HISTCMP_CORREL. 1 для абсолютно
# идентичных изображений и < 0.1 для абсолютно разных.
# <-------------------------Thresholds----------------------------->


# <-------------------------Processing----------------------------->
image = increase_brightness(image)
template = increase_brightness(template)
heat_map = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(heat_map)
h, w, _ = template.shape
y, x = np.unravel_index(np.argmax(heat_map), heat_map.shape)
new_image = image[y + 4:y + h - 4, x + 4:x + w - 4]
new_template = template[4:h - 4, 4:w - 4]
# <-------------------------Processing----------------------------->
# <-------------------------conf----------------------------->
#y = y - 1
#x = x - 12
#if y < 0:
#    y = 0
#if x < 0:
#    x = 0
# <-------------------------conf----------------------------->
# <-------------------------Results----------------------------->
contour_similarity_index = check_similarity(new_image, new_template)
color_similarity_index = check_colors(new_image, new_template)


#contourMatch = True
#colorMatch = True
#if contour_similarity_index > contour_similarity_threshold:
#    contourMatch = False

#if color_similarity_index < color_similarity_threshold:
#    colorMatch = False

# <-------------------------Results----------------------------->

# <-------------------------Output----------------------------->
output = {"xpos": int(x),
          "ypos": int(y),
          "height": int(h),
          "width": int(w),
          #"cntM": contourMatch,
          #"clrM": colorMatch,
          "contour_similarity_index": int(contour_similarity_index),
          "color_similarity_index": float(color_similarity_index)
          }
json_dump = json.dumps(output)
print(json_dump)

Вот так я его использую из языка PHP. Уверен на C# есть свое решение. Его даже можно прикрутить к ZP с легкостью.
Кто шарит хоть чуть в программирование может его настроить под себя. Сложного там нет.
PHP:
Развернуть Свернуть Копировать
exec('python final.py "Путь к большой картинке" "Путь к маленькой картинке в формате base64" 2>&1', $result_exec);

В данном решение есть жирный минус, скрипт не проверяет схож ли найденный фрагмент с искомым.
Пробовал методы сравнения пикселей, Среднее хеширование, Перцептивное хеширование, Разностное хеширование, Вейвлет-хеширование. и многие другие. В этом плане решения я не нашел.
 

Вложения

Последнее редактирование:

Кто просматривает тему: (Всего: 0, Пользователи: 0, Гости: 0)