python - 将二维数组插入另一个二维数组,同时考虑值
问题描述
我试图在某些坐标上将一张图片(透明 .png)插入另一张图片。虽然如何使用 x,y 坐标在另一个图像上添加图像的解决方案?
frame[y: y+insert_size[1], x: x+insert_size[0]] = image
(其中 insert_size - 插入图片的宽度和高度)有效,我也不想要最终图像上的黑色像素(这就是 opencv 表示透明像素的方式)。
我编写了一个逐像素迭代的函数,虽然它工作 - 它非常慢(它每秒完成大约 2 个图像插入),代码:
def insert_image(frame, image, insert_coordinates, masked_value):
img_height = len(image)
img_width = len(image[0])
mask = np.ndarray((3,), np.uint8, buffer=np.array(masked_value))
y_diff = 0 #current vertical position in insert picture
for y, line in enumerate(frame):
if y_diff == img_height-1:
continue #interested until last row
if y < insert_coordinates[1] or y > insert_coordinates[1]+img_height:
continue #interested only in rows that will be changed
else:
x_diff = 0 #current horizontal position in insert picture
for x, col in enumerate(line):
if x_diff == img_width-1:
continue #interested until last column
if x < insert_coordinates[0] or x > insert_coordinates[0]+img_width:
continue #interested only in columns that will be changed
else:
if (image[y_diff][x_diff] != mask).all():
frame[y][x] = image[y_diff][x_diff] #setting pixel value if its not of masked value
x_diff += 1
y_diff += 1
return frame
也许有更聪明的方法可以做到这一点?opencv 版本 4.5.0 numpy 版本 1.20.0rc1
更新:“插入”是指将图像中的像素值分配给帧的某个像素。我为可重现的示例添加了数据和代码(也修改了函数,所以它有点快):
- “帧” - 原始图片,该图像将被添加到,在 (100,100) 坐标处具有红色正方形大小 (500,500)
- "image" - 透明的 .png,大小为 (500,500),将被“插入”到原始帧中
- “result1” - 结果,其中红色像素被插入图像中的黑色“透明”像素替换
- "result2" - 想要的结果
代码,需要 opencv-python 和 numpy 模块:example.py
import cv2
import numpy as np
import copy
def insert_image_v2(frame, image, insert_coordinates, masked_value):
img_height = len(image)
img_width = len(image[0])
mask = np.ndarray((3,), np.uint8, buffer=np.array(masked_value))
y_diff = 0
for y in range(insert_coordinates[1], insert_coordinates[1]+img_height, 1):
x_diff = 0
for x in range(insert_coordinates[0], insert_coordinates[0]+img_width, 1):
if (image[y_diff][x_diff] != mask).all():
frame[y][x] = image[y_diff][x_diff]
x_diff += 1
y_diff += 1
return frame
if __name__ == "__main__":
frame = cv2.imread('frame.png')
image = cv2.imread('image.png')
insert_size = (image.shape[0], image.shape[1])
insert_coordinates = (100, 100)
x = insert_coordinates[0]
y = insert_coordinates[1]
result1 = copy.deepcopy(frame)
result1[y: y+insert_size[1], x: x+insert_size[0]] = image
result2 = insert_image_v2(frame, image, insert_coordinates, [0,0,0])
cv2.imshow('result1', result1)
cv2.imshow('result2', result2)
cv2.imwrite('result1.jpg', result1)
cv2.imwrite('result2.jpg', result2)
print()
解决方案
在Image alpha composition with OpenCV中找到了一个解决方案,它比我的速度快 20 倍。代码:
import cv2
import numpy as np
import time
def insert_image_v2(frame, image, insert_coordinates):
x = insert_coordinates[0]
y = insert_coordinates[1]
insert_size = (image.shape[1], image.shape[0])
background = frame[y: y+insert_size[1], x: x+insert_size[0]]
foreground = image
kernel = np.ones((5,5), np.uint8)
image_gray = cv2.cvtColor(foreground, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(image_gray, 1, 255, cv2.THRESH_BINARY_INV)
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
output = np.zeros(foreground.shape, dtype=foreground.dtype)
for i in range(3):
output[:,:,i] = background[:,:,i] * (opening/255)+foreground[:,:,i]*(1-opening/255)
frame[y: y+insert_size[1], x: x+insert_size[0]] = output
return frame
if __name__ == "__main__":
frame = cv2.imread('frame.png')
image = cv2.imread('image_1.png')
insert_size = (image.shape[0], image.shape[1])
insert_coordinates = (100, 100)
t1 = time.time()
frame = insert_image_v2(frame, image, insert_coordinates)
t2 = time.time()
print(f"{t2-t1}")
cv2.imshow('img', frame)
cv2.waitKey(0)
推荐阅读
- nlog - nlog 根据记录器优先级改变行为
- waf - 将 CleanContext 添加到 sphinx_build.py
- c# - 如何使用 Entity Framework .NET Core 将数据插入到我的数据库中?
- python-3.x - boto3 upload_file 上传部分wav文件
- teamcity - Teamcity - Signtool 错误 - 找不到 pfx 文件
- docker - 当我尝试重新启动 docker 容器时,我收到容器已存在的消息
- python - 如何计算给定单词列表的复数单词数以找到分数
- dns - 如何使多个 DNS 指向 Kubernetes 中的一项服务
- ios - 如何控制 UICollectionViewCell 调整动画大小?
- javascript - 在 NodeJS 上发送 UDP 请求