void QuickDemo::channels_demo(Mat& image)
{
std::vector<Mat> vm;
split(image, vm);
//按照B、G、R次序提取出image对象里的元素值
imshow("蓝色", vm[0]);
imshow("绿色", vm[1]);
imshow("红色", vm[2]);
}
通过split函数将存储在image对象当中的三色提取出来,分别是[B、G、R]。
在合并的过程会发生有趣的现象,总结出了一些规律,如果一共是三个通道,而在合并的时候如果缺少某个通道,那么合并的结果就是该通道的颜色。
比如:
B + G == R
B + R == G
G + R == B
void QuickDemo::channels_demo(Mat& image)
{
std::vector<Mat> vm;
split(image, vm);
//合并
Mat dst;
vm[0] = 0; //B
vm[1] = 0; //G
merge(vm, dst);
imshow("合并之后", dst);
}
void cv::mixChannels (
InputArrayOfArrays src,
InputOutputArrayOfArrays dst,
const std::vector< int > & fromTo
)
参数介绍
比如 {0,2,1,1,2,0}表示:
void cv::mixChannels
(
const Mat * src,
size_t nsrcs,
Mat * dst,
size_t ndsts,
const int * fromTo,
size_t npairs
)
第一个参数:输入矩阵
第二个参数:输入矩阵的数量
第三个参数:输出矩阵
第四个参数:输出矩阵的数量
第五个参数:复制列表
第六个参数:复制列表的数量
在这个函数原型中,如果输入矩阵和输出矩阵都写1,那么就跟第一种函数原型是一致的了。
如果不为1,就可以实现多个矩阵组合并或者一个矩阵拆分为多个复杂矩阵等功能。
void QuickDemo::channels_demo(Mat& image)
{
Mat dst = Mat::zeros(image.size(), image.type());
int from_to[] = {0,2, 1,1,2,0};
/*
0通道赋值到2通道
1通道赋值到1通道
2通道赋值到0通道
*/
mixChannels(&image,1, &dst,1, from_to, 3);
imshow("交换的图像", dst);
}
HSV 也称六角锥体模型(Hexcone Model)。、这个模型中颜色的参数分别是:色调(H),饱和度(S),亮度(V)。
色调H:用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
饱和度S:取值范围为0.0~1.0;
亮度V:取值范围为0.0(黑色)~1.0(白色)。
HSV的模糊取值范围
H: 0— 180
S: 0— 255
V: 0— 255
此处把部分红色归为紫色范围:
提取mask对象
//提取mask值
void QuickDemo::inrange_demo(Mat& image)
{
Mat hsv;
//转换为hsv色彩的图像空间
cvtColor(image, hsv, COLOR_BGR2HSV);
Mat mask;
inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask);
imshow("轮廓显示", mask);
}
将mask对象的像素点的值取反,再以只拷贝mask的方式拷贝至另一张图像上。
//提取mask值
void QuickDemo::inrange_demo(Mat& image)
{
Mat hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
imshow("人物", image);
Mat mask;
inRange(hsv, Scalar(100, 43, 46), Scalar(124, 255, 255), mask);
//imshow("轮廓", mask);
Mat obj = Mat::zeros(image.size(), image.type());
obj = Scalar(0, 43 , 46);
//由于copyTo方法只能拷贝白色的像素点,所以需要对原图像的mask
//进行一个取反操作, 这样就能将取反后的mask放到obj上
bitwise_not(mask, mask);
image.copyTo(obj, mask);
imshow("转移", obj);
}
首先需要先提取出mask,mask是属于这张图片除了背景以外的阴影部分。
Mat mask;
inRange(hsv, Scalar(100, 43, 46), Scalar(124, 255, 255), mask);
imshow("轮廓", mask);
通过提取出人物的整个轮廓,再将该轮廓上的所有细节拷贝到另外一个Mat对象上。
void QuickDemo::pixel_statistic_demo(Mat& image)
{
double minv;
double maxv;
Point minLoc;
Point maxLoc;
std::vector<Mat> mv;
split(image, mv);
for (int i = 0; i < mv.size(); i++) {
minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());
std::cout << "第" << i << "统计 " << "min value: " << minv << "max value: " << maxv << std::endl;
}
//求出均值跟方差
Mat stddev, mean;
meanStdDev(image ,mean, stddev);
std::cout << "均值:";
for (int i = 0; i < 3; i++) {
std::cout << " " << mean.at<double>(i);
}
std::cout << std::endl;
std::cout << "方差:";
for (int i = 0; i < 3; i++) {
std::cout << " " << stddev.at<double>(i);
}
std::cout << std::endl;
}
void QuickDemo::draw_demo(Mat& image)
{
//设置背景
Mat m = Mat::zeros(image.size(), image.type());
m = Scalar(0,0,0);
//在m图像上绘制红色矩形
// 矩形原点以及宽高 颜色 填充
rectangle(m,Rect(120, 120, 200, 200), Scalar(0, 0, 255), -1, LINE_8, 0);
//在m图像上绘制蓝色圆形
// 原点 半径 圆颜色 填充
circle(m, Point(325, 325), 10, Scalar(255, 0, 0), -1, LINE_8, 0);
//在m图像绘制绿色线条
// 线段原点 线段结尾位置 线段颜色 绘制
line(m, Point(120, 120), Point(320, 320), Scalar(0, 255, 0), 2, LINE_8, 0);
//绘制椭圆
RotatedRect rrt;
rrt.center = Point(120, 120); //原点
rrt.size = Size(100, 200); //大小
rrt.angle = 240.0; //以Point为旋转角度
//在m对象上绘制rrt规则的椭圆
ellipse(m, rrt, Scalar(150, 22,30));
imshow("绘制几何", m);
}
在OpenCV中,有个RNG类,用它来产生随机数。可以使用RNG的构造函数,来创建随机数生成器的对象。代码如下:
RNG rng(12345); //指定随机种子位12345
uniform()
关于RNG类,再提到一个它的函数,uinform()
uniform:指定了一个在a和b范围的均匀分布的随机数
rng.uniform(1,255); //返回一个在1~255范围内的随机数
随机绘制直线并填充色彩
void QuickDemo::rangdrawing_demo()
{
Mat m = Mat::zeros(Size(512, 512), CV_8UC3);
int w = m.rows;
int h = m.cols;
m = Scalar(0, 0 ,0);
RNG rng(12345); //随机种子
while (true) {
int val = waitKey(200);
if (val == 27) {
break;
}
//随机点与随机色的设置
int pointx = rng.uniform(0, w);
int pointy = rng.uniform(0, h);
int linew = rng.uniform(0, w);
int lineh = rng.uniform(0, h);
int b = rng.uniform(0, 255);
int g = rng.uniform(0, 255);
int r = rng.uniform(0, 255);
//绘制线段
line(m, Point(pointx, pointy), Point(linew, lineh), Scalar(b, g, r), 1);
imshow("随机绘制", m);
}
}
void QuickDemo::drwaing_polygon_demo()
{
Mat m = Mat::zeros(Size(512, 512), CV_8UC3);
m = Scalar(0, 0, 0);
std::vector<Point> ptv;
int x, y;
int n = 0;
std::cout << "输入几变形";
std::cin >> n;
for (int i = 0; i < n; i++) {
std::cin >> x;
std::cin >> y;
ptv.push_back(Point(x, y));
}
//绘制多边
polylines(m, ptv, true, Scalar(0, 0 ,255),1, 8, 0);
imshow("绘制多边形", m);
//多边形填充
fillPoly(m, ptv,Scalar(0, 0, 255),8, 0);
imshow("填充多边形", m);
}
效果:
void drawContours(InputOutputArray image, InputArrayOfArrays contours,
int contourIdx, const Scalar& color, int thickness=1, int lineType=8,
InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )
void QuickDemo::drwaing_polygon_demo()
{
Mat m = Mat::zeros(Size(512, 512), CV_8UC3);
m = Scalar(0, 0, 0);
std::vector<Point> ptv;
int x, y;
int n = 0;
std::cout << "输入几变形";
std::cin >> n;
for (int i = 0; i < n; i++) {
std::cin >> x;
std::cin >> y;
ptv.push_back(Point(x, y));
}
std::vector<std::vector<Point>> pvv;
pvv.push_back(ptv);
drawContours(m, pvv, -1, Scalar(0, 0, 255), 2);
imshow("填充多边形", m);
}