效果图:

背景图:前景图:

import cv2
import numpy as np


'''
叠加图片
'''
def image_overlay():
    # 加载背景图像
    background = cv2.imread('background.jpg')
    # 加载前景图像
    foreground = cv2.imread('foreground.png', cv2.IMREAD_UNCHANGED)

    # 确保前景图像和背景图像尺寸相同
    foreground = cv2.resize(foreground, (background.shape[1], background.shape[0]))

    # 获取前景图像的 alpha 通道(如果有的话)
    alpha = foreground[:, :, 3] / 255.0
    
    # 分离前景和背景的颜色通道
    foreground = foreground[:, :, 0:3]
    background = background[:, :, 0:3]
    # 扩展 alpha 通道的维度,以便进行乘法运算
    alpha = np.expand_dims(alpha, axis=2)
    # 根据 alpha 通道对前景图像和背景图像进行混合
    blended = (background * (1 - alpha) + foreground * alpha).astype(np.uint8)

    # 在背景图像上覆盖混合后的图像
    result = background.copy()
    result[:,:,:] = blended

    # 显示结果
    cv2.imshow('Overlay Image', result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

using OpenCvSharp;
using System;

namespace OpenCVNet.Utility
{
    public static class OpenCVUtility
    {
        
        /// <summary>
        /// 叠加图片(循环像素点)
        /// </summary>
        /// <param name="bgPath">背景图像</param>
        /// <param name="fgPath">前景图像</param>
        /// <param name="dstPath">目标图像</param>
        /// <returns></returns>
        public static void OverlayImage2(string bgPath, string fgPath, string dstPath)
        {
            // 加载背景图像
            Mat background = Cv2.ImRead(bgPath,ImreadModes.Color);
            // 加载前景图像
            Mat foreground = Cv2.ImRead(fgPath, ImreadModes.Unchanged);
           
            // 确保前景图像和背景图像尺寸相同
            Cv2.Resize(foreground, foreground, new Size(background.Cols, background.Rows));

            // 将前景图片覆盖在背景图片上
            for (int y = 0; y < foreground.Rows; y++)
            {
                for (int x = 0; x < foreground.Cols; x++)
                {
                    Vec4b foregroundPixel = foreground.Get<Vec4b>(y, x);
                    Vec3b backgroundPixel = background.Get<Vec3b>(y, x);

                    // 获取前景图像的RGB通道值和alpha通道值
                    int foregroundB = foregroundPixel.Item0;
                    int foregroundG = foregroundPixel.Item1;
                    int foregroundR = foregroundPixel.Item2;
                    // 将alpha值归一化到0到1之间
                    double alpha = foregroundPixel.Item3 / 255.0;  
                    // 混合RGB通道值
                    int mixedB = (int)(foregroundB * alpha + backgroundPixel.Item0 * (1 - alpha));
                    int mixedG = (int)(foregroundG * alpha + backgroundPixel.Item1 * (1 - alpha));
                    int mixedR = (int)(foregroundR * alpha + backgroundPixel.Item2 * (1 - alpha));
                    // 更新背景图像的RGB通道值
                    background.Set(y, x, new Vec3b((byte)mixedB, (byte)mixedG, (byte)mixedR));
                    //if (foregroundPixel[3] > 0)  // 只处理不透明的像素
                    //{
                    //    background.Set<Vec3b>(y, x, new Vec3b(foregroundPixel[0], foregroundPixel[1], foregroundPixel[2]));
                    //}
                }
            }

            // 显示结果
            Cv2.ImShow("Overlay Image", background);
            Cv2.WaitKey(0);
            Cv2.DestroyAllWindows();
            //保存合成的图像
            //result.SaveImage(dstPath);
        }


        /// <summary>
        /// 叠加图片
        /// </summary>
        /// <param name="bgPath"></param>
        /// <param name="fgPath"></param>
        /// <param name="dstPath"></param>
        /// <returns></returns>
        public static string OverlayImage(string bgPath, string fgPath, string dstPath)
        {
            // 加载背景图像
            Mat background = Cv2.ImRead("D:/test/Image376.jpg");// ImreadModes.Color
            // 加载前景图像
            Mat foreground = Cv2.ImRead("D:/test/4330_PhotoStand003_2023-05-19_101659.png", ImreadModes.Unchanged);

            // 确保前景图像和背景图像尺寸相同
            Cv2.Resize(foreground, foreground, new Size(background.Cols, background.Rows));

            // 分离前景图像的RGB通道和alpha通道
            Mat[] foregroundChannels = Cv2.Split(foreground);
            Mat alpha = (foregroundChannels.Length == 4) ? foregroundChannels[3] : null;

            // 分离前景和背景的颜色通道
            Mat blended = new Mat();
            Cv2.Merge(foregroundChannels[0..3], blended);

            if (alpha != null)
            {
                // 扩展 alpha 通道的维度,以便进行位运算
                Mat expandedAlpha = new Mat();
                Cv2.CvtColor(alpha, expandedAlpha, ColorConversionCodes.GRAY2BGR);

                // 对 alpha 通道进行取反操作
                Mat invAlpha = new Mat();
                Cv2.BitwiseNot(expandedAlpha, invAlpha);

                // 根据 alpha 通道对前景图像和背景图像进行混合
                Cv2.BitwiseAnd(background, invAlpha, background);
                Cv2.BitwiseAnd(blended, expandedAlpha, blended);
                Cv2.BitwiseOr(background, blended, blended);
            }

            // 在背景图像上覆盖混合后的图像
            Mat result = background.Clone();
            blended.CopyTo(result);

            // 显示结果
            Cv2.ImShow("Overlay Image", result);
            Cv2.WaitKey(0);
            Cv2.DestroyAllWindows();
            //保存合成的图像
            //result.SaveImage(dstPath);
        }
    }
}


 

GitHub 加速计划 / opencv31 / opencv
77.34 K
55.71 K
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:25 天前 )
e1fec156 features2d: fixed out of bounds access in SIFT 3 天前
63087396 - 3 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐