Python, OpenCV для поиска и наложения / замены частей изображения - PullRequest
0 голосов
/ 05 ноября 2018

Необходимо найти и заменить некоторые части изображения другими изображениями.

Исходное изображение показано ниже. Я хочу найти и заменить:

blue squares to blue triangles
orange squares to orange octagons

enter image description here

файлы изображений на месте как:

original.jpg, blue square.jpg, orange square.jpg, blue triangle.jpg, orange octagon.jpg

enter image description here enter image description here enter image description here enter image description here

используя cv2, я могу найти расположение целевых изображений.

import cv2
import numpy as np

img_original = cv2.imread("C:\\original.jpg")

img_to_replace_0 = cv2.imread("C:\\blue square.jpg")
img_to_replace_1 = cv2.imread("C:\\orange square.jpg")

img_overlay_0 = cv2.imread("C:\\blue triangle.jpg")
img_overlay_1 = cv2.imread("C:\\orange octagon.jpg")

res_0 = cv2.matchTemplate(img_original, img_to_replace_0, cv2.TM_CCOEFF_NORMED)
res_1 = cv2.matchTemplate(img_original, img_to_replace_1, cv2.TM_CCOEFF_NORMED)

threshold = 0.80
loc_0 = np.where (res_0 >= threshold)
loc_1 = np.where (res_1 >= threshold)

bl_0 = list(loc_0)
bl_1 = list(loc_1)

print bl_0
print bl_1

вывод:

[array([106, 294, 477]), array([17, 18, 21])]
[array([ 22, 210, 393]), array([16, 17, 20])]

Какой лучший способ продолжить? Является ли CV2 лучшим инструментом для этого случая? Спасибо.

1 Ответ

0 голосов
/ 05 ноября 2018

Да, с этого момента можно продолжить. Вы получите местоположения каждого из них, первый массив - ось y, а второй массив - ось x. Эта позиция является верхним левым углом объекта.

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

В любом случае, вы можете добиться замены следующим образом:

import cv2
import numpy as np

# load the data
img = cv2.imread('scene.jpg')
blueTri = cv2.imread('blueTri.jpg')
blueSq = cv2.imread('blueSq.jpg')
bgColor = (255,255,255)

# find the matching rectangles
res = cv2.matchTemplate(img, blueSq, cv2.TM_CCOEFF_NORMED)
threshold = 0.98 # I used a higher threshold, because it was giving several "good" locations that are next to each other
loc = np.where (res >= threshold)

# process the positions
for i in range(len(loc[0])):
  # it is given as (y,x)
  pos = (loc[0][i], loc[1][i])
  # delete the blue squares
  img[pos[0]:pos[0]+blueSq.shape[0] , pos[1]:pos[1]+blueSq.shape[1] ] = bgColor
  # put the new blue triangle
  img[pos[0]:pos[0]+blueTri.shape[0] , pos[1]:pos[1]+blueTri.shape[1] ] = blueTri


cv2.imshow("Frame", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

А вот результат от синих квадратов до синих треугольников:

enter image description here

И для обоих изменений, как в вашем примере:

enter image description here

Если размеры двух шаблонов равны (т. Е. Изображение, которое вы ищете, и изображение, на которое оно будет заменено), вы можете уменьшить один шаг и изменить цикл for на:

# process the positions
for i in range(len(loc[0])):
  # it is given as (y,x)
  pos = (loc[0][i], loc[1][i])
  # put the new blue triangle
  img[pos[0]:pos[0]+blueTri.shape[0] , pos[1]:pos[1]+blueTri.shape[1] ] = blueTri

UPDATE

Чтобы переместить копируемую фигуру, вы можете сдвинуть всю область интереса, в любом случае вы уже удалили старую, так что все будет в порядке. Только не забудьте проверить пределы изображения. Для этого вы можете сделать следующее:

for i in range(len(loc[0])):
  posToDelete = (loc[0][i], loc[1][i])
  posToAdd = (loc[0][i] -10, loc[1][i]+15) # 10 pixels up and 15 to the right
  posToAdd = (max(0, min(posToAdd[0],img.shape[0]-1 -blueTri.shape[0] )) , max(0, min(posToAdd[1],img.shape[1]-1-blueTri.shape[1]))) # sanity check to make sure it is inside the borders
  img[posToDelete[0]:posToDelete[0]+blueSq.shape[0] , posToDelete[1]:posToDelete[1]+blueSq.shape[1] ] = bgColor
  img[posToAdd[0]:posToAdd[0]+blueTri.shape[0] , posToAdd[1]:posToAdd[1]+blueTri.shape[1] ] = blueTri
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...