多通道图像混合
视频讲解如下:
当前系列所有demo下载地址:
https://github.com/GaoRenBao/OpenCv4-Demo
不同编程语言对应的OpenCv版本以及开发环境信息如下:
语言 | OpenCv版本 | IDE |
C# | OpenCvSharp4.4.8.0.20230708 | Visual Studio 2022 |
C++ | OpenCv-4.5.5-vc14_vc15 | Visual Studio 2022 |
Python | OpenCv-Python (4.6.0.66) | PyCharm Community Edition 2022.1.3 |
测试原图:


运行效果如下:

C#版本
C#版本需要安装“OpenCvSharp4”、“OpenCvSharp4.runtime.win”两个库才行。不然会报错。
如果需要使用“ BitmapConverter.ToBitmap”操作,则需要追加安装“OpenCvSharp4.Extensions”库。
using OpenCvSharp;
using System;
namespace demo
{
internal class Program
{
static void Main(string[] args)
{
if (MultiChannelBlending())
{
Console.WriteLine("运行成功,得出了需要的图像~! ");
}
Cv2.WaitKey(0);
}
static bool MultiChannelBlending()
{
#region 多通道混合-蓝色分量部分
// 【1】读入图片
Mat logoImage = Cv2.ImRead("../../../images/dota_logo.jpg", 0);
Mat srcImage = Cv2.ImRead("../../../images/dota_jugg.jpg");
if (logoImage.Data == null) { Console.WriteLine("Oh,no,读取logoImage错误~! \n"); return false; }
if (srcImage.Data == null) { Console.WriteLine("Oh,no,读取srcImage错误~! \n"); return false; }
//【2】把一个3通道图像转换成3个单通道图像
Mat[] channels;
Cv2.Split(srcImage, out channels);//分离色彩通道
//【3】将原图的蓝色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
Mat imageBlueChannel = channels[0];
//【4】将原图的蓝色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageBlueChannel中
Cv2.AddWeighted(
imageBlueChannel[new Rect(500, 250, logoImage.Cols, logoImage.Rows)],
1.0, logoImage, 0.5, 0,
imageBlueChannel[new Rect(500, 250, logoImage.Cols, logoImage.Rows)]);
//【5】将三个单通道重新合并成一个三通道
Cv2.Merge(channels, srcImage);
//【6】显示效果图
//Cv2.NamedWindow(" <1>游戏原画+logo蓝色通道");
Cv2.ImShow(" <1>游戏原画+logo蓝色通道", srcImage);
#endregion
#region 多通道混合-绿色分量部分
// 【1】读入图片
logoImage = Cv2.ImRead("../../../images/dota_logo.jpg", 0);
srcImage = Cv2.ImRead("../../../images/dota_jugg.jpg");
if (logoImage.Data == null) { Console.WriteLine("读取logoImage错误~! \n"); return false; }
if (srcImage.Data == null) { Console.WriteLine("读取srcImage错误~! \n"); return false; }
//【2】将一个三通道图像转换成三个单通道图像
Cv2.Split(srcImage, out channels);//分离色彩通道
//【3】将原图的绿色通道的引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
Mat imageGreenChannel = channels[1];
//【4】将原图的绿色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageGreenChannel中
Cv2.AddWeighted(
imageGreenChannel[new Rect(500, 250, logoImage.Cols, logoImage.Rows)],
1.0, logoImage, 0.5, 0,
imageGreenChannel[new Rect(500, 250, logoImage.Cols, logoImage.Rows)]);
//【5】将三个独立的单通道重新合并成一个三通道
Cv2.Merge(channels, srcImage);
//【6】显示效果图
//Cv2.NamedWindow("<2>游戏原画+logo绿色通道");
Cv2.ImShow("<2>游戏原画+logo绿色通道", srcImage);
#endregion
#region 多通道混合-红色分量部分
// 【1】读入图片
logoImage = Cv2.ImRead("../../../images/dota_logo.jpg", 0);
srcImage = Cv2.ImRead("../../../images/dota_jugg.jpg");
if (logoImage.Data == null) { Console.WriteLine("读取logoImage错误~! \n"); return false; }
if (srcImage.Data == null) { Console.WriteLine("读取srcImage错误~! \n"); return false; }
//【2】将一个三通道图像转换成三个单通道图像
Cv2.Split(srcImage, out channels);//分离色彩通道
//【3】将原图的红色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
imageGreenChannel = channels[2];
//【4】将原图的红色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageRedChannel中
Cv2.AddWeighted(
imageGreenChannel[new Rect(500, 250, logoImage.Cols, logoImage.Rows)],
1.0, logoImage, 0.5, 0,
imageGreenChannel[new Rect(500, 250, logoImage.Cols, logoImage.Rows)]);
//【5】将三个独立的单通道重新合并成一个三通道
Cv2.Merge(channels, srcImage);
//【6】显示效果图
//Cv2.NamedWindow("<3>游戏原画+logo红色通道 ");
Cv2.ImShow("<3>游戏原画+logo红色通道 ", srcImage);
#endregion
return true;
}
}
}
C++版本
C++版本采用的是毛星云的代码
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
bool MultiChannelBlending()
{
//【0】定义相关变量
Mat srcImage;
Mat logoImage;
vector<Mat> channels;
Mat imageBlueChannel;
//=================【蓝色通道部分】=================
// 描述:多通道混合-蓝色分量部分
//============================================
// 【1】读入图片
logoImage = imread("../images/dota_logo.jpg", 0);
srcImage = imread("../images/dota_jugg.jpg");
if (!logoImage.data) { printf("Oh,no,读取logoImage错误~! \n"); return false; }
if (!srcImage.data) { printf("Oh,no,读取srcImage错误~! \n"); return false; }
//【2】把一个3通道图像转换成3个单通道图像
split(srcImage, channels);//分离色彩通道
//【3】将原图的蓝色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
imageBlueChannel = channels.at(0);
//【4】将原图的蓝色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageBlueChannel中
addWeighted(imageBlueChannel(Rect(500, 250, logoImage.cols, logoImage.rows)), 1.0,
logoImage, 0.5, 0, imageBlueChannel(Rect(500, 250, logoImage.cols, logoImage.rows)));
//【5】将三个单通道重新合并成一个三通道
merge(channels, srcImage);
//【6】显示效果图
namedWindow(" <1>游戏原画+logo蓝色通道");
imshow(" <1>游戏原画+logo蓝色通道", srcImage);
//=================【绿色通道部分】=================
// 描述:多通道混合-绿色分量部分
//============================================
//【0】定义相关变量
Mat imageGreenChannel;
//【1】重新读入图片
logoImage = imread("dota_logo.jpg", 0);
srcImage = imread("dota_jugg.jpg");
if (!logoImage.data) { printf("读取logoImage错误~! \n"); return false; }
if (!srcImage.data) { printf("读取srcImage错误~! \n"); return false; }
//【2】将一个三通道图像转换成三个单通道图像
split(srcImage, channels);//分离色彩通道
//【3】将原图的绿色通道的引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
imageGreenChannel = channels.at(1);
//【4】将原图的绿色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageGreenChannel中
addWeighted(imageGreenChannel(Rect(500, 250, logoImage.cols, logoImage.rows)), 1.0,
logoImage, 0.5, 0., imageGreenChannel(Rect(500, 250, logoImage.cols, logoImage.rows)));
//【5】将三个独立的单通道重新合并成一个三通道
merge(channels, srcImage);
//【6】显示效果图
namedWindow("<2>游戏原画+logo绿色通道");
imshow("<2>游戏原画+logo绿色通道", srcImage);
//=================【红色通道部分】=================
// 描述:多通道混合-红色分量部分
//============================================
//【0】定义相关变量
Mat imageRedChannel;
//【1】重新读入图片
logoImage = imread("../images/dota_logo.jpg", 0);
srcImage = imread("../images/dota_jugg.jpg");
if (!logoImage.data) { printf("Oh,no,读取logoImage错误~! \n"); return false; }
if (!srcImage.data) { printf("Oh,no,读取srcImage错误~! \n"); return false; }
//【2】将一个三通道图像转换成三个单通道图像
split(srcImage, channels);//分离色彩通道
//【3】将原图的红色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
imageRedChannel = channels.at(2);
//【4】将原图的红色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageRedChannel中
addWeighted(imageRedChannel(Rect(500, 250, logoImage.cols, logoImage.rows)), 1.0,
logoImage, 0.5, 0., imageRedChannel(Rect(500, 250, logoImage.cols, logoImage.rows)));
//【5】将三个独立的单通道重新合并成一个三通道
merge(channels, srcImage);
//【6】显示效果图
namedWindow("<3>游戏原画+logo红色通道 ");
imshow("<3>游戏原画+logo红色通道 ", srcImage);
return true;
}
int main()
{
if (MultiChannelBlending())
{
cout << endl << "\n运行成功,得出了需要的图像~! ";
}
waitKey(0);
return 0;
}
Python版本
import cv2
def MultiChannelBlending():
# =================【蓝色通道部分】=================
# 描述:多通道混合-蓝色分量部分
# ============================================
# 【1】读入图片
logoImage = cv2.imread('../images/dota_logo.jpg', 0)
srcImage = cv2.imread('../images/dota_jugg.jpg')
if logoImage is None:
print("Oh,no,读取logoImage错误~! \n")
return False
if srcImage is None:
print("Oh,no,读取srcImage错误~! \n")
return False
# 【2】把一个3通道图像转换成3个单通道图像
ImgB, ImgG, ImgR = cv2.split(srcImage)
# 【3】将原图的蓝色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到ImgB中
rows, cols = logoImage.shape
cv2.addWeighted(
ImgB[250:250 + rows, 500:500 + cols],
1, logoImage, 0.5, 0,
ImgB[250:250 + rows, 500:500 + cols])
# 【4】将三个单通道重新合并成一个三通道
srcImage = cv2.merge([ImgB, ImgG, ImgR])
# 【5】显示效果图
cv2.imshow("Blue", srcImage)
# =================【绿色分量部分】=================
# 描述:多通道混合-绿色分量部分
# ============================================
# 【1】读入图片
logoImage = cv2.imread('../images/dota_logo.jpg', 0)
srcImage = cv2.imread('../images/dota_jugg.jpg')
if logoImage is None:
print("Oh,no,读取logoImage错误~! \n")
return False
if srcImage is None:
print("Oh,no,读取srcImage错误~! \n")
return False
# 【2】把一个3通道图像转换成3个单通道图像
ImgB, ImgG, ImgR = cv2.split(srcImage)
# 【3】将原图的绿色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到ImgG中
rows, cols = logoImage.shape
cv2.addWeighted(
ImgG[250:250 + rows, 500:500 + cols],
1, logoImage, 0.5, 0,
ImgG[250:250 + rows, 500:500 + cols])
# 【4】将三个单通道重新合并成一个三通道
srcImage = cv2.merge([ImgB, ImgG, ImgR])
# 【5】显示效果图
cv2.imshow("Green", srcImage)
# =================【红色分量部分】=================
# 描述:多通道混合-红色分量部分
# ============================================
# 【1】读入图片
logoImage = cv2.imread('dota_logo.jpg', 0)
srcImage = cv2.imread('dota_jugg.jpg')
if logoImage is None:
print("Oh,no,读取logoImage错误~! \n")
return False
if srcImage is None:
print("Oh,no,读取srcImage错误~! \n")
return False
# 【2】把一个3通道图像转换成3个单通道图像
ImgB, ImgG, ImgR = cv2.split(srcImage)
# 【3】将原图的红色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到ImgR中
rows, cols = logoImage.shape
cv2.addWeighted(
ImgR[250:250 + rows, 500:500 + cols],
1, logoImage, 0.5, 0,
ImgR[250:250 + rows, 500:500 + cols])
# 【4】将三个单通道重新合并成一个三通道
srcImage = cv2.merge([ImgB, ImgG, ImgR])
# 【5】显示效果图
cv2.imshow("Red", srcImage)
MultiChannelBlending()
cv2.waitKey(0)