Как наложить несколько изображений на базовое изображение по определенным координатам?

[Это теперь решено. Я разместил свой обновленный код внизу моего вопроса для справки].

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

Цель кода — найти самые яркие точки на изображении (в данном случае изображение звездного поля), использовать порог, эрозию, процесс расширения для выделения самых ярких/самых больших звезд. Затем используется функция findContours, и вокруг каждого контура рисуется прямоугольник. Центральные координаты каждого прямоугольника рассматриваются как пиксельные координаты этой звезды. Затем я пытаюсь использовать эти координаты для наложения меньшего изображения на базовое изображение в каждой позиции, где обнаружена яркая звезда. По какой-то причине это не работает, и я был бы очень признателен за некоторую помощь, спасибо.

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

Это код, который я использовал для наложения одного изображения на базовое изображение, и он работает правильно:

import cv2
import numpy as np

fg_img = cv2.imread("image_small.png")
bg_img = cv2.imread("image_big.png")

cv2.imshow('small',fg_img)
cv2.imshow('big',bg_img)

h1, w1 = fg_img.shape[:2]
print (h1, w1)

pip_h = 10
pip_w = 10

bg_img[pip_h:pip_h+h1,pip_w:pip_w+w1] = fg_img

cv2.imshow('overlaid', bg_img)
cv2.waitKey(0)

И это код, который я пытаюсь заставить работать:

import imutils
import cv2

fg_img = cv2.imread("image_small.png")
bg_img = cv2.imread("image_big.png")

graybg = cv2.cvtColor(bg_img, cv2.COLOR_BGR2GRAY)

h1, w1 = fg_img.shape[:2]
##print(h1, w1)

thresh = cv2.threshold(graybg, 225, 255, cv2.THRESH_BINARY)[1]
mask = thresh.copy()
mask = cv2.erode(mask, None, iterations=1)
mask2 = mask.copy()
mask2 = cv2.dilate(mask2, None, iterations = 2)
h2, w2 = mask2.shape[:2]
print(h2, w2)

cnts = cv2.findContours(mask2.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
output = mask2.copy()

for c in cnts:
        x,y,w,h = cv2.boundingRect(c)
        print(x,y)
        pip_h = y 
        pip_w = x 
        mask2[pip_h:pip_h+h1,pip_w:pip_w+w1] = fg_img
        cv2.imshow("Contours", output)

cv2.waitKey(0)

Сообщение об ошибке, которое я получаю при запуске второй воспроизведенной выше программы, гласит: «ValueError: не удалось передать входной массив из формы (82,70,3) в форму (11,70)». Для справки, разрешение меньшего изображения было 82x70, разрешение большого изображения на самом деле было 1920x1080...

Еще раз спасибо за чтение, я надеюсь, что ошибка легко разрешима. Спасибо

ИСПРАВЛЕННЫЙ КОД:

import imutils
import cv2

fg_img = cv2.imread("image_small.png")
bg_img = cv2.imread("image_big.png")

graybg = cv2.cvtColor(bg_img, cv2.COLOR_BGR2GRAY)

h1, w1 = fg_img.shape[:2]
print(h1, w1)

thresh = cv2.threshold(graybg, 225, 255, cv2.THRESH_BINARY)[1]
mask = thresh.copy()
mask = cv2.erode(mask, None, iterations=1)
mask2 = mask.copy()
mask2 = cv2.dilate(mask2, None, iterations = 2)
h2, w2 = mask2.shape[:2]
print(h2, w2)

cnts = cv2.findContours(mask2.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

for c in cnts:
        x,y,w,h = cv2.boundingRect(c)
        pip_h = y 
        pip_w = x
        print(pip_h, pip_w)

        if h2 - pip_h > h1 + 1 and w2 - pip_w > w1 + 1:
                bg_img[pip_h:pip_h+h1,pip_w:pip_w+w1] = fg_img

        cv2.imshow("Contours", bg_img)

cv2.waitKey(0)

person raspberrystars    schedule 15.07.2019    source источник


Ответы (1)


Проблема с вашим кодом в том, что внутри цикла for:

x,y,w,h = cv2.boundingRect(c)

если pip_h=y близко к высоте исходного изображения h2, то операция нарезки

mask2[pip_h:pip_h+h1]

даст вам только h2 - pip_h строк. В крайнем случае подумайте, что происходит, когда pip_h=h2.

Короче говоря, операция клонирования

mask2[pip_h:pip_h+h1,pip_w:pip_w+w1] = fg_img

терпит неудачу, когда h2 - pip_h < h1 или w2 - pip_w < w1 по вышеуказанной причине.

person Quang Hoang    schedule 15.07.2019
comment
Большое спасибо за ваши комментарии. Я реализовал то, что вы предложили, а также нашел еще одну небольшую ошибку. Я отправляю свой рабочий код в качестве обновления моего вопроса для справки другим пользователям: - person raspberrystars; 16.07.2019