RGB,RGBA,YUV(亮度,红色分量与亮度信号的插值,蓝色与亮度的插值),HSV(色度,饱和度,亮度)。。。。。
void cv::cvtColor ( InputArray src,
OutputArray dst,
int code,
int dstCn = 0
)
// 数据类型转换
void cv::Mat::convertTo ( OutputArray m,
int rtype,
double alpha = 1,
double beta = 0
) const
改变色彩空间,前两个参数用于输入图像,目标图像,第三个参数指明转换的色彩空间,第四个参数默认就行。。需要注意的是该函数变换前后的图像取值范围
8位无符号图像的像素为0 - 255。CV_8U
16 无符号图像的像素为 0-65535. CV_16U
32 位浮点图像的像素为 0-1 ,
因此一定要注意目标图像的像素范围.在线性变换的情况下,范围问题不需要考虑,目标图像的像素不会超出范围。如果在非线性变换的情况下,那么应将输入 RGB 图像归一化到适当的范围以内来获得正确的结果,例如将 8位无符号图像转成 位32浮点图像 需要先将图像像素通过除以 255 缩放0-1 范围内 以防止产生错误结果.
数据类型转换,参数为输出图像,转换图像的目标类型,alpha ,beta缩放因子,偏置因子。
m ( x , y ) = s a t u r a t e c a s t < r t p y e > ( α ( ∗ t h i s ) ( x , y ) + β ) m(x,y) = saturate_cast
转换方式就是线性变换,按照指定的类型输出。
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
system("color E");
Mat img = imread("D:\\壁纸\\2k.jpg");
cout<<img.type()<<endl;
cout << size(img) << img.type() << endl;
if (img.empty())
{
cout << "error";
}
Mat gray, HSV, YUV, Lab, img32;
img.convertTo(img32, CV_32F, 1.0 / 255); // 类型转换,将CV_8U转换成CV_32F
cvtColor(img32, HSV, COLOR_BGR2HSV);
cvtColor(img32, YUV, COLOR_BGR2YUV);
cvtColor(img32, Lab, COLOR_BGR2Lab);
cvtColor(img32, gray, COLOR_BGR2GRAY);
imshow("原图", img32);
imshow("hsv", HSV);
imshow("YUV", YUV);
imshow("Lab", Lab);
imshow("gray", gray);
waitKey(100);
return 0;
}
图片的不同分量存放在不同通道里,通道的分离处理,在合并重新生成图像。
void cv::split ( const Mat & src,
Mat * mvbegin // 分离的通道,为数组的形式,需要知道通道数
)
void cv::split ( InputArray m,
OutputArrayOfArrays mv // 分离的单通道,向量vector格式,不用知道通道数
)
void cv::merge ( const Mat * mv, // 数组,尺寸,类型相同
size_t count, // 输入图像数组的长度,大于0
OutputArray dst
)
void cv::merge ( InputArrayOfArrays mv, // 与split对应
OutputArray dst
)
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
system("color E");
Mat img = imread("D:\\壁纸\\2k.jpg");
Mat HSV;
cvtColor(img, HSV, COLOR_RGB2HSV);
Mat imgs0, imgs1, imgs2; // 存放数组类型的结果
Mat imgv0, imgv1, imgv2; // 存放vector类型的结果
Mat result0, result1, result2; // 合并结果
Mat imgs[3];
split(img, imgs);
imgs0 = imgs[0];
imgs1 = imgs[1];
imgs2 = imgs[2];
imshow("B", imgs0); // 分离的结果
imshow("G", imgs1);
imshow("R", imgs2);
imgs[2] = img; // 改变通道数
merge(imgs, 3, result0); // 合并成 5 通道
// imshow("result0", result0); // imshow最多显示 4 个通道。可以在image watch中查看
Mat zero = cv::Mat::zeros(img.rows, img.cols, CV_8UC1);
imgs[0] = zero;
imgs[2] = zero;
merge(imgs, 3, result1); // 只剩绿色通道
imshow("resutl1", result1);
vector<Mat> imgv;
split(HSV, imgv);
imgv0 = imgv.at(0);
imgv1 = imgv.at(1);
imgv2 = imgv.at(2);
imshow("H", imgv0);
imshow("S", imgv1);
imshow("V", imgv2);
imgv.push_back(HSV); // 通道数改变
merge(imgv, result2); // 六通道
// imshow("result2", result2);
waitKey(0);
return 0;
}
void cv::minMaxLoc ( InputArray src, // 单通道,多个最值返回左上第一个
double * minVal, // 值,不需要的值设置为NULL
double * maxVal = 0, // 输入参数加上 &
Point * minLoc = 0, // 坐标指针,左上角为远点,Point(x,y)
Point * maxLoc = 0, // 水平x轴,数值y轴
InputArray mask = noArray() // 掩模,指定区域
)
cv::Point2i 对二维坐标设置的整形类型,Point2d double Point2f float,三维Point3i
Point.x 具体坐标可以通过对变量的 x,y,z 属性访问。
Mat cv::Mat::reshape ( int cn, // 转换后矩阵的通道数
int rows = 0 // 转换后矩阵的行数,0表示不变
) const
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
system("color E");
// Mat img = imread("D:\\壁纸\\2k.jpg");
float a[12] = { 1,2,3,4,5,10,6,7,8,9,10,0 };
Mat img = Mat(3, 4, CV_32FC1, a); // 单通道
Mat imgs = Mat(2, 3, CV_32FC2, a); // 多通道
double minVal, maxVal;
Point minIdx, maxIdx;
minMaxLoc(img, &minVal, &maxVal, &minIdx, &maxIdx); // 放入地址
cout << "max" << maxVal << " " << " point" << maxIdx << endl;
cout << "min" << minVal << " " << "point" << minIdx << endl;
Mat imgs_re = imgs.reshape(1, 4); // 多通道的最值要转换成单通道,(4,3)
minMaxLoc(imgs_re, &minVal, &maxVal, &minIdx, &maxIdx);
cout << "max" << maxVal << " " << " point" << maxIdx << endl;
cout << "min" << minVal << " " << "point" << minIdx << endl;
return 0;
}
Scalar cv::mean ( InputArray src, // 通道为 1-4,返回Scalar类型变量,4位单通道后三位为0
InputArray mask = noArray() // 掩模
)
void cv::meanStdDev ( InputArray src,
OutputArray mean, // 平均值,标准差
OutputArray stddev, // Mat型变量,数据个数与传入的通道数一样
InputArray mask = noArray()
)
int main(int argc, char *argv[])
{
system("color E");
// Mat img = imread("D:\\壁纸\\2k.jpg");
float a[12] = { 1,2,3,4,5,10,6,7,8,9,10,0 };
Mat img = Mat(3, 4, CV_32FC1, a); // 单通道
Mat imgs = Mat(2, 3, CV_32FC2, a); // 多通道
Scalar Mean;
Mean = mean(imgs);
cout << Mean << Mean[0] << Mean[1] << endl;
Mat MeanMat, StddevMat;
meanStdDev(img, MeanMat, StddevMat);
cout << MeanMat << StddevMat << endl;
meanStdDev(imgs, MeanMat, StddevMat);
cout << MeanMat << StddevMat << endl;
return 0;
}
求两幅图每个像素的大值,小值,保留较大值
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
system("color E");
Mat img0 = imread("lena.png");
Mat img1 = imread("noobcv.jpg");
Mat comMin, comMax;
max(img0, img1, comMax); // 保留两幅图像对应位置较大的值
min(img0, img1, comMin);
imshow("max", comMax);
imshow("min", comMin);
Mat src1 = Mat::zeros(Size(512, 512), CV_8UC3);
Rect rect(100, 100, 300, 300); // x,y,w,h
src1(rect) = Scalar(255, 255, 255); // 此范围内赋值,构建一个掩模
Mat comsrc1, comsrc2;
min(img0, src1, comsrc1); // 显示较小值,就提取了掩模 255(白色)的部分。
imshow("src1", comsrc1);
Mat img0G, img1G, comMinG, comMaxG;
cvtColor(img0, img0G, COLOR_BGR2GRAY);
cvtColor(img1, img1G, COLOR_BGR2GRAY);
max(img0G, img1G, comMaxG);
min(img0G, img1G, comMinG);
imshow("MinG", comMinG);
imshow("MaxG", comMaxG);
return 0;
}
就是逐位的 与 或 非 异或。对应的函数就是 bitwise_and/or/xor/not ,参数一样,两个输入图像,一个输出图像,一个掩模。
int main()
{
Mat img = imread("lena.png");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
//创建两个黑白图像
Mat img0 = Mat::zeros(200, 200, CV_8UC1);
Mat img1 = Mat::zeros(200, 200, CV_8UC1);
Rect rect0(50, 50, 100, 100);
img0(rect0) = Scalar(255);
Rect rect1(100, 100, 100, 100);
img1(rect1) = Scalar(255);
imshow("img0", img0);
imshow("img1", img1);
//进行逻辑运算
Mat myAnd, myOr, myXor, myNot, imgNot;
bitwise_not(img0, myNot);
bitwise_and(img0, img1, myAnd);
bitwise_or(img0, img1, myOr);
bitwise_xor(img0, img1, myXor);
bitwise_not(img, imgNot);
imshow("myAnd", myAnd);
imshow("myOr", myOr);
imshow("myXor", myXor);
imshow("myNot", myNot);
imshow("img", img);
imshow("imgNot", imgNot);
waitKey(0);
return 0;
}
非黑即白
double cv::threshold ( InputArray src, // CV_8U,CV_32F 两种类型,通道数与选择的方法有关
OutputArray dst, // 结果图
double thresh, // 阈值
double maxval, // 二值化过程中的最大值,BINARY方法有关
int type // 二值化的标志
)
标志 | 简记 | 作用 |
---|---|---|
THRESH_BINARY | 0 | 灰度值大于阈值的为最大值,其余为0 |
THREESH_BINARY_INY | 1 | 灰度值大于阈值的为0,其余为最大值 |
THRESH_TRUNC | 2 | 灰度值大于阈值的为阈值,其他值不变 |
THRESH_TOZERO | 3 | 灰度值大于阈值的不变,其他为0 |
THRESH_TOZERO_INV | 4 | 灰度值大于阈值的为0,其他不变 |
THRESH_OTSU | 8 | 大津法自动求全局阈值 |
THRESH_TRIANGLE | 16 | 三角形法自动求全局阈值 |
后两个标志是获取阈值的方法,可以与前面的标志一起使用比如“ THRESH_OTSU|THRESH_BINARY" ,前面5种需要认为的设置阈值,自动获取的会更加合适。但是调用时还是要输入thresh参数,就是系统不会认。
threshold() 函数全局就用一个阈值,实际上,由于光照,阴影的影响,全局只有一个i阈值是不合理的。adativeThershold() 提供了两个局部自适应阈值的二值化方法。
void cv::adaptiveThreshold ( InputArray src, // 只能是CV_8U
OutputArray dst,
double maxValue, // 二值化的最大值
int adaptiveMethod, // 自适应阈值的方法两种。高斯法或均值法
int thresholdType, // 二值化的标志,只能是BINART OR BINARY_INV 两种
int blockSize, // 自适应确定阈值的邻域,3,5,7奇数
double C // 平均值或加权平均值种减去的常数,可正可负
)
int main()
{
Mat img = imread("lena.png");
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
Mat img_B, img_B_V, gray_B, gray_B_V, gray_T, gray_T_V, gray_TRUNC;
//彩色图像二值化
threshold(img, img_B, 125, 255, THRESH_BINARY);
threshold(img, img_B_V, 125, 255, THRESH_BINARY_INV);
imshow("img_B", img_B);
imshow("img_B_V", img_B_V);
//灰度图BINARY二值化
threshold(gray, gray_B, 125, 255, THRESH_BINARY);
threshold(gray, gray_B_V, 125, 255, THRESH_BINARY_INV);
imshow("gray_B", gray_B);
imshow("gray_B_V", gray_B_V);
//灰度图像TOZERO变换
threshold(gray, gray_T, 125, 255, THRESH_TOZERO);
threshold(gray, gray_T_V, 125, 255, THRESH_TOZERO_INV);
imshow("gray_T", gray_T);
imshow("gray_T_V", gray_T_V);
//灰度图像TRUNC变换
threshold(gray, gray_TRUNC, 125, 255, THRESH_TRUNC);
imshow("gray_TRUNC", gray_TRUNC);
//灰度图像大津法和三角形法二值化
Mat img_Thr = imread("threshold.png", IMREAD_GRAYSCALE);
Mat img_Thr_O, img_Thr_T;
threshold(img_Thr, img_Thr_O, 100, 255, THRESH_BINARY | THRESH_OTSU);
threshold(img_Thr, img_Thr_T, 125, 255, THRESH_BINARY | THRESH_TRIANGLE);
imshow("img_Thr", img_Thr);
imshow("img_Thr_O", img_Thr_O);
imshow("img_Thr_T", img_Thr_T);
//灰度图像自适应二值化
Mat adaptive_mean, adaptive_gauss;
adaptiveThreshold(img_Thr, adaptive_mean, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 55, 0);
adaptiveThreshold(img_Thr, adaptive_gauss, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 55, 0);
imshow("adaptive_mean", adaptive_mean);
imshow("adaptive_gauss", adaptive_gauss);
waitKey(0);
return 0;
}
前面介绍的阈值比较方法都只有一个阈值,需要与多个阈值比较,就用LUT,一个像素灰度值的映射表,,它以像索灰度值作为索引,以灰度值映射后的数值作为表中的内容。
void cv::LUT ( InputArray src, // 输入图像矩阵,只能是cv_8u,可以多通道
InputArray lut, // 1*256的像素灰度值的查找表,单通道或多通道
OutputArray dst // 输出类型与LUT 的类型一致,将灰度值映射到了新的空间种
)
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
//LUT查找表第一层
uchar lutFirst[256];
for (int i = 0; i < 256; i++)
{
if (i <= 100)
lutFirst[i] = 0;
if (i > 100 && i <= 200) // 就是原图像的i像素,映射为我们指定的。
lutFirst[i] = 100;
if (i > 200)
lutFirst[i] = 255;
}
Mat lutOne(1, 256, CV_8UC1, lutFirst);
//LUT查找表第二层
uchar lutSecond[256];
for (int i = 0; i < 256; i++)
{
if (i <= 100)
lutSecond[i] = 0;
if (i > 100 && i <= 150)
lutSecond[i] = 100;
if (i > 150 && i <= 200)
lutSecond[i] = 150;
if (i > 200)
lutSecond[i] = 255;
}
Mat lutTwo(1, 256, CV_8UC1, lutSecond);
//LUT查找表第三层
uchar lutThird[256];
for (int i = 0; i < 256; i++)
{
if (i <= 100)
lutThird[i] = 100;
if (i > 100 && i <= 200)
lutThird[i] = 200;
if (i > 200)
lutThird[i] = 255;
}
Mat lutThree(1, 256, CV_8UC1, lutThird);
//拥有三通道的LUT查找表矩阵
vector<Mat> mergeMats;
mergeMats.push_back(lutOne);
mergeMats.push_back(lutTwo);
mergeMats.push_back(lutThree);
Mat LutTree;
merge(mergeMats, LutTree); // 通道合并
//计算图像的查找表
Mat img = imread("lena.png");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat gray, out0, out1, out2;
cvtColor(img, gray, COLOR_BGR2GRAY);
LUT(gray, lutOne, out0);
LUT(img, lutOne, out1);
LUT(img, LutTree, out2);
imshow("out0", out0);
imshow("out1", out1);
imshow("out2", out2);
waitKey(0);
return 0;
}
函数 | 说明 |
---|---|
cvtColor | 色彩空间转换 |
converTo | 数据类型转换 |
saturate_cast |
缩放到标准 |
split | 通道的分割 |
merge | 通道的合并 |
minMaxLoc | 像素最大最小值与位置 |
mean | 平均值 |
meanStdDev | 平均值加标准差 |
max/min | 比较两幅图像的较大较小值 |
bitwise_and/or/xor/not | 两幅图像素之间的逻辑操作 |
threshold | 二值化 |
adaptiveThreshold | 局部自适应二值化 |
LUT | 灰度值映射,多阈值 |
// 构建一个掩模
Mat src1 = Mat::zeros(Size(512, 512), CV_8UC3);
Rect rect(100, 100, 300, 300); // x,y,w,h
src1(rect) = Scalar(255, 255, 255); // 此范围内赋值,构建一个掩模