opencv中的API解读

目录

一.imread和imshow

1.imread

2.imshow

二.waitKey和destoryAllWindows()

1.waitKey()

2.destoryAllWindows()

三.namedWindow()

四.cvtColor和imwrite(色彩转化)

1.cvtColor

2.imwrite

五.Mat/clone/copyto

1.创建与克隆

2.打印一个8*8的单通道的8位的无符号的数据0

3.打印一个8*8的三通道的8位的无符号的数据 0

4.打印一个8*8的单通道的8位的无符号的数据 1

​编辑5.打印一个8*8的三通道的8位的无符号的数据 1

​编辑6.给三个通道赋值

​编辑7.展示颜色

六. add/subtract/divide/multiply

1.标量的加减乘除形式

2.直接操作API

七.createTrackbar(滑动控件)

1.API介绍

2.例子 

八.addWeighted(图像比例混合)

1.API介绍

2.例子 

九.applyColorMap(伪色彩)

1.API介绍

2.例子  

十.rectangle和Rect(创建矩形框)

1.API介绍

2.例子  

十一.逻辑运算符与或非

十二.split和merge(图像通道分离)

十三.mixChannels(图像通道混合)

十四. inRange(指定空间色彩提取)

十五.minMaxLoc(计算最大最小值)

​编辑

十六.meanStdDev(计算均值和标准方差)

十七.rectangle(矩形)/circle(圆)/line(线)/ellipse(椭圆)

1.坐标系

2.Rect

3.rectangle 

4.circle

5.line

6.ellipse

十八.polylines多边形图像绘制

十九.fillPoly多边形图像填充

二十.drawContours绘制与填充

二十一.rng.uniform产生随机数

二十二.setMouseCallback(鼠标绘制)

二十二.convertTo(缩放并转换到另外一种数据类型)

二十三.normalize归一化函数

二十四.resize放缩和插值

二十五.flip图像的翻转

一.imread和imshow

读取图像imread
显示图像imshow

1.imread

Mat cv::imread(const String& filename, int flags = IMREAD_COLOR)
//imread函数读取出来都是Mat类型,所有的图片类型都是Matrix矩阵类型(二维数组)
//const String& filename:第一个参数是代表的完整的文件夹路径
//
标志参数作用
IMREAD_COLOR或者1(默认) imread按三通道方式读入图像,即彩色图像
IMREAD_GRAYSCALE或者0imread按单通道的方式读入图像,即灰度图像
IMREAD_UNCHANGED或者-1 imread按解码得到的方式读入图像

2.imshow

void cvimshow(const cv:String &winname, cv::lnputArray mat)
//第一个参数:表示窗口的名称
//第二个参数:表示要输出的图像的数据对象

举例: 

Mat img;  //声明一个保存图像的类
img = imread("F:/picture/yang.png",1);//彩色图像
//img=imread("F:/picture/yang.png",0);灰度图像
imshow("test", img); //显示图像

二.waitKey和destoryAllWindows()

显示指定的图像(毫秒)waitKey()
销毁所有创建的窗口

destoryAllWindows()

1.waitKey()

waitKey()与waitKey(0),都代表无限等待一直阻塞,非常适合一直显示图像。

waitKey(n),显示n毫秒后,关闭显示的窗口。人眼可识别300毫秒以上的。

void Demo::Key_demo(Mat& img)
{
	Mat dst = Mat::zeros(img.size(), img.type());
	while (true)
	{
		int c = waitKey(100);//键盘响应
		if (c == 27) { //ESc退出
			break;
		}
		if (c == 49) {   //按键1
			std::cout << "you enter key #1" << std::endl;
			cvtColor(img, dst, COLOR_BGR2GRAY);//将BGR->GRAY
		} 
		if (c == 50) {   //按键2
			std::cout << "you enter key #2" << std::endl;
			cvtColor(img, dst, COLOR_BGR2HSV); //将BGR->HSV
		}
		else if (c == 51) { //按键3
			std::cout << "you enter key #3" << std::endl;
			add(img, Scalar(100, 100, 100), dst); //图像增加亮度
		}
		imshow("图像转化后", dst);
	}
}

2.destoryAllWindows()

destoryAllWindows(),将前面创建的所有窗口销毁了

三.namedWindow()

图像显示类型namedWindow()

针对图像显示不全,使用函数namedWindow

namedWindow(winname, flags=None)
//第一个参数代表输入窗口的名称
//第二个参数代表输入窗口的类型
标志参数作用
WINDOW_NORMAL显示图像后,允许用户随意调整窗口大小
WINDOW_AUTOSIZE(默认类型)根据图像大小显示窗口,不允许用户调整大小
WINDOW_FREERATIO窗口大小自适应比例
WINDOW_KEEPRATIO保持图像的比例

举例:namedWindow("test", WINDOW_FREERATIO);

四.cvtColor和imwrite(色彩转化)

图像色彩空间转化

cvtColor

保存函数

imwrite

1.cvtColor

void cv::cvtColor(cv::InputArray src, cv::OutputArray dst,int code, int dstCn = 0 
//第一个参数输入图像 Mat类型
//第二个参数输出图像 Mat类型
//第三个参数颜色映射类型 
//第四个参数输出的通道数 (0='automatic'),我们可以使用默认值,什么都不写。

COLOR_BGR2GRAY=6

彩色到灰度
COLOR_GRAY2BGR=8灰度到彩色
COLOR_BGR2HSV=40BGR到HSV
COLOR_HSV2BGR=54HSV到BGR

举例:

void Demo::cvtcolor_demo(Mat& img)
{
	Mat gray, hsv;
	cvtColor(img, gray, COLOR_BGR2GRAY);//bgr->gray
	cvtColor(img, hsv, COLOR_BGR2HSV);//bgr->hsv
	imshow("输出gray", gray);
	imshow("输出hsv",hsv);
}

2.imwrite

bool cv::write(const String& filename, InputArray img,const std::vector<int>& params = std::vector<int>())
//第一个参数表示要保存在哪个目录下
//第二个参数表示要保存的图像 Mat类型

举例:

void Demo::cvtcolor_demo(Mat& img)
{
	Mat gray, hsv;
	cvtColor(img, gray, COLOR_BGR2GRAY);//bgr->gray
	cvtColor(img, hsv, COLOR_BGR2HSV);
	imshow("输出gray", gray);
	imshow("输出hsv",hsv);
	imwrite("F:/picture/jiajiagray.png", gray);//保存gray名字jiajiagray.png
	imwrite("F:/picture/jiajiahsv.png", hsv);//保存hsv名字jiajiahsv.png
}

五.Mat/clone/copyto

image_in.copyTo(image_out);//把image_in这张图复制(copy to)到image_out上
image_in.copyTo(image_out,mask);
//把image_in这张图复制(copy to)到image_out上,且image_in对应mask中像素值为0的像素点都不会贴到image_out上

//创建方法  克隆
Mat m1=src.clone();

//复制
Mat m2;
src.copyTo(m2);

//赋值
Mat m3=src;

//创建空白图像
Mat m4=Mat::zeros(src.size(),src.type());//创建的大小与src相同,类型与src相同
Mat m5=Mat::zeros(Size(512,512),CV_8UC3);
Mat m6=Mat::ones(Size(512,512),CV_8UC3);
Mat m7(600,800,CV_8UC1);设置图像的高度是600,宽度是800,单通道
Mat m8(600,800,CV_8UC3);设置图像的高度是600,宽度是800,三通道

//c++11快速创建
Mat kernel=(Mat<char>(3,3)<<0,-1,0,
                            -1,5,-1,
                            0,-1,0)

1.创建与克隆

void Demo::mat_demo(Mat& img)
{
	Mat m1, m2;
	m1 = img.clone();
	img.copyTo(m2);
}

2.打印一个8*8的单通道的8位的无符号的数据0

	Mat m3 = Mat::zeros(Size(8, 8), CV_8UC1);
	std::cout << "width:" << m3.cols << endl;
	std::cout << "height:" << m3.rows << endl;
	std::cout << "channels:" << m3.channels() << endl;
	std::cout << m3 << endl;

3.打印一个8*8的三通道的8位的无符号的数据 0

	Mat m3 = Mat::zeros(Size(8, 8), CV_8UC3);
	std::cout << "width:" << m3.cols << endl;
	std::cout << "height:" << m3.rows << endl;
	std::cout << "channels:" << m3.channels() << endl;
	std::cout << m3 << endl;

4.打印一个8*8的单通道的8位的无符号的数据 1

	Mat m3 = Mat::ones(Size(8, 8), CV_8UC1);
	std::cout << "width:" << m3.cols << endl;
	std::cout << "height:" << m3.rows << endl;
	std::cout << "channels:" << m3.channels() << endl;
	std::cout << m3 << endl;

5.打印一个8*8的三通道的8位的无符号的数据 1

	Mat m3 = Mat::ones(Size(8, 8), CV_8UC3);
	std::cout << "width:" << m3.cols << endl;
	std::cout << "height:" << m3.rows << endl;
	std::cout << "channels:" << m3.channels() << endl;
	std::cout << m3 << endl;

6.给三个通道赋值

错误的赋值

	Mat m3 = Mat::zeros(Size(8, 8), CV_8UC3);
	m3 = 127;//这样赋值只能给第一个像素点赋值
	std::cout << "width:" << m3.cols << endl;
	std::cout << "height:" << m3.rows << endl;
	std::cout << "channels:" << m3.channels() << endl;
	std::cout << m3 << endl;

正确的赋值

	Mat m3 = Mat::zeros(Size(8, 8), CV_8UC3);
	m3 = Scalar(127, 127, 127);
	std::cout << "width:" << m3.cols << endl;
	std::cout << "height:" << m3.rows << endl;
	std::cout << "channels:" << m3.channels() << endl;
	std::cout << m3 << endl;

7.展示颜色

	Mat m3 = Mat::zeros(Size(200, 200), CV_8UC3);
	m3 = Scalar(0, 0, 127);//Blue 0,Green 0,Red 127->红色
	std::cout << "width:" << m3.cols << endl;
	std::cout << "height:" << m3.rows << endl;
	std::cout << "channels:" << m3.channels() << endl;
	imshow("m3", m3);

六. add/subtract/divide/multiply

1.标量的加减乘除形式

void Demo::operator_demo(Mat& img)
{
	Mat dst;
	dst = img + Scalar(100, 100, 100);// 直接+标量实现
	imshow("加操作", dst);
	dst = img - Scalar(100, 100, 100);// 直接-标量实现
	imshow("减操作", dst);
	dst = img / Scalar(2, 2, 2);// 直接/标量实现
	imshow("除操作", dst);

	Mat m = Mat::zeros(img.size(), img.type());
	m = Scalar(2, 2, 2);
	multiply(img, m, dst);
	imshow("乘操作", dst);
}

可以等价于 下面的

void Demo::operator_demo(Mat& img)
{
	Mat dst = Mat::zeros(img.size(), img.type());//创建一个与img大小相同的黑幕布
	Mat m = Mat::zeros(img.size(), img.type());//创建一个与img大小相同的黑幕布
	m = Scalar(100, 100, 100);//m的标量大小
	for (int row = 0; row < img.rows; row++)
	{
		for (int col = 0; col < img.cols; col++)
		{
			Vec3b p1 = img.at<Vec3b>(row, col);//提取每一个像素点
			Vec3b p2 = m.at<Vec3b>(row, col);//提取每一个像素点
			dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);//通道0处的相加
			dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);//通道1处的相加
			dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);//通道2处的相加
		}
	}
	imshow("dst", dst);
}
saturate_cast<uchar>() 数据的转型,如果数据大于255则一直是255,如果数据小于0,就是0

2.直接操作API

add
subtract
divide
multiply
    Mat dst = Mat::zeros(image.size(), image.type());
    Mat m = Mat::zeros(image.size(), image.type());
    m = Scalar(50, 50, 50);
    add(image, m, dst);//加法操作
    imshow("加法操作", dst);

    Mat dst = Mat::zeros(image.size(), image.type());
    Mat m = Mat::zeros(image.size(), image.type());
    m = Scalar(50, 50, 50);
    subtract(image, m, dst);//减法操作
    imshow("减法操作", dst);

    Mat dst = Mat::zeros(image.size(), image.type());
    Mat m = Mat::zeros(image.size(), image.type());
    m = Scalar(2, 2, 2);
    divide(image, m, dst);//除法操作
    imshow("除法操作", dst);

    Mat dst;
    Mat m = Mat::zeros(image.size(), image.type());//创建一个图像大小与之前相同,类型相同
    m = Scalar(2, 2, 2);
    multiply(image, m, dst);//乘法操作
    imshow("乘法操作", dst);

七.createTrackbar(滑动控件)

1.API介绍

快速创建一个滑动控件

createTrackbar
CV_EXPORTS int createTrackbar(const string& trackbarname, 
                              const string& winname,
                              int* value, 
                              int count,
                              TrackbarCallback onChange = 0,
                              void* userdata = 0);
//参数一、trackbarname:滑动空间的名称(滚动条的名字)
//参数二、winname:滑动空间用于依附的图像窗口的名称(滚动条用在什么窗口上)
//参数三、value:滑块位置一个初始值的,也就是告诉我们滑块最初位置在哪(以地址的形式)
//参数四、count:(滚动条的最大值)

//参数五、TrackbarCallback是回调函数(用来接收回调函数函数名),其定义如下:
//typedef void (CV_CDECL *TrackbarCallback)(int pos, void* userdata);
//int pos:它表示的是当前滑块所在的位置
//void* userdata:回调函数形参userdata的值就是通过createTrackbar()的形参userdata直接得到的

//参数六、用户传给回调函数的数据,用来处理轨迹条事件,默认值为0。(要强转成void*类型)

2.例子 


//回调函数只调用一次解决滑块一开始的状态
static void on_track(int b, void* userdata)//回调函数(传值50,img传给回调函数)
{
	Mat img = *((Mat*)userdata);
	Mat dst = Mat::zeros(img.size(), img.type());
	Mat m = Mat::zeros(img.size(), img.type());
	m = Scalar(b, b, b);
	add(img, m, dst);//开始的位置亮度是+50的
	imshow("亮度调整", dst);
}
void Demo::tracking_demo(Mat& img)
{
	namedWindow("亮度调整", WINDOW_AUTOSIZE);
    int lightness = 50;//滑动窗口的最开始的值是50
	createTrackbar("滚动条", "亮度调整", &lightness, 255, on_track, (void*)(&img));
	on_track(50,&img);//创建回调函数(50表示的是当前滑块所在的位置,img传给回调函数)
}
static void on_track(int b, void* userdata)//回调函数(传值50,img传给回调函数)
{
	Mat img = *((Mat*)userdata);
	Mat dst = Mat::zeros(img.size(), img.type());
	Mat m = Mat::zeros(img.size(), img.type());
	m = Scalar(b, b, b);
	subtract(img, m, dst);
	imshow("亮度对比度调整", dst);
}
static void on_contrast(int b, void* userdata)//回调函数(传值50,img传给回调函数)
{
	Mat img = *((Mat*)userdata);
	Mat dst = Mat::zeros(img.size(), img.type());
	Mat m = Mat::zeros(img.size(), img.type());
	m = Scalar(b, b, b);
	multiply(img,m,dst);
	imshow("亮度对比度调整", dst);
}
void Demo::tracking_demo(Mat& img)
{
	namedWindow("亮度对比度调整", WINDOW_AUTOSIZE);
	int lightness = 100;
	int contrast_value = 2;
	createTrackbar("亮度调整", "亮度对比度调整", &lightness, 255, on_track, (void*)(&img));
	createTrackbar("对比度调整", "亮度对比度调整", &contrast_value, 10, on_contrast, (void*)(&img));
	on_track(100,&img);//创建回调函数(传值1用于加亮度,img传给回调函数)
	on_contrast(2, &img);
}

八.addWeighted(图像比例混合)

1.API介绍

将两张相同大小,相同类型的图片融合的函数

addWeighted
void AddWeighted(const CvArr* src1, 
                 double alpha,
                 const CvArr* src2, 
                 double beta,
                 double gamma,                   
                 CvArr* dst 
                 int dtype=-1));

//第一个参数 src1,第一个原数组 类型是Mat
//第二个参数 alpha,第一个数组元素权重(第一个数组占图形的比重)
//第三个参数 src2,第二个原数组 类型是Mat
//第四个参数 beta,第二个数组元素权重(第二个数组占图形的比重)
//第五个参数 gamma,图1与图2混合后添加的数值,总和等于255以上就是纯白色了,加到权重总和上的标量值
//第六个参数 dst,输出图片 类型是Mat
//第七个参数 dtype,int类型的dtype, 输出阵列的可选深度,默认值-1。当两个输入数组具有相同的深度时,这个参数设置为-1 (默认值)

// dst = src1[I] * alpha + src2[I] * beta + gamma

2.例子 

static void on_lightness(int b, void* userdata)
{
	Mat image = *((Mat*)userdata);
	Mat dst = Mat::zeros(image.size(), image.type());
	Mat m = Mat::zeros(image.size(), image.type());
	addWeighted(image, 1.0, m, 0, b, dst);//比值权重image*1.0+m*0+b
	imshow("亮度调整对比度调整", dst);
}

static void on_contrast(int b, void* userdata)
{
	Mat image = *((Mat*)userdata);
	Mat dst = Mat::zeros(image.size(), image.type());
	Mat m = Mat::zeros(image.size(), image.type());
	double contrast = b / 100.0;
	addWeighted(image, contrast, m, 0.0, 0, dst);//比值权重image*b/100+m*0.0+b
	imshow("亮度调整对比度调整", dst);
}
void Demo::tracking_demo(Mat& image)
{
	namedWindow("亮度调整对比度调整", WINDOW_AUTOSIZE);
	int lightness = 50;
	int contrast_value = 100;
	createTrackbar("Value Bar:", "亮度调整对比度调整", &lightness, 100, on_lightness, (void*)(&image));
	createTrackbar("Contrast Bar:", "亮度调整对比度调整", &contrast_value, 200, on_contrast, (void*)(&image));
	on_contrast(100, &image);//这个函数调用是来显示最初的图片的样子
	on_lightness(100, &image);//这个函数调用是来显示最初的图片的样子
}

九.applyColorMap(伪色彩)

1.API介绍

伪色彩函数applyColorMap
void applyColorMap(InputArray src, OutputArray dst, InputArray userColor)
//第一个参数 源图像(灰度图或彩色图(CV_8UC1 or CV_8UC3))
//第二个参数 在源图像上进行色彩映射后的结果图像
//第三个参数 提供的色彩图代码值

/*       int colormap[] = 
        {
            COLORMAP_AUTUMN,
            COLORMAP_BONE,
            COLORMAP_JET,
            COLORMAP_WINTER,
            COLORMAP_RAINBOW,
            COLORMAP_OCEAN,
            COLORMAP_SUMMER,
            COLORMAP_SPRING,
            COLORMAP_COOL,
            COLORMAP_HSV,
            COLORMAP_PINK,
            COLORMAP_HOT,
            COLORMAP_PARULA,
            COLORMAP_MAGMA,
            COLORMAP_INFERNO,
            COLORMAP_PLASMA,
            COLORMAP_VIRIDIS,
            COLORMAP_CIVIDIS,
            COLORMAP_TWILIGHT,
            COLORMAP_TWILIGHT_SHIFTED,
        };
*/

2.例子  

void Demo::color_demo(Mat& img)
{
	int colormap[] = {
			COLORMAP_AUTUMN,
			COLORMAP_BONE,
			COLORMAP_JET,
			COLORMAP_WINTER,
			COLORMAP_RAINBOW,
			COLORMAP_OCEAN,
			COLORMAP_SUMMER,
			COLORMAP_SPRING,
			COLORMAP_COOL,
			COLORMAP_HSV,
			COLORMAP_PINK,
			COLORMAP_HOT,
			COLORMAP_PARULA,
			COLORMAP_MAGMA,
			COLORMAP_INFERNO,
			COLORMAP_PLASMA,
			COLORMAP_VIRIDIS,
			COLORMAP_CIVIDIS,
			COLORMAP_TWILIGHT,
			COLORMAP_TWILIGHT_SHIFTED,
	};
	Mat dst = Mat::zeros(img.size(), img.type());
	int index = 0;
	while (true)
	{
		int c = waitKey(100);
		if (c == 27) break;
		else
		{
            //图片每过1s变一个颜色
			applyColorMap(img, dst, colormap[index % 19]);
			index++;
			imshow("展示图片", dst);
			waitKey(1000);
		}
	}
}

十.rectangle和Rect(创建矩形框)

1.API介绍

绘制矩形Rect
绘制一个矩形框rectangle
Rect(x,y,width,height);
//x, y 为左上角坐标, width, height 则为长和宽。
void rectangle(Mat& img, 
               Point pt1,
               Point pt2,
               const Scalar& color, 
               int thickness=1, 
               int lineType=8, 
               int shift=0)
//第一个参数 绘制的图像Mat类型
//第二个参数 矩形的一个顶点
//第三个参数 矩形对角线上的另一个顶点
//第四个参数 矩形的颜色
//第五个参数 组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
//第六个参数 线条的类型 (默认取8),有没有锯齿LINE_4()、LINE_8()、LINE_AA(反锯齿)
//第七个参数 坐标点的小数点位数

2.例子  

Rect(100, 100, 80, 80)//等价于从Point(100,100)->point(180,180)的矩形
rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 0, 0), -1, 8, 0);//方式1
rectangle(m2, Point(20, 20), Point(100, 100), Scalar(0, 0, 255), -1, 8, 0);//方式2
	Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);
	Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);
	rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 0, 0), -1, LINE_8, 0);
	rectangle(m2, Point(120, 120), Point(200, 200), Scalar(0, 0, 255), -1, LINE_8, 0);
	imshow("m1", m1);
	imshow("m2", m2);

十一.逻辑运算符与或非

bitwise_or

bitwise_or(m1, m2, dst)

bitewise_and

bitwise_and(m1,m2,dst)

bitewise_not

bitwise_not(image,dst)

void Demo::bitwise_demo(Mat& img)
{
	Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);
	Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);
	rectangle(m1, Rect(100, 100, 80, 80), Scalar(100, 100, 100), -1, LINE_8, 0);
	rectangle(m2, Point(120, 120), Point(200, 200), Scalar(0, 0, 255), -1, LINE_8, 0);
	imshow("m1", m1);
	imshow("m2", m2);
	Mat dst_or = Mat::zeros(img.size(), img.type());//创建幕布
	Mat dst_and = Mat::zeros(img.size(), img.type());//创建幕布
	Mat dst_not = Mat::zeros(img.size(), img.type());//创建幕布
	bitwise_or(m1, m2, dst_or);//与
	bitwise_and(m1, m2, dst_and);//或
	bitwise_not(m1, dst_not);//非
	imshow("or", dst_or);
	imshow("and", dst_and);
	imshow("not", dst_not);
}

十二.split和merge(图像通道分离)

一个图是基于红色通道,绿色通道,蓝色通道

通道分离

split

通道合并

merge
void Demo::channels_demo(Mat& img)
{
	vector<Mat> mv;
	split(img, mv);
	imshow("blue", mv[0]);// mv[0]等效于mv.at(0)
	imshow("green", mv[1]);
	imshow("red", mv[2]);
}
void Demo::channels_demo(Mat& img)
{
	vector<Mat> mv;
	split(img, mv);
	imshow("blue", mv[0]);
	imshow("green", mv[1]);
	imshow("red", mv[2]);

	Mat dst;
	mv[1] = 0;//消除掉绿色
	mv[2] = 0;//消除掉红色
	merge(mv, dst);//合并起来
	imshow("蓝色", dst);
}

十三.mixChannels(图像通道混合)

//用法1
void cv::mixChannels    (    
        InputArrayOfArrays src,
        InputOutputArrayOfArrays dst,
        const std::vector<int> & fromTo 
)    
//第一个参数 原图像类型Mat
//第二个参数 混合后的目标图像
//第三个参数 数组类型的fromTo     
//int from_to[] = { 0,2,1,1,2,0 };//第0个通道跑到第2个通道里面去
                                  //第1个通道跑到第1个通道里面去
                                  //第2个通道跑到第0个通道里面去

//用法2
void cv::mixChannels    
(    
        const Mat *src,//输入矩阵
        size_t nsrcs,//输入矩阵的数量
        Mat *dst,  //输出矩阵
        size_t ndsts, //输出矩阵的数量
        const int *fromTo,//复制列表fromto
        size_t  npairs //复制列表的数量
)    
//方法1
vector<int>from_to = {0,2,1,1,2,0};
                                    //第0个通道跑到第2个通道里面去
									//第1个通道跑到第1个通道里面去
									//第2个通道跑到第0个通道里面去
mixChannels(img, dst, from_to);//从哪里到哪里,几对交换



//方法2
int from_to[] = {0,2,1,1,2,0};
                                //第0个通道跑到第2个通道里面去
							    //第1个通道跑到第1个通道里面去
								//第2个通道跑到第0个通道里面去
mixChannels(&img, 1, &dst, 1,from_to,3);//从哪里到哪里,几对交换
        Mat m(500, 500, CV_8UC3, Scalar(255, 255, 0));
        Mat m2(500, 500, CV_8UC3);
        vector<Mat> channels;
        split(m, channels);
        imshow("m", m);  //原图m为青色
        imshow("0", channels.at(0));//分离出蓝色通道的 255白色
        imshow("1", channels.at(1));//分理处绿色通道的 255白色
        imshow("2", channels.at(2));//分理处红色通道的  0黑色
    
        vector<int> fromTo = {0,2,1,1,2,0}; //更改的通道
        mixChannels(m,1 m2,1,fromTo);
        vector<Mat> channels2;
        split(m2, channels2);//分离通道
        imshow("/m", m2);
        imshow("/0", channels2.at(0));//分离蓝色通道的 0黑色 
        imshow("/1", channels2.at(1));//分离绿色通道的 255白色
        imshow("/2", channels2.at(2));//分离红色通道的 255白色
        waitKey(0);

              

十四. inRange(指定空间色彩提取)

        inRange()函数可实现二值化功能,可以同时针对多通道进行操作,使用起来非常方便。主要是将在两个阈值内的像素值设置为白色(255),而不在阈值区间内的像素值设置为黑色(0)。

指定空间色彩提取inRange
//该函数输出的dst是一幅二值化之后的图像    
void inRange(InputArray src,   //输入要处理的图像,可以为单通道或多通道。
                 InputArray lowerb,//包含下边界的数组或标量。
                 InputArray upperb, //包含上边界数组或标量。
                 OutputArray dst); //输出图像,与输入图像src 尺寸相同且为CV_8U 类型。

举例

void Demo::inrange_demo(Mat& img)
{
	Mat hsv;
	cvtColor(img, hsv, COLOR_BGR2HSV);//转换成HSV
	Mat dst;
	inRange(hsv, Scalar(0, 0, 221), Scalar(150, 30, 255), dst);//扣出颜色是白色
	imshow("抠出白色的", dst);//其他颜色不保留,只保留白色,其他颜色用黑色保留
}
void Demo::inrange_demo(Mat& img)
{
	Mat hsv;
	cvtColor(img, hsv, COLOR_BGR2HSV);//转换成HSV
	Mat dst;
	inRange(hsv, Scalar(0, 0, 221), Scalar(150, 30, 255), dst);//扣出颜色是白色的
	imshow("抠出白色的", dst);//其他颜色不保留

	Mat redback = Mat::zeros(img.size(), img.type());
	redback = Scalar(0, 0, 255);
	bitwise_not(dst, dst);//将所有的颜色取反,白色变成黑色
	imshow("取反", dst);
	img.copyTo(redback, dst);
	//将img拷贝到redback中,且image对应mask中像素值为0的像素点都不会贴到redback上。
	imshow("成品", redback);
}

十五.minMaxLoc(计算最大最小值)

void minMaxLoc(InputArray src,   //输入的数组,若是图像,需为单通道图像。
               double* minVal,   //返回最小值的指针。若无需返回,此值设为 NULL。
               double* maxVal = 0, //返回最大值的指针。若无需返回,此值设为 NULL。
               Point* minLoc = 0, //返回最小值位置的指针(二维情况下),无需返回,此值设为NULL。
               Point* maxLoc = 0, //返回最大值位置的指针(二维情况下),无需返回,此值设为NULL。
               InputArray mask = noArray());
                //可选的掩膜操作,非零掩码元素用于标记待统计元素,需要与输入图像集有相同尺寸。
void Demo::static_demo(Mat& img)
{
	double minv, maxv;
	Point minLoc;//最小值地址 point点坐标类型
	Point maxLoc;//最大值地址 point点坐标类型
	vector<Mat> mv;
	split(img, mv);//分离通道mv[0]  mv[1]  mv[2]从三通道变成单通道
 	for (int i = 0; i < mv.size(); i++)
	{
		minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());
		cout << "No.channels:" << i 
			<< " min value:" << minv 
			<< "max value:" << maxv << std::endl;
	}
}

十六.meanStdDev(计算均值和标准方差)

void meanStdDev(InputArray src, //src输入数组,由1-4个通道组成,能够把结果存储到Scalar里
                OutputArray mean, //mean 输出参数,计算平均值
                OutputArray stddev,//stddev 输出参数,计算出的标准差
                InputArray mask=noArray());//mask可选参数,操作掩摸,用以标记求取哪些区域。
	Mat mean, stddev;
	meanStdDev(img, mean, stddev,Mat());//mean是均值,stddev是方差
	std::cout << "mean:" << mean << std::endl;
	std::cout << "stddev:" << stddev << std::endl;

十七.rectangle(矩形)/circle(圆)/line(线)/ellipse(椭圆)

1.坐标系

2.Rect

Rect(x,y,width,height);
//x, y 为左上角坐标, width, height 则为长和宽。

//等价于
Rect rect;//定义矩形  定义坐标是左上角
rect.x = 200;
rect.y = 200;
rect.width = 100;
rect.height = 100;
Rect(200,200,100,100);

3.rectangle 

void rectangle(Mat& img, 
               Point pt1,
               Point pt2,
               const Scalar& color, 
               int thickness=1, 
               int lineType=8, 
               int shift=0)
//第一个参数 绘制的图像Mat类型
//第二个参数 矩形的一个顶点
//第三个参数 矩形对角线上的另一个顶点
//第四个参数 矩形的颜色
//第五个参数 组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
//第六个参数 线条的类型 (默认取8),有没有锯齿LINE_4()、LINE_8()、LINE_AA(反锯齿)
//第七个参数 坐标点的小数点位数
rectangle(bg, Rect(200, 200, 100, 100), Scalar(255, 0, 0), -1, LINE_8, 0);

Rect rect;
rect.x = 100;
rect.y = 100;
rect.width = 100;
rect.height = 100;
rectangle(bg, rect, Scalar(0, 255, 0), -1, LINE_8, 0);

4.circle

circle(cv::InputOutputArray img, //画圆的图像Mat类型
       cv::Point center,  //圆的圆心Point类型
       int radius,       //圆的半径
       const cv::Scalar&color,//圆的颜色
       int thickness=1,   //如果为整数,表示圆轮廓的厚度;如果为负数,表示要绘制一个填充的圆
       int lineType =8 //圆形边界的类型
       int shift =0)//位移中心坐标和半径值的小数位数
circle(bg, Point(50, 50), 50, Scalar(0, 0, 255), -1, LINE_8, 0);
//圆心坐标(50,50),半径50,颜色红色,填充,边缘LINE_8,0

5.line

CV_EXPORTS_W void line(InputOutputArray img, //要绘制线段的图像
						Point pt1, //线段的起点
						Point pt2, //线段的终点
						const Scalar& color, //颜色
						int thickness = 1, //线条的宽度
						int lineType = LINE_8, //线条类型
						int shift = 0)//坐标点小数点位数
line(bg, Point(160, 60), Point(200, 60), Scalar(0, 0, 255), 2, LINE_AA, 0);

6.ellipse

void ellipse(cv::InputOutputArray img, 
             const cv.:RotatedRect &box, //RotatedRect类型
             const cv.:Scalar &color, 
             int thickness = 1, 
             int lineType =img: lmage)
void cv::ellipse(		InputOutputArray    img,    //要绘制的图像
                        Point 	            center, //圆心
                        Size 	            axes,   //轴的长度
                        double 	            angle,  //偏转的角度
                        double 	            startAngle,//圆弧起始角的角度
                        double 	            endAngle, //圆弧终结角的角度
                        const Scalar & 	    color,    //颜色
                        int 	            thickness = 1, //线宽
                        int 	            lineType = LINE_8,//线的类型
                        int 	            shift = 0 //小数位数
                )	
RotatedRect rrt;
rrt.center = Point(150, 150);//椭圆的圆心
rrt.size = Size(200, 200);//弧度的高低,x轴方向的长度,y轴方向的长度
rrt.angle = 0.0;
ellipse(bg, rrt, Scalar(255, 0, 0), 1,LINE_8);

ellipse(bg, Point(150, 150), Size(100, 50), 0.0, 0.0, 360.0, Scalar(255, 0, 0), 1, LINE_8, 0);

十八.polylines多边形图像绘制

void polylines(Mat& img, //在img表示的图像上绘制
               const Point** pts, //是指向多边形数组的指针,必须是const修饰的
               const int* npts, //是多边形顶点个数的数组名
               int ncontours, //绘制多边形的个数
               bool isClosed, //表示多边形是否闭合,1表示闭合,0表示不闭合
               const Scalar& color, //颜色
               int thickness=1, 
               int lineType=8, 
               int shift=0 );		
void Demo::polyline_demo(Mat& img)
{
	Mat canvas = Mat::zeros(Size(500, 500), CV_8UC3);
	Point p1(50, 25);
	Point p2(37, 75);
	Point p3(75, 50);
	Point p4(25, 50);
	Point p5(63, 75);
	Point p6(50, 25);
	std::vector<Point> pts;
	pts.push_back(p1);
	pts.push_back(p2);
	pts.push_back(p3);
	pts.push_back(p4);
	pts.push_back(p5);
	pts.push_back(p6);
	polylines(canvas, pts, true, Scalar(0, 255, 0), 1, LINE_8, 0);//依次链接的,不能填充
	imshow("绘制图像", canvas);
}
//创建一个二维数组,每一行存储一个多边形的点,总共存储了两个多边形的点
Point p[2][5] = 
{{Point(100, 100),Point(150, 50),Point(180, 90),Point(10, 190),Point(200, 267)},
{Point(360, 410), Point(700, 650), Point(334,456), Point(531, 463), Point(384, 634)}};

const Point *pp[] ={p[0], p[1]};//这个指针数组存储每一个多边形的定点所在的一维数组的地址
int n[] = {5, 5};//这个数组存储每一个多边形的定点个数
polylines(src, pp, n, 2, 1, Scalar(255, 255, 0), 1);//绘制两个不填充的多边形

十九.fillPoly多边形图像填充

void fillPoly(Mat& img,   //在img表示的图像上绘制
              const Point** pts, //是指向多边形数组的指针,必须是const修饰的
              const int* npts, //是多边形顶点个数的数组名
              int ncontours, //是绘制多边形的个数
              const Scalar& color, //颜色
              int lineType=8, 
              int shift=0,
              Point offset=Point() );
void QuickDemo::polyline_drawing_demp(Mat& image)
{
        Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);//绘制底图
        Point p1(100, 100);//找多边形的五个点
        Point p2(50, 125);
        Point p3(75, 150);
        Point p4(125, 150);
        Point p5(150, 125);
        std::vector<Point> pts;
        pts.push_back(p1);
        pts.push_back(p2);
        pts.push_back(p3); 
        pts.push_back(p4);
        pts.push_back(p5);
    
        fillPoly(canvas, pts, Scalar(0, 0, 255), 8, 0);//填充
        imshow("绘制图像", canvas);
}

二十.drawContours绘制与填充

void drawContours(InputOutputArray image, //image表示目标图像
                  InputArrayOfArrays contours, //输入的轮廓组,每一组轮廓由点vector构成,
                  int contourIdx, //指明画第几个轮廓,如果该参数为负值,则画全部轮廓
                  const Scalar& color, //color为轮廓的颜色
                  int thickness=1, //轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部
                  int lineType=8, //线型
                  InputArray hierarchy=noArray(), //轮廓结构信息
                  int maxLevel=INT_MAX, 
                  Point offset=Point() )

Point p1(100, 100);
	Point p2(50, 125);
	Point p3(75, 150);
	Point p4(125, 150);
	Point p5(150, 125);
	std::vector<Point> pts;
	pts.push_back(p1);
	pts.push_back(p2);
	pts.push_back(p3);
	pts.push_back(p4);
	pts.push_back(p5);
	vector<vector<Point>> contours;
	contours.push_back(pts);//插入一个点集
	//contours可以绘制无穷个多边形,里面存放每一个多边形的点集
	drawContours(canvas, contours, -1, Scalar(0, 0, 255), -1);
	//第一个0代表绘制vector第几个 0 ,1,2...如果是-1就是全绘制    
	imshow("绘制图像", canvas);

二十一.rng.uniform产生随机数

rng.uniform(1, 3);     //在[1,3)区间,随机生成一个整数
void QuickDemo::random_drawing_demo(Mat& image)
{
        Mat canvas = Mat::zeros(Size(512,512),CV_8UC3);//绘制底图
        int w = canvas.cols;//宽度
        int h = canvas.rows;//高度
        RNG rng(12345);//构造方法设定一个具体值,表示下面代码每次生成的结果都是一样的
        while (true) {
            int c = waitKey(10);
            if (c == 27) {
                break;
            }
            int x1 = rng.uniform(0, w);//坐标点的范围
            int y1 = rng.uniform(0, h);//坐标点的范围
            int x2 = rng.uniform(0, w);//坐标点的范围
            int y2 = rng.uniform(0, h);//坐标点的范围
    
            int b = rng.uniform(0, 255);//0-255上的随机颜色
            int g = rng.uniform(0, 255);//0-255上的随机颜色
            int r = rng.uniform(0, 255);//0-255上的随机颜色
            line(canvas, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 1, 8, 0);//产生线
            imshow("绘制演示", canvas);
        }
}

二十二.setMouseCallback(鼠标绘制)

 void setMousecallback(const string& winname, //winname:窗口的名字
                       MouseCallback onMouse, 
//onMouse:鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 
//这个函数的原型应该为:void on_Mouse(int event, int x, int y, int flags, void* param);
                       void* userdata=0)//userdate:传给回调函数的参数 

void on_Mouse(int event, int x, int y, int flags, void* param);
event是 CV_EVENT_*变量之一
x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系) 
flags是CV_EVENT_FLAG的组合, param是用户定义的传递到setMouseCallback函数调用的参数。
    
附常用的event:
EVENT_MOUSEMOVE  //鼠标移动
EVENT_LBUTTONDOWN //左键按下
EVENT_RBUTTONDOWN //右键按下
EVENT_LBUTTONUP   //左键松
EVENT_RBUTTONUP   //右键松

    
Point sp(-1, -1);//初始位置
Point ep(-1, -1);//结束位置
Mat tmp;
static void on_draw(int event, int x, int y, int flags, void* param)
{
	Mat img = *((Mat*)param);
	if (event == EVENT_LBUTTONDOWN)//如果鼠标第一个事件(按下)
	{
		sp.x = x;
		sp.y = y;
		std::cout << "start point:" << sp << std::endl;//显示初始的位置
	}
	else if (event == EVENT_LBUTTONUP)//鼠标松开(结束的位置)
	{

			ep.x = x;
			ep.y = y;
			int dx = ep.x - sp.x;//开始到结束的x轴距离
			int dy = ep.y - sp.y;//开始到结束的y轴距离
			if (dx > 0 && dy > 0)
			{
				Rect rect(sp.x, sp.y, dx, dy);//绘制一个矩形框
				rectangle(img, rect, Scalar(0, 0, 255), 1, 8, 0);
				imshow("ROI区域", img(rect));//将图形小窗口展示
			}
			sp.x = -1;//回归(-1,-1)
			sp.y = -1;//回归(-1,-1)
	}
	else if (event == EVENT_MOUSEMOVE)//显示鼠标移动(每次移动前都要去擦除前面哪个状态)
	{
		if (sp.x > 0 && sp.y > 0)//必须是大于0才能去绘制,否则就一直在绘制
		{
			ep.x = x;
			ep.y = y;
			int dx = ep.x - sp.x;//开始到结束的x轴距离
			int dy = ep.y - sp.y;//开始到结束的y轴距离
			if (dx > 0 && dy > 0)
			{
				tmp.copyTo(img);//绘制一个就要将前一个状态拷贝下来
				Rect rect(sp.x, sp.y, dx, dy);//绘制一个矩形框
				rectangle(img, rect, Scalar(0, 0, 255), 1, 8, 0);
				imshow("鼠标绘制", img);
			}
		}
	}
}
void Demo::mouse_demo(Mat& img)
{
	namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
	setMouseCallback("鼠标绘制", on_draw, (void*)&img);
	imshow("鼠标绘制", img);
	tmp = img.clone();
}

二十二.convertTo(缩放并转换到另外一种数据类型)

src.convertTo(dst, type, scale, shift)
//第一个参数 目的矩阵
//第二个参数 需要的输出矩阵类型,或者更明确的,是输出矩阵的深度,如果是负值(常用-1)则输出矩阵和输入矩阵类型相同;
//第三个参数 比例因子
//第四个参数 将输入数组元素按比例缩放后添加的值
//CV_8UC3转为CV_32FC3
Mat dst;
img.convertTo(dst, CV_32F);//将img转化成32位的浮点型
cout << img.type() << endl;
cout << dst.type() << endl;

二十三.normalize归一化函数

NORM_L1   //L1归一化
//sum(numbers)=20.0
// 2.0   0.1    (2.0/20.0)
// 8.0   0.4    (8.0/20.0)
// 10.0  0.5    (10.0/20.0)  

NORM_L2   //L2,单位向量为1
// Norm to unit vector: ||positiveData||=1.0
// 2.0   0.15  
// 8.0   0.62
// 10.0  0.77

NORM_MINMAX    //根据delta=max-min
//Norm to range [0.0;1.0]  根据2-10区间的位置
// 2.0   0.0    (2的位置是左边界)
// 8.0   0.75   (6.0/8.0)
// 10.0  1.0    (10的位置是右边界)

NORM_INF  //根据最大值
// 2.0   0.2    (2.0/10)
// 8.0   0.8    (8.0/10)
// 10.0  1.0    (10.0/10)

void cv::normalize(InputArray  src,    //输入矩阵
                   InputOutputArray  dst,//输出矩阵,与输入矩阵尺寸相同
                   double  alpha = 1,
//norm_type为NORM_MINMAX,则alpha为最小值或最大值;如果norm_type为其他类型,则为归一化要乘的系数
                   double  beta = 0,
//norm_type为NORM_MINMAX,则beta为最小值或最大值;如果norm_type为其他类型,beta被忽略,此处不会被用到,一般传入0
                   int  norm_type = NORM_L2,
//归一化类型,常见的有NORM_L1,NORM_L2,NORM_INF,NORM_MINMAX
                   int  dtype = -1,
//如果取负值时,dst与src同样的类型;否则,dst和src有同样的通道数,且此时图像深度为CV_MAT_DEPTH(dtype)
                   InputArray  mask = noArray())//可选操作掩膜
void Demo::norm_demo(Mat& img)
{
	Mat dst;
	cout << img.type() << endl;
	img.convertTo(img, CV_32F);//将img转化成32位的浮点型
	cout << img.type() << endl;
	normalize(img, dst, 1.0, 0, NORM_MINMAX);
	cout << dst.type() << endl;
	imshow("图像归一化", img);
}

二十四.resize放缩和插值

resize(InputArray src, //输入,原图像,即待改变大小的图像;
       OutputArray dst, //输出,改变后的图像。
       Size dsize, //输出图像的大小,Size类型
       double fx=0, //width方向的缩放比例,为0就按照src.cols
       double fy=0, //height方向的缩放比例,为0就按照src.rows来计算
       int interpolation=INTER_LINEAR )//这个是指定插值的方式
                    
                     //INTER_NEAREST   最邻近插值
                     //INTER_LINEAR    线性插值,如果最后一个参数你不指定,默认使用这种方法
                     //INTER_CUBIC     4x4像素邻域内的双立方插值
                     //INTER_LANCZOS4  8x8像素邻域内的Lanczos插值
void QuickDemo::resize_demo(Mat& image)
{
        Mat zoomin, zoomout;
        int h = image.rows;
        int w = image.cols;
        resize(image, zoomin, Size(w / 2, h / 2), 0, 0, INTER_LINEAR);//线性插值
        imshow("zoomin", zoomin);
        resize(image, zoomout, Size(w * 2, h * 2), 0, 0, INTER_LINEAR);
        imshow("zoomout", zoomout);
}

二十五.flip图像的翻转

CV_EXPORTS_W void flip(InputArray src, OutputArray dst, int flipCode);
//第一个参数 原来的图像
//第二个参数 结果图像
//第三个参数 参数flipCode一个标志,决定怎么翻转矩阵; 0是围绕着x轴翻转,正值是围绕着y轴翻转,负值是围绕着两个轴一起翻转。
void QuickDemo::flip_demo(Mat& image)
{
        Mat dst;
        flip(image, dst, 0);//0是上下反转
        flip(image, dst, 1);//1是左右翻转
        flip(image, dst, -1);//-1是180°反转
        imshow("反转图像", dst);
}

二十六.warpAffine旋转和平移

void warpAffine(InputArray src, //原来的图像
                OutputArray dst, //得到的图像
                InputArray M, //仿射变换
                Size dsize, //大小
                int flags=INTER_LINEAR, //插值的方式(默认线性插值)
                int borderMode=BORDER_CONSTANT, //边缘处理
                const Scalar& borderValue=Scalar())//底色

void QuickDemo::rotate_demo(Mat& image)
{
        Mat dst, M;
        int w = image.cols;
        int h = image.rows;
        M = getRotationMatrix2D(Point2f(w / 2, h / 2), 45, 1.0);
        warpAffine(image, dst, M, image.size(),INTER_LINEAR,0,Scalar(255,0,0));
        imshow("旋转演示", dst);
}

二十七.capture摄像头处理

方法cv::VideoCapture capture(const string& filename);  // 从视频文件读取 
例程cv::VideoCapture capture("C:/Users/DADA/DATA/gogo.avi");  // 从视频文件读取 
void QuickDemo::Quick_video(Mat& image)
{
        VideoCapture capture(0);//视频捕捉设备 id ---笔记本电脑的用0
        Mat frame;
        while (true)
        {
            capture.read(frame);
            if (frame.empty())
            {
                break;
            }
            imshow("frame", frame);
            int c = waitKey(10);
            if (c == 27)
            {
                break;
            }
    
        }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值