简体   繁体   English

Python,OpenCV 查找和覆盖/替换图像的部分

[英]Python, OpenCV to find and overlay/replace portions of an image

Need to find and replace some portions in an image, with other images.需要找到并用其他图像替换图像中的某些部分。

The original image is shown below.原始图像如下所示。 I want to find and replace:我想查找和替换:

blue squares to blue triangles
orange squares to orange octagons

在此处输入图片说明

the image files are in place as:图像文件如下:

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

在此处输入图片说明 在此处输入图片说明 在此处输入图片说明 在此处输入图片说明

using cv2, I can find the locations of the target images.使用 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

the output is:输出是:

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

What's the best way to proceed further?进一步进行的最佳方法是什么? Is CV2 the best tool for this case? CV2 是这种情况下的最佳工具吗? Thank you.谢谢你。

Yes, it is possible to continue from that point.是的,可以从这一点继续。 You will get the locations of each of then, first array is y axis and the second array the x axis.您将获得每个的位置,第一个数组是y轴,第二个数组是x轴。 This position is the top left corner of the object.该位置是对象的左上角。

What could be aproblem here is that the templates have different sizes.. so it may overlap with other parts of the image which is not happening in the original image and I do not know if this is a problem.这里可能存在的问题是模板具有不同的大小......所以它可能与原始图像中没有发生的图像的其他部分重叠,我不知道这是否是一个问题。 So you may have to make sure all of them are equally big or that they have enough space if this is a problem.因此,如果这是一个问题,您可能必须确保所有这些都同样大或它们有足够的空间。 This could be solve, scaling the images to be of the same size for example.这可以解决,例如将图像缩放为相同大小。

Anyways, you may achieve the replacement like this:无论如何,您可以像这样实现替换:

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()

And here is the result of blue squares to blue triangles:这是蓝色方块到蓝色三角形的结果:

在此处输入图片说明

And for both changes as in your example:对于您的示例中的两个更改:

在此处输入图片说明

If the sizes of the two templates are equal (ie the image you look for and the one it will be replace with), you can reduce one step and change the for loop to:如果两个模板的大小相等(即您要查找的图像和将要替换的图像),您可以减少一步并将 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更新

To move the shape you are copying you can shift the whole ROI, anyways you already have deleted the old one so it will be ok.要移动您正在复制的形状,您可以移动整个 ROI,无论如何您已经删除了旧的,这样就可以了。 Just don't forget to check the limitsof the image.只是不要忘记检查图像的限制。 For that you can do the following:为此,您可以执行以下操作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM