如何在Python中使用OpenCV合成两张图像?

7 投票
3 回答
5996 浏览
提问于 2025-04-18 13:09

我有一张不变的图片,还有一张是第一张图片加了滤镜的版本。我想创建第三张图片,这张图片应该是前两张的合成。

我知道在MATLAB里有一个叫做 imfuse() 的函数,它默认使用绿色和品红色的颜色通道。我想在Python中做同样的事情,使用完全相同的颜色通道。我该怎么做呢?

这里是这些图片(第一张是原始图片,第二张是加了滤镜的图片,第三张是MATLAB的结果):

image filter result

谢谢你的帮助!

3 个回答

0

下面是如何在Python/OpenCV/Numpy中实现这个功能的方法。

  • 读取图片
  • 以灰度模式读取边缘图像
  • 将原图像复制一份作为结果
  • 把边缘图像放到绿色通道中
  • (原图的红色和蓝色通道会变成品红色)
  • 保存结果

图片:

这里输入图片描述

边缘:

这里输入图片描述

import cv2
import numpy as np

# read the image
image = cv2.imread('image.png')

# read the edge image as grayscale
edges = cv2.imread('edges.png', cv2.IMREAD_GRAYSCALE)

# set the image to the red and blue channels and edges to the green channels
result = image.copy()
result[:,:,1] = edges

# save the results
cv2.imwrite('image_and_edges.png', result)

# show the results
cv2.imshow('result', result)
cv2.waitKey(0)

结果:

这里输入图片描述

替代方案

使用

result = image.copy()
result[:,:,0] = edges
result[:,:,2] = edges

结果:

这里输入图片描述

1

使用 SimpleITK,我们有以下的MR输入图像:

这里输入图片描述 这里输入图片描述

import SimpleITK as sitk
fixed_image = sitk.ReadImage("images/mr1.png", sitk.sitkFloat32)
moving_image = sitk.ReadImage("images/mr2.png", sitk.sitkFloat32)
out_image = sitk.GetArrayFromImage(sitk.Compose(fixed_image, moving_image, fixed_image))
plt.imshow(out_image / out_image.max()), plt.axis('off')

这里输入图片描述

8

默认情况下,imfuse 只是将一对图像叠加在一起,并用不同的颜色通道显示(默认设置是 Method=falsecolorColorChannels=green-magenta)。

下面是一个在MATLAB中的例子来说明这个过程(用Python/OpenCV写这个应该也很简单):

% a pair of grayscale images
A = imread('cameraman.tif');
B = imrotate(A,5,'bicubic','crop');    % image "A" rotated a bit

% use IMFUSE
C = imfuse(A,B);
imshow(C)

% use our version where: Red=B, Green=A, Blue=B
C = cat(3, B, A, B);
imshow(C)

这两种方式应该会得到相同的结果:

fused_images


编辑:

这里是Python/OpenCV的版本:

import numpy as np
import cv2

A = cv2.imread(r"C:\path\to\a.png", 0)
B = cv2.imread(r"C:\path\to\b.png", 0)

#C = cv2.merge((B,A,B))
C = np.dstack((B,A,B))
cv2.imshow("imfuse",C)
cv2.waitKey(0)

opencv_python_imfuse

撰写回答