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

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
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

Связь:
telegram: inilim
email: [email protected]
 

Вложения

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

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43
Закрыто.
 
Последнее редактирование:

amyboose

Client
Регистрация
21.04.2016
Сообщения
2 312
Благодарностей
1 191
Баллы
113
Помню такое делал на C#, с помощью математики можно схитрить и искать быстрее, чем просто попиксельно
 

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43

7make

Client
Регистрация
25.06.2011
Сообщения
1 547
Благодарностей
1 311
Баллы
113

Обращаем Ваше внимание на то, что данный пользователь заблокирован.
Не рекомендуем проводить с 7make какие-либо сделки.

задача класса Template matching
реализация на питоне - opencv
на шарпе либа - accord framework
завернуть все в rest api где мультипартом пост запросом кинул две пикчи

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

чтобы искалось норм нужно с грейскейлом работать, rgb > gray :-)
 

amyboose

Client
Регистрация
21.04.2016
Сообщения
2 312
Благодарностей
1 191
Баллы
113
задача класса Template matching
реализация на питоне - opencv
на шарпе либа - accord framework
завернуть все в rest api где мультипартом пост запросом кинул две пикчи

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

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

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43

7make

Client
Регистрация
25.06.2011
Сообщения
1 547
Благодарностей
1 311
Баллы
113

Обращаем Ваше внимание на то, что данный пользователь заблокирован.
Не рекомендуем проводить с 7make какие-либо сделки.

если шаблонов поиска несколько, тогда канешь уже другие подходы юзать нужно.
нейронки тут избыточные будут. есть куда проще варианты, типа (Local Binary Patterns) LBP+SVM / Каскады Хаара
главное задачу внятно описать.
тогда уже и имплементацию легче подобрать и подумать над оптимизацией

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


81825
 
  • Спасибо
Реакции: Astraport

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43
Сколько классов обьектов для поиска?
Может от 1 до десятков.

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

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

7make

Client
Регистрация
25.06.2011
Сообщения
1 547
Благодарностей
1 311
Баллы
113

Обращаем Ваше внимание на то, что данный пользователь заблокирован.
Не рекомендуем проводить с 7make какие-либо сделки.

Это браузерная или десктоп игра?
 

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43
Это браузерная или десктоп игра?
В основном десктопные. Обращаю внимание, скриншоты делаю не я. Они берутся из интернета.

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

Это можно назвать как определение игры по скринам.
 

bizzon

Client
Регистрация
08.09.2015
Сообщения
1 103
Благодарностей
132
Баллы
63
Интересно, можно таким способом на яндекс карте мониторить прохождение троллейбусом точки маршрута?

Скриншот 2021-08-28 10.22.09.png
 

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43

one

Client
Регистрация
22.09.2015
Сообщения
6 833
Благодарностей
1 275
Баллы
113

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43
Какими например?
Появление второй пиктограммы транспорта, заход одной пиктограммы на другую и тому подобное.
Если нужно следить за одним транспортом то на него нужно кликнуть, а если за всеми то бывает такая каша как на картинке.

81844
 
  • Спасибо
Реакции: one

one

Client
Регистрация
22.09.2015
Сообщения
6 833
Благодарностей
1 275
Баллы
113
Появление второй пиктограммы транспорта, заход одной пиктограммы на другую и тому подобное.
Если нужно следить за одним транспортом то на него нужно кликнуть, а если за всеми то бывает такая каша как на картинке.

Посмотреть вложение 81844
А ну да, каша из пиктограмм без масла. )))
 

bizzon

Client
Регистрация
08.09.2015
Сообщения
1 103
Благодарностей
132
Баллы
63
Взялся бы кто в рамках конкурсной работы, точно бы 1-е место взял.
 

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43

inilim

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

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43
Закрыто
 
Последнее редактирование:

Viking01

Client
Регистрация
19.08.2017
Сообщения
228
Благодарностей
151
Баллы
43
Регистрация
03.12.2020
Сообщения
146
Благодарностей
103
Баллы
43
а смысл, какое ее массовое практическое применение?
Вариантов применения масса.
Вот только заготовок рабочих для анскильных юзеров практически нет. Там каждый подгон под задачу, по сути, отдельный полноценный проект, с исследованием и аналитикой.
 

Viking01

Client
Регистрация
19.08.2017
Сообщения
228
Благодарностей
151
Баллы
43

amyboose

Client
Регистрация
21.04.2016
Сообщения
2 312
Благодарностей
1 191
Баллы
113

Viking01

Client
Регистрация
19.08.2017
Сообщения
228
Благодарностей
151
Баллы
43

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 719
Баллы
113
канвас - это кеш орисованного пикселя, причем тут поиск мини картинки в картинке?
очень интересно было бы увидеть ваше решение работы с канвасом, где нет обычных элементов, а есть только кеш орисованного пикселя . Например надо найти определенную кнопку в браузерной игре.
ну и конечно без поиска картинки в картинке :bk:
 
  • Спасибо
Реакции: Viking01

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43
очень интересно было бы увидеть ваше решение работы с канвасом, где нет обычных элементов, а есть только кеш орисованного пикселя . Например надо найти определенную кнопку в браузерной игре.
ну и конечно без поиска картинки в картинке :bk:
Я скину чуть позже в этот топик решение что заказал.
 

Viking01

Client
Регистрация
19.08.2017
Сообщения
228
Благодарностей
151
Баллы
43
Например надо найти определенную кнопку в браузерной игре.
ну вот это уже конкретные примеры)
что я и спрашивал)

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

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

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43
Сам код. Требует сам 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);
В данном решение есть жирный минус, скрипт не проверяет схож ли найденный фрагмент с искомым.
Пробовал методы сравнения пикселей, Среднее хеширование, Перцептивное хеширование, Разностное хеширование, Вейвлет-хеширование. и многие другие. В этом плане решения я не нашел.
 

Вложения

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

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