如何将多个图像叠加到特定坐标上的基础图像上?

How to overlay multiple images onto a base image on certain coordinates?

[现在已经解决了。我已经在我的问题底部发布了我更新的代码以供参考。

我正在尝试在 Python 中创建一个程序,以自动将小图像叠加到大图像上以获得坐标列表。我可以让它为一个小图像到一个更大图像的单个示例工作,但当我试图多次重复这个时就不行了。如果有人能指出我的代码中的错误,我将不胜感激(我希望可能是非常基本的,我对 Python 没有信心)。

代码的目的是找到图像(在本例中为星空图像)中的最亮点,使用阈值、腐蚀、膨胀过程来隔离 brightest/largest 星。然后使用 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: could not broadcast input array from shape (82,70,3) into shape (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)

您的代码的问题在于,在 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 < h1w2 - pip_w < w1 时失败。