1、Mat通道的分离与合并
多通道Mat分离为vector数组,vector数组可以合并为多通道Mat
vector< cv::Mat > mv;
cv::split(lab, mv); //分离
cv::merge(mv, lab);//合并
2、图片的深拷贝和浅拷贝
1)浅拷贝:
Mat B;
B = image // 第一种方式
Mat C(image); // 第二种方式
这两种方式称为浅copy,是由于它们有不同的矩阵头,但是它们共享内存空间,即指向一个矩阵。当图像矩阵发生变化时,两者相关联,都会变化。
2)深拷贝
Mat B,C;
B = image.clone(); // 第一种方式
image.copyTo(C); // 第二种方式
深拷贝是真正的copy了一个新的图像矩阵,此时image,B,C三者相互没有影响。
3、图像的拼接(横向和纵向)
// 图像拼接
cv::Mat ImageSplicing(vector<cv::Mat> images,int type)
{
if (type != 0 && type != 1)
type = 0;
int num = images.size();
int newrow = 0;
int newcol = 0;
cv::Mat result;
// 横向拼接
if (type == 0)
{
int minrow = 10000;
//1、获取行最小值
for (int i = 0; i < num; ++i)
{
if (minrow > images[i].rows)
minrow = images[i].rows;
}
newrow = minrow;
//2、利用行最小值调整图片大小、统一图片类型
for (int i = 0; i < num; ++i)
{
int tcol = images[i].cols*minrow / images[i].rows;
int trow = newrow;
cv::resize(images[i], images[i], cv::Size(tcol, trow));
newcol += images[i].cols;
if (images[i].type() != images[0].type())
images[i].convertTo(images[i], images[0].type());//数据类型转换
}
//3、创建拼图的mat
result = cv::Mat(newrow, newcol, images[0].type(), cv::Scalar(255, 255, 255));
cv::Range rangerow, rangecol;
int start = 0;
for (int i = 0; i < num; ++i)
{
rangerow = cv::Range((newrow - images[i].rows) / 2, (newrow - images[i].rows) / 2 + images[i].rows);
rangecol = cv::Range(start, start + images[i].cols);
images[i].copyTo(result(rangerow, rangecol)); //将image[i]复制到result的指定范围内
start += images[i].cols;
}
}
// 纵向拼接
else if (type == 1) {
int mincol = 10000;
for (int i = 0; i < num; ++i)
{
if (mincol > images[i].cols)
mincol = images[i].cols;
}
newcol = mincol;
for (int i = 0; i < num; ++i)
{
int trow = images[i].rows*mincol / images[i].cols;
int tcol = newcol;
cv::resize(images[i], images[i], cv::Size(tcol, trow));
newrow += images[i].rows;
if (images[i].type() != images[0].type())
images[i].convertTo(images[i], images[0].type());
}
result = cv::Mat(newrow, newcol, images[0].type(), cv::Scalar(255, 255, 255));
cv::Range rangerow, rangecol;
int start = 0;
for (int i = 0; i < num; ++i)
{
rangecol= cv::Range((newcol - images[i].cols) / 2, (newcol - images[i].cols) / 2 + images[i].cols);
rangerow = cv::Range(start, start + images[i].rows);
images[i].copyTo(result(rangerow, rangecol));
start += images[i].rows;
}
}
return result;
}
4、图像的加权混合(两张图片的透明度不同)
函数是将两张相同大小,相同类型的图片(叠加)线性融合的函数,可以实现图片的特效。
算子:g(x)=(1−α)f0(x)+αf1(x)
Mat dst;
addWeighted(image1, alpha, image2, (1 - alpha), 0, dst, -1);
imshow("dst", dst);
5、图像的亮度、对比度调节
算子:g(i,j)=αf(i,j)+β //α亮度 β对比度
此操作需要访问图像的每一个元素:
方法一:下标遍历法,格式为M.at< typede>(i,j)
if (channel == 3) {
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
dst_at.at<Vec3b>(h, w)[0] = saturate_cast<uchar>(image32f.at<Vec3f>(h, w)[0] * alpha + beta);
dst_at.at<Vec3b>(h, w)[1] = saturate_cast<uchar>(image32f.at<Vec3f>(h, w)[1] * alpha + beta);
dst_at.at<Vec3b>(h, w)[2] = saturate_cast<uchar>(image32f.at<Vec3f>(h, w)[2] * alpha + beta);
}
}
}
saturate_cast: 在图像处理方面,无论是加是减,乘除,都会超出一个像素灰度值的范围(0~255),saturate_cast函数的作用即是:当运算完之后,结果为负,则转为0,结果超出255,则为255。