**
前言
**
打算做点有意思的东西了。
**
分离通道
**
split用于将一个多通道数组分离成几个单通道数组。
void split(const Mat& src, Mat* mvbegin);
void split(InputArray m, OutputArrayOfArrays mv);
- 第一个参数const Mat&类型或InputArray类型的需要进行分离的多通道数组
- 第二个参数,Mat*类型或OutputArrayOfArrays类型的输出数组或输出的vector容器
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
Mat src = imread("E:/File/fusionImage2.bmp");
vector<Mat> channels;
split(src, channels);
Mat img_B= channels.at(0);
imshow("img_B", img_B);
Mat logoImg = Mat::zeros(Size(500, 500), CV_8UC1);
Mat img_ROI = img_B(Rect(100, 50, logoImg.cols, logoImg.rows));
double alpha = 1.4;
addWeighted(img_ROI, alpha, logoImg, 1 - alpha, 0.,img_ROI);
imshow("分离得到的blue通道的ROI与logoImg混合", img_B);
waitKey(0);
}
由于img_B只是单通道,所以显示出来是灰色。
**
合并通道
**
void merge(const Mat* mv, size_t count, OutputArray dst);
void merge(InputArrayOfArrays mv, OutputArray dst);
- 第一个参数mv,填入需要被合并的输入矩阵或vector容器,这个mv参数中所有的矩阵必须有着一样的尺寸和深度
- 第二个参数,count。当mv为空白的C数组时,代表输入矩阵的个数,这个参数必须大于1
- 第三个参数,dst,输出矩阵,和mv[0]拥有一样的尺寸和深度,并且通道数量是矩阵阵列中的通道的总数
输出矩阵中的每个元素都将是输出数组的串接。其中第i个输入数组的元素被视为mv[i]。C一般用其中的Mat::at()方法对某个通道进行存储。
- Mat::at()返回的是引用,修改一个,另一个也随之改变。
Mat src = imread("E:/File/face.jpg");
if (src.empty()) {
cout << "读取图像有误,请重新输入正确路径!" << endl;
return;
}
imshow("src img", src);
//分离
vector<Mat> channels_BGR;
split(src, channels_BGR);
Mat img_B = channels_BGR[0];
Mat img_G = channels_BGR[1];
Mat img_R = channels_BGR[2];
imshow("blue img", img_B); //这个是单通道,所以是灰色
imshow("green img", img_G);
imshow("red img", img_R);
//将BGR色彩空间转换成HSV色彩空间
Mat img_HSV;
cvtColor(src, img_HSV, COLOR_BGR2HSV);
imshow("HSV img", img_HSV);
//分离
vector<Mat> channels_HSV;
split(img_HSV, channels_HSV);
Mat img_H = channels_HSV[0];
Mat img_S = channels_HSV[1];
Mat img_V = channels_HSV[2];
imshow("hue img", img_H);
imshow("saturation img", img_S);
imshow("value img", img_V);
//合成
Mat dst;
merge(channels_HSV, dst);
imshow("HSV合成图像", dst);
单独显示一个通道就是0~255的灰色,但是如果是把3个通道的值都让其等于提取的那个通道的话,单独通道的颜色就显示出来了--------同理,单独去除哪个通道也是一样的道理:
Mat src = imread("E:/wumo.jpg");
imshow("原始图", src);
vector<Mat> channels;
split(src, channels);
vector<Mat> bgr(3);
//需要隐藏的通道,尺寸与src相同,单通道黑色图像
Mat hideChannel(src.size(), CV_8UC1, Scalar(0));
//显示彩色的B-蓝色分量
Mat img_B(src.size(), CV_8UC3);
bgr[0] = channels[0];
bgr[1] = hideChannel;
bgr[2] = hideChannel;
merge(bgr, img_B);
imshow("img_B-蓝色通道", img_B); //这个是3通道,都是蓝色
//红蓝混合
Mat img_RB(src.size(), CV_8UC3);
bgr[0] = channels[0];
bgr[1] = hideChannel;
bgr[2] = channels[2];
merge(bgr, img_RB);
imshow("红蓝混合,无绿", img_RB);
**
HSV提取图像
**
BGR颜色空间中,各个颜色区分性不强。但是对于HSV颜色空间来说,每种颜色都很明确。
- 根据下表,可以看出,HSV把几个基本的颜色都划定了上下范围。因此,根据HSV范围,可以很容易把某种颜色分离出来。
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void extract_object() {
VideoCapture capture("E:/File/tree.avi");
if (!capture.isOpened()) {
cout << "cannot open ...";
system("pause");
}
while (true) {
Mat frame;
bool ret = capture.read(frame);
cout << ret << endl;
if (ret == false)
break;
//转换颜色空间
Mat hsv;
cvtColor(frame,hsv, COLOR_BGR2HSV);
imshow("hsv", hsv);
if (waitKey(30) >= 0)
break;
}
}
int main() {
extract_object();
cout << "END" << endl;
system("pause");
destroyAllWindows();
}
装了Opencv的,都会有一份素材,应该在\opencv\sources\samples\data目录下。上面用的tree.avi,素材里也会有。
MASK是什么?
mask掩码,学过PS的应该知道,其实就是蒙版。但是有时候,Opencv里的mask没有蒙版那么强。只要把物体轮廓显示出来的图像,都叫mask。把前面循环里的改一下:
//显示源图像
imshow("源", frame);
//转换颜色空间
Mat hsv;
cvtColor(frame,hsv, COLOR_BGR2HSV);
//拿到绿色的掩码
Mat mask;
inRange(hsv, Scalar(35,43,46), Scalar(77,255,255), mask);
//显示掩码
imshow("mask", mask);
这里用了个inRange()把特定区域的图像印到mask上。
void inRange(InputArray src,
InputArray lowerb,
InputArray upperb,
OutputArray dst);
但是如果我不要这种,我想把那块绿色的区域显示出来,啊彩色的。那才是蒙版MASK对吧
//图像与操作
Mat dst;
bitwise_and(frame, frame, dst, mask);
借用了bitwise_and()里有一个传入mask的参数,这里我们没有使用这个函数与的功能,只使用了遮盖的功能。
最后有一点,其他函数中的遮盖操作:
.copyTo()
这个函数第二个参数就是mask。
Mat src = imread("E:/File/fusionImage2.bmp");
Mat signal = imread("E:/File/002.jpg");
if (!src.data||!signal.data) {
cout << "读取图像有误,请重新输入正确路径!" << endl;
return;
}
imshow("violet evergarden", src);
imshow("logo", signal);
Mat img_Roi = src(Rect(450, 20, signal.cols, signal.rows));
//加载掩模
Mat mask = imread("E:/File/mask.jpg",0);//0显示为灰度图
imshow("mask", mask);
//将掩模复制到ROI
signal.copyTo(img_Roi,mask); //mask大小要和img_Roi一样,mask为1 的区域,不要,mask为0的区域,保留
//将signal复制到ROI
//signal.copyTo(img_Roi);
imshow("利用ROI实现图像叠加", src);
参考:《Opencv3编程入门》