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

时间:2019-07-15 16:47:12

标签: python opencv haar-classifier cascade-classifier

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

我正在尝试在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)

1 个答案:

答案 0 :(得分: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 < h1w2 - pip_w < w1失败。