C/C++ vs2017 OpenCV简单入门

article/2025/9/28 1:06:04

 离职之际,自学一下图像相关的知识点,只是简单学了一点皮毛!


目录

一、 OpenCV环境搭建

二、使用opencv

常用接口说明

使用案例

1. 图像色彩空间转换

2. Mat对象的创建与赋值

3. 图像像素的读写操作

4. 图像像素的算术操作

5. 滚动条操作演示

6. 键盘响应操作

7. OpenCV自带颜色表操作

8. 图像像素的逻辑操作

9. 通道分离与合并

10. 图像色彩空间转换

11. 图像像素值统计 

12. 图像几何形状绘制

13. 随机数与随机颜色 

14. 多边形填充与绘制

15. 鼠标操作与响应

16. 图像像素类型转换与归一化

17. 图像缩放与插值

18. 图像翻转

19. 图像旋转

20. 视频文件摄像头使用

21. 图像卷积操作

22. 高斯模糊 

23. 高斯双边模糊

三、键盘操作小demo

1. 键盘小demo

2. 旋转、缩放、裁剪、平移案例

3. 往图片中写入中文文字

四、总结


一、 OpenCV环境搭建

官网下载链接:Releases - OpenCV

 下载后双击开始解压安装

 

解压完毕 

 进入路径 D:\opencv\opencv\build\x64\vc14\bin

 vs2019及其以上的版本可以选择vc15那个文件夹

 拷贝该路径,设置环境变量

在路径D:\opencv\opencv\build\x64\vc14\lib 会有项目中需要使用到的lib

新建一个VS工程,

右键 属性 - VC++目录 - 包含库目录,添加头文件路径进来

 右键 属性 - VC++目录 - 库目录,添加lib文件路径进行

 右键 属性 - 链接器 - 输入 - 附加依赖项,将opencv_world460d.lib添加进来,如果是release项目,那么就添加opencv_world460.lib

 注意,属性中的“配置”和“平台”需要和界面的保持一致

当然,上面添加目录和库目录的操作,可以将相应的头文件和库拷贝到项目路径,再添加项目路径进来即可!

编写如下代码测试环境:

#include <opencv2/opencv.hpp>#include <iostream>
#include <stdio.h>using namespace cv;void int test1(Mat src) {// 设置新的窗体标题,参数一窗体标题,参数二窗体随图片大小namedWindow("opencv窗口2", WINDOW_AUTOSIZE);Mat output_image;/* 设置图片颜色 */cvtColor(src, output_image, COLOR_BGRA2RGB);imshow("opencv窗口2", output_image);/* 保存图片到本地 */imwrite("D:/new.png", output_image);// 等待waitKey(0);
}int main(void) {// 正常:IMREAD_COLOR// 灰度:IMREAD_GRAYSCALEMat image = imread("图.jpeg", IMREAD_COLOR);    // 读取一张图片if (image.empty()) {        // 判断图片是否读取成功printf("path image NULL!\n");return -1;}// 显示图片    参数一是窗体标题,参数二图片对象imshow("原图", image);test1(image);return 0;
}

编译运行,不出意外的话,就会显示两张我们指定路径读取的图片

 左边那一种是修改颜色后的图片,右边是原图!

至此,环境搭建完毕!


二、使用opencv

常用接口说明

1. imread

Mat image = imread("图.jpeg", IMREAD_COLOR);

        解析:读取一张图片。

2. image.empty()

        解析:判断文件是否读取成功,ture表示不成功,false表示成功。

3. imshow

imshow("opencv窗口2", output_image);

        解析:显示一张图片,参数一是窗体名字,参数二是图片对象,也就是Mat对象

4. imwrite

imwrite("D:/new.png", output_image);

        解析:将图像保存到本地。参数一是文件路径名,参数二是图片对象。

5. waitKey

int waitKey(int delay = 0);

        解析:等待,相当于c/c++中的system("pause"); 参数为0,表示一直等待,其他大于零的数,则表示等待对应的秒数。
        

6. destroyAllWindows

void destroyAllWindows();

        解析:销毁所有打开的窗体。

7. cvtColor

void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );

        解析:设置图像的颜色。参数一是输入图像对象,参数二是设置好输出的图像对象,参数三是设置图像颜色枚举(enum ColorConversionCodes)

8. clone

Mat src = image.clone()

        解析:将图像对象克隆赋值,需要另一个Mat对象去接收,相当于深拷贝。

8. copyTo

Mat m2;
image.copyTo(m2)

        解析:将图像对象拷贝给另一个图像对象,相当于深拷贝。

9. zeros

Mat m4 = Mat::zeros(Size(128, 128), CV_8UC3);

        解析:创建空白图像。参数一是图像大小,参数二表示通道数。

10. Scalar

m4 = Scalar(255, 255, 0);

        解析:给图像设置颜色。因为是给三个通道的图像设置颜色,所以这里使用三个参数;如果是给单通道设置颜色,则设置一个参数即可。

11. cols

int width = m4.cols;

        解析:获取图像的宽度。

12. rows

int height = m4.rows;

        解析:获取图像的高度。

13. channels

int channels = m4.channels();

        解析:获取通向的通道数。单通道表示灰色图像,三通道表示彩色图像。

14. add

add(image, m1, dst1);

        解析:图像的像素相加。参数一和参数二是输入图像,参数三是输出图像。也就是将参数一和参数二的像素相加后输出到参数三。

15. subtract

subtract(image, m2, dst2);

        解析:图像的像素相减。参数一和参数二是输入图像,参数三是输出图像。也就是将参数一和参数二的像素相减后输出到参数三。

16. multiply

multiply(image, m3, dst3);

        解析:图像的像素相乘。参数一和参数二是输入图像,参数三是输出图像。也就是将参数一和参数二的像素相乘后输出到参数三。

17. divide

divide(image, m4, dst4);

         解析:图像的像素相除。参数一和参数二是输入图像,参数三是输出图像。也就是将参数一和参数二的像素相除后输出到参数三。

18. waitKey

 int c = waitKey(100);

        解析:等待键盘输入,如果参数设置的毫秒数结束后还没有键盘输入,则默认输入-1,结束等待。

19. applyColorMap 

applyColorMap(image, dst, COLORMAP_COOL);

        解析:设置图像彩色映射。参数一是输入图像,参数二是输出图像,参数三是映射的颜色类型,他是枚举enum ColormapTypes。

        

20. bitwise_and  

bitwise_and(m1, m2, dst1);

        解析:图像像素逻辑操作。参数一和参数二是输入图像,参数三是输出图像。

21. bitwise_or

bitwise_or(m1, m2, dst2);

        解析:图像像素逻辑操作。参数一和参数二是输入图像,参数三是输出图像。

22. bitwise_not

bitwise_not(image, dst3);

        解析:图像像素取反操作。参数一是输入图像,参数二是输出图像。

23. bitwise_xor

bitwise_xor(m1, m2, dst4);

        解析:图像像素逻辑异或操作。参数一和参数二是输入图像,参数三是输出图像。

24. split

std::vector<Mat> mv;
split(image, mv);

        解析:通道分离。

25. rectangle

rectangle(dst1, rect, Scalar(0, 255, 255), 2, 8, 0);

        解析:绘制一个矩形。参数一是输出图像,参数二是矩形对象,参数三是颜色,参数四是边框厚度,参数五是反锯齿(可以使用LINE_AA效果更加),参数六不清楚。

        如果是需要填充,则将参数四传入-1。

26. circle

circle(dst1, Point(300, 400), 30, Scalar(255, 0, 255), 2, 8, 0);

        解析:绘制一个圆形。参数一是输出图像,参数二是圆的中心位置,参数三是圆的半径,参数四是颜色,参数五是边框厚度,参数六是反锯齿(可以使用LINE_AA效果更加),参数七不清楚。

        如果是需要填充,则将参数五传入-1。

27. line

line(dst5, Point(100, 130), Point(300, 400), Scalar(255, 0, 0), 2, 8, 0);

        解析:绘制一条线。参数一是输入输出图像, 参数二是第一个点位置,参数三是第二个点位置,参数四是颜色,参数五是线的宽度,参数六是反锯齿,参数七不清楚。

28. RNG

RNG rng((unsigned)time(NULL));    // 用系统时间作为种子初始化rng,要用到time.h库
int b = rng.uniform(0, 255);    // 随机生成 0 - 255

        解析:opencv的随机函数。

29. drawContours

drawContours(canvas, contours, 0, Scalar(255, 0, 0), -1);

        解析:绘制多边形或者填充多边形。参数一是输入输出图像,参数二是std::vector<std::vector<Point>>类型对象,参数三指定绘制容器中指定数据的第几个(-1表示全都绘制),最后一个参数为多边形的边框(-1表示填充)

30. resize

resize(image, zoomin, Size(w / 2, h / 2));

        解析:图像缩放。参数一是输入图像,参数二是输出图像,参数三是重新设置的图像大小。

31. flip

// 上下翻转
flip(image, dst, 0);// 左右翻转
flip(image, dst, 1);// 先左右翻转再上下翻转
flip(image, dst, -1);

        解析:图像翻转。参数一是输入图像,参数二是输出图像,参数三0表示上下翻转,1表示左右翻转,-1表示先左右翻转再上下翻转。

使用案例

以下函数的参数都基于此读取的图像对象:

int main(void) {// 正常:IMREAD_COLOR// 灰度:IMREAD_GRAYSCALEMat image = imread("图.jpeg", IMREAD_COLOR);if (image.empty()) {printf("path image NULL!\n");return -1;}imshow("原图", image);waitKey(0);destroyAllWindows();return 0;
}

1. 图像色彩空间转换

/* 图像色彩空间转换 */
void colorSpace_Demo(Mat &image) {Mat gray, hsv;cvtColor(image, hsv, COLOR_BGR2HSV);cvtColor(image, gray, COLOR_BGR2GRAY);	// 灰度图像imshow("HSV", hsv);imshow("灰度", gray);imwrite("HSV.png", hsv);imwrite("GRAY.png", gray);
}

运行截图

2. Mat对象的创建与赋值

/* Mat对象的创建与赋值 */
void mat_creation_demo(Mat &image) {Mat m1, m2, m3;// 克隆m1 = image.clone();		// 深拷贝// 拷贝image.copyTo(m2);		// 深拷贝// 赋值m3 = image;				// 浅拷贝// 创建空白图像//Mat m4 = Mat::zeros(Size(8, 8), CV_8UC1);		// 创建一通道Mat m4 = Mat::zeros(Size(128, 128), CV_8UC3);	// 最后的数字表示通道数// 给通道赋值(相当于设置颜色)m4 = Scalar(123, 200, 100);	// 因为是3通道,所以赋三个值;如果是一通道,给一个参数值即可//std::cout << m4 << std::endl;imshow("m4", m4);// 图像的宽int width = m4.cols;// 图像的高int height = m4.rows;// 图像的通道数int channels = m4.channels();printf("width = %d\theight = %d\tchannels = %d\n", width, height, channels);// C++11新出的创建空白图像方法Mat kernel = (Mat_<char>(3, 3) <<0, -1, 0,-1, 5, -1,0, -1, 0);kernel = Scalar(50, 100, 150);imshow("kernel", kernel);
}

运行截图

3. 图像像素的读写操作

/* 图像像素的读写操作 */
void pixel_visit_demo(Mat &image) {int w = image.cols;		// 获取图像宽int h = image.rows;		// 获取图像高int dims = image.channels();	// 获取图像通道数/* 数组方式 *///for (int row = 0; row < h; row++) {//	for (int col = 0; col < w; col++) {//		// 单通道 - 灰色图像//		if (1 == dims) {//			// 获取通道中的值//			int pv = image.at<uchar>(row, col);//			// 还可以对其进行修改//			image.at<uchar>(row, col) = 255 - pv;	// 得确保值在0-255区间//		} else if (3 == dims) {	// 三通道 - 彩色图像//			// 获取通道中的三个值//			Vec3b bgr = image.at<Vec3b>(row, col);//			// 还可以对其进行修改//			image.at<Vec3b>(row, col)[0] = 255 - bgr[0];//			image.at<Vec3b>(row, col)[1] = 255 - bgr[1];//			image.at<Vec3b>(row, col)[2] = 255 - bgr[2];//		}//	}//}/* 指针方式 */for (int row = 0; row < h; row++) {uchar *current_row = image.ptr<uchar>(row);for (int col = 0; col < w; col++) {if (1 == dims) {*current_row++ = 255 - *current_row;} else if (3 == dims) {*current_row++ = 255 - *current_row;*current_row++ = 255 - *current_row;*current_row++ = 255 - *current_row;}}}imshow("pixel_visit_demo", image);
}

运行截图:

4. 图像像素的算术操作

/* 图像像素的算术操作 */
void operators_demo(Mat &image) {// 加Mat dst1;Mat m1 = Mat::zeros(image.size(), image.type());m1 = Scalar(100, 100, 100);	// 给通道赋值(相当于设置颜色)add(image, m1, dst1);imshow("图像像素加法操作", dst1);// 减Mat dst2;Mat m2 = Mat::zeros(image.size(), image.type());m2 = Scalar(50, 50, 50);subtract(image, m2, dst2);imshow("图像像素减法操作", dst2);// 乘Mat dst3;Mat m3 = Mat::zeros(image.size(), image.type());m3 = Scalar(2, 2, 2);multiply(image, m3, dst3);	// 参数一乘以参数二结果给参数三imshow("图像像素乘法操作", dst3);// 除Mat dst4;Mat m4 = Mat::zeros(image.size(), image.type());m4 = Scalar(5, 5, 5);divide(image, m4, dst4);imshow("图像像素除法操作", dst4);///* 另外一种方式实现加法操作 *///Mat dst5 = Mat::zeros(image.size(), image.type());//Mat m5 = Mat::zeros(image.size(), image.type());//m5 = Scalar(50, 50, 50);//int w = image.cols;//int h = image.rows;//int dims = image.channels();//for (int row = 0; row < h; row++) {		//	for (int col = 0; col < w; col++) {//		if (3 == dims) {//			Vec3b p1 = image.at<Vec3b>(row, col);//			Vec3b p2 = m5.at<Vec3b>(row, col);//			// 加减乘除都是一样的//			dst5.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);//			dst5.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);//			dst5.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);//		}//		//	}//}//imshow("图像像素加法操作", dst5);
}

运行截图

5. 滚动条操作演示

static void on_track(int b, void *userdata) {Mat image = *((Mat*)userdata);Mat dst = Mat::zeros(image.size(), image.type());Mat m = Mat::zeros(image.size(), image.type());m = Scalar(b, b, b);add(image, m, dst);imshow("亮度调整", dst);
}
/* 滚动条操作演示 */
void tracking_bar_demo(Mat &image) {namedWindow("亮度调整", WINDOW_AUTOSIZE);int lightness = 0;int max_value = 100;// 创建一个滚动条createTrackbar("Value Bar:", "亮度调整", &lightness, max_value, on_track, (void*)(&image));on_track(lightness, &image);
}

运行截图

6. 键盘响应操作

/* 键盘响应操作 */
void key_demo(Mat &image) {bool flag = true;Mat input;image.copyTo(input);while (flag) {int c = waitKey(100);	// 等待键盘输入,等待100msprintf("按键:%d\n", c);switch (c) {case 27: {			// Esc退出flag = false;}break;case 52: {			// 4 向左旋转}break;case 54: {			// 6 向右旋转}break;case 56: {			// 8 放大}break;case 50: {			// 2 缩小}break;case 48: {		// 0 复原}break;default:				break;}imshow("原图", image);}
}

这个键盘响应,我用来写了一个小demo,通过键盘按键来对图片进行旋转、缩放、平移、翻转和裁剪的操作。

7. OpenCV自带颜色表操作

/* OpenCV自带颜色表操作 */
void color_style_demo(Mat &image) {int colorMap[] = {COLORMAP_AUTUMN,COLORMAP_BONE,COLORMAP_CIVIDIS,COLORMAP_COOL,COLORMAP_DEEPGREEN,COLORMAP_HOT,COLORMAP_HSV,COLORMAP_INFERNO,COLORMAP_JET,COLORMAP_MAGMA,COLORMAP_OCEAN,COLORMAP_PARULA,COLORMAP_PINK,COLORMAP_PLASMA,COLORMAP_RAINBOW,COLORMAP_SPRING,COLORMAP_SUMMER,COLORMAP_TURBO,COLORMAP_TWILIGHT,COLORMAP_TWILIGHT_SHIFTED,COLORMAP_VIRIDIS,COLORMAP_WINTER,DECOMP_NORMAL};Mat dst;int index = 0;while (1) {int c = waitKey(1000);if (27 == c) {break;}applyColorMap(image, dst, colorMap[index % 19]);index++;imshow("Opencv自带颜色表", dst);}
}

数组colorMap中存储的,都是enum ColormapTypes枚举中的数据。

运行截图

8. 图像像素的逻辑操作

/* 图像像素的逻辑操作 */
void bitwise_demo(Mat &image) {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, 255, 0), -1, LINE_8, 0);rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);imshow("m1", m1);imshow("m2", m2);// 逻辑与Mat dst1;bitwise_and(m1, m2, dst1);imshow("逻辑与", dst1);// 逻辑或Mat dst2;bitwise_or(m1, m2, dst2);imshow("逻辑或", dst2);// 逻辑非Mat dst3;bitwise_not(image, dst3);imshow("逻辑非", dst3);// 逻辑异或Mat dst4;bitwise_xor(m1, m2, dst4);imshow("逻辑异或", dst4);
}

运行截图

9. 通道分离与合并

/* 通道分离与合并 */
void channels_demo(Mat &image) {std::vector<Mat> mv;// 将一个多通道数组划分为多个单通道数组split(image, mv);imshow("blue", mv.at(0));imshow("green", mv.at(1));imshow("red", mv.at(2));Mat dst;//mv.at(1) = 0;mv.at(2) = 0;// 通道合并merge(mv, dst);imshow("合并通道颜色", dst);int from_to[] = { 0, 2, 1, 1, 2, 0 };	// 将0 和 2通道交换// 通道混合mixChannels(&image, 1, &dst, 1, from_to, 3);imshow("通道混合", dst);
}

运行截图

10. 图像色彩空间转换

/* 图像色彩空间转换 */
void 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);	// 将草莓扣掉Mat redback = Mat::zeros(image.size(), image.type());redback = Scalar(40, 40, 200);	// 红色背景图bitwise_not(mask, mask);		// 逻辑非imshow("mask", mask);image.copyTo(redback, mask);	// 将原图草莓图中按照mask里白色区域拷贝到参数一中imshow("roi区域提取", redback);
}

运行截图

11. 图像像素值统计 

/* 图像像素值统计 */
void pixel_statistic_demo(Mat &image) {double minv, maxv;Point minLoc, maxLoc;std::vector<Mat> mv;split(image, mv);	// 通道分离for (int i = 0; i < mv.size(); i++) {// 找出通道中的最大值和最小值minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());printf("No.channels:%d\tminvalue:%f\tmaxvalue:%f\n", i, minv, maxv);}Mat mean, stddev;// 计算矩阵的均值和标准偏差meanStdDev(image, mean, stddev);std::cout << "means: " << mean << std::endl;std::cout << "stddev:" << stddev << std::endl;
}

运行截图

12. 图像几何形状绘制

/* 图像几何形状绘制 */
void drawing_demo(Mat &image) {Rect rect;rect.x = 100;rect.y = 130;rect.width = 200;rect.height = 270;Mat dst1 = image.clone();Mat dst2 = image.clone();// 绘制一个矩形rectangle(dst1, rect, Scalar(0, 255, 255), 2, 8, 0);// 绘制一个圆形circle(dst1, Point(300, 400), 30, Scalar(255, 0, 255), 2, 8, 0);imshow("绘制演示", dst1);// 填充一个矩形rectangle(dst2, rect, Scalar(255, 255, 0), -1, 8, 0);// 填充一个圆形circle(dst2, Point(100, 400), 30, Scalar(0, 255, 0), -1, 8, 0);imshow("填充演示", dst2);Mat dst5 = image.clone();// 绘制线line(dst5, Point(100, 130), Point(300, 400), Scalar(255, 0, 0), 2, 8, 0);// 绘制椭圆RotatedRect rrt;rrt.center = Point(200, 200);rrt.size = Size(100, 200);rrt.angle = 90.0;ellipse(dst5, rrt, Scalar(0, 0, 255), 2, 8);	// 如果需要填充,第四个参数传-1imshow("线和椭圆", dst5);Mat dst3, dst4;dst3 = Mat::zeros(image.size(), image.type());dst3 = Scalar(100, 180, 200);imshow("dst3", dst3);// 将两张相同大小,相同类型的图片融合的函数addWeighted(image, 0.7, dst3, 0.5, 1, dst4);imshow("两种图片融合", dst4);
}

运行截图

13. 随机数与随机颜色 

/* 随机数与随机颜色 */
void random_drawing_demo() {Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);int w = canvas.cols;int h = canvas.rows;RNG rng((unsigned)time(NULL)); // 用系统时间作为种子初始化rng,要用到time.h库while (1) {int c = waitKey(10);if (27 == c) {break;}canvas = Scalar(0, 0, 0);// 获得随机值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);int g = rng.uniform(0, 255);int r = rng.uniform(0, 255);line(canvas, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 1, LINE_AA, 0);imshow("随机数与随机颜色", canvas);}
}

运行截图

14. 多边形填充与绘制

/* 多边形填充与绘制 */
void polyline_drawing_demo() {Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);Point p1(100, 100);Point p2(350, 120);Point p3(300, 350);Point p4(450, 500);Point p5(50, 200);std::vector<Point> pts;pts.emplace_back(p1);pts.emplace_back(p2);pts.emplace_back(p3);pts.emplace_back(p4);pts.emplace_back(p5);// 填充一个多边形//fillPoly(canvas, pts, Scalar(255, 0, 255), 8, 0);// 绘制一个多边形//polylines(canvas, pts, true, Scalar(0, 0, 255), 2, LINE_AA, 0);std::vector<std::vector<Point>> contours;contours.push_back(pts);// 绘制多边形或者填充多边形,参数三指定绘制容器中指定数据的第几个(-1表示全都绘制),最后一个参数为多边形的边框(-1表示填充)drawContours(canvas, contours, 0, Scalar(255, 0, 0), -1);imshow("多边形填充与绘制",  canvas);
}

运行截图

15. 鼠标操作与响应

Point sp(-1, -1);
Point ep(-1, -1);
Mat temp;
static void on_draw(int event, int x, int y, int flags, void *userdata) {Mat image = *((Mat*)userdata);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;int dy = ep.y - sp.y;if (dx > 0 && dy > 0 && ep.y < image.size().height && ep.x < image.size().width) {Rect box(sp.x, sp.y, dx, dy);rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);	// 绘制矩形imshow("鼠标绘制", image);imshow("ROI区域提取", temp(box));	// 提取矩形中的图像} else {temp.copyTo(image);imshow("鼠标绘制", image);}sp.x = -1;sp.y = -1;} else if (event == EVENT_MOUSEMOVE) {if (sp.x > 0 && sp.y > 0) {ep.x = x;ep.y = y;int dx = ep.x - sp.x;int dy = ep.y - sp.y;if (dx > 0 && dy > 0) {temp.copyTo(image);Rect box(sp.x, sp.y, dx, dy);rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);imshow("鼠标绘制", image);}}}
}
/* 鼠标操作与响应 */
void mouse_drawing_demo(Mat &image) {namedWindow("鼠标绘制", WINDOW_AUTOSIZE);// 设置鼠标回调setMouseCallback("鼠标绘制", on_draw, (void*)(&image));imshow("鼠标绘制", image);temp = image.clone();
}

运行截图

16. 图像像素类型转换与归一化

/* 图像像素类型转换与归一化 */
void norm_demo(Mat &image) {Mat dst;std::cout << image.type() << std::endl;image.convertTo(image, CV_32F);std::cout << image.type() << std::endl;normalize(image, dst, 1.0, 0, NORM_MINMAX);std::cout << dst.type() << std::endl;imshow("图像数据归一化", dst);
}

运行截图

17. 图像缩放与插值

/* 图像缩放与插值 */
void 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*1.5, h*1.5), 0, 0, INTER_LINEAR);imshow("zoomout", zoomout);
}

运行截图

18. 图像翻转

/* 图像翻转 */
void flip_demo(Mat &image) {Mat dst;// 上下翻转flip(image, dst, 0);// 左右翻转//flip(image, dst, 1);// 先左右翻转再上下翻转//flip(image, dst, -1);imshow("图像翻转", dst);
}

运行截图

19. 图像旋转

/* 图像旋转 */
void 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);// 计算旋转后需要多大的窗体才能完全装下旋转后的图像double cos = abs(M.at<double>(0, 0));double sin = abs(M.at<double>(0, 1));int nw = cos * w + sin * h;int nh = sin * w + cos * h;M.at<double>(0, 2) += (nw / 2 - w / 2);M.at<double>(1, 2) += (nh / 2 - h / 2);warpAffine(image, dst, M, Size(nw, nh), INTER_LINEAR, 0, Scalar(255, 0, 0));imshow("图像旋转", dst);
}

运行截图

20. 视频文件摄像头使用

/* 视频文件摄像头使用 */
void video_demo() {// VideoCapture capture(0);		// 参数是0,就是读取电脑摄像头VideoCapture capture("E:\\Code\\vs2017Code\\OpencvTest2\\OpencvTest2\\win10.mp4");	// 视频宽int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);// 视频高int frame_hegiht = capture.get(CAP_PROP_FRAME_HEIGHT);// 视频总帧率int count = capture.get(CAP_PROP_FRAME_COUNT);// 视频每秒多少fps(每秒多少帧)double fps = capture.get(CAP_PROP_FPS);std::cout << "froma_width:" << frame_width << std::endl;std::cout << "frame_hegiht:" << frame_hegiht << std::endl;std::cout << "count:" << count << std::endl;std::cout << "fps:" << fps << std::endl;// 定义视频保存对象VideoWriter writer("D://test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_hegiht), true);Mat frame;while (1) {capture.read(frame);	// 读取画面//flip(frame, frame, 1);	// 左右翻转,读取电脑摄像头时需要翻转,视频不用if (frame.empty()) {break;}imshow("frame", frame);// 保存视频writer.write(frame);int c = waitKey(10);if (27 == c) {break;}}// 释放capture.release();writer.release();
}

运行截图

21. 图像卷积操作

/* 图像卷积操作 */
void blur_demo(Mat &image) {Mat dst;blur(image, dst, Size(1, 1), Point(-1, -1));    // // 设置参数三的数值即可imshow("图像模糊", dst);    
}

运行截图

22. 高斯模糊 

/* 高斯模糊 */
void gaussian_blur_demo(Mat &image) {Mat dst;GaussianBlur(image, dst, Size(0, 0), 5);	// 参数三默认0即可,设置参数四实现模糊imshow("高斯模糊", dst);
}

运行截图

23. 高斯双边模糊

/* 高斯双边模糊 */
void bifilter_demo(Mat &image) {Mat dst;bilateralFilter(image, dst, 0, 100, 10);imshow("双边模糊", dst);
}

运行截图


三、键盘操作小demo

1. 键盘小demo

对图片操作,旋转,缩放,平移,翻转,裁剪的操作。

#include <opencv2/opencv.hpp>using namespace cv;void imageOperate1(Mat &image, Mat input, double angle, double scale, int xOffset, int yOffset, int startRow, int &endRow, int startCol, int &endCol, bool up_down, bool left_right) {input.copyTo(image);// 图像平移Size dst_sz = image.size();//定义平移矩阵Mat t_mat = Mat::zeros(2, 3, CV_32FC1);t_mat.at<float>(0, 0) = 1;t_mat.at<float>(0, 2) = xOffset; //水平平移量t_mat.at<float>(1, 1) = 1;t_mat.at<float>(1, 2) = yOffset; //竖直平移量//根据平移矩阵进行仿射变换warpAffine(image, image, t_mat, dst_sz);// 旋转图像Point2f center((image.cols - 1) / 2.0, (image.rows - 1) / 2.0);	// 图像中心位置Mat rotation_matix = getRotationMatrix2D(center, angle, 1.0);warpAffine(image, image, rotation_matix, image.size());// 缩放图像int width = int(input.cols * scale);int height = int(input.rows * scale);resize(image, image, cv::Size(width, height), 0, 0, INTER_LINEAR);if (0 == endRow) {		// 发生了缩放操作endRow = height;endCol = width;}// 裁剪图像	image = image(Range(startRow, endRow), Range(startCol, endCol));// 上下翻转if (up_down) flip(image, image, 0);// 左右翻转if (left_right) flip(image, image, 1);
}
/* 键盘响应操作 */
void key_demo1(Mat &image) {bool flag = true;double scale = 1.0;		// 缩放比例double angle = 0;		// 旋转角度int xOffset = 0;		// 水平平移量int yOffset = 0;		// 竖直平移量int startRow = 0;					// 裁剪起始行int endRow = image.size().height;	// 裁剪结束行int startCol = 0;					// 裁剪起始列int endCol = image.size().width;	// 才接结束列bool up_down = false;				// 上下翻转bool left_right = false;			// 左右翻转Mat input;image.copyTo(input);while (flag) {int c = waitKey(100);	// 等待键盘输入,等待100msprintf("按键:%d\n", c);switch (c) {case 27:{			// Esc退出flag = false;}break;case 52:{			// 4 向左旋转angle += 5;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);}break;case 54:{			// 6 向右旋转angle -= 5;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);}break;case 56:{			// 8 放大scale += 0.1;if (scale <= 2.05) {	// 设置最大放大是2endRow = 0;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);} else {scale = 2.0;}}break;case 50:{			// 2 缩小scale -= 0.1;if (scale >= 0.15) {	// 最小缩小是0.2endRow = 0;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);} else {scale = 0.2;}}break;case 87:case 119:{		// wW 图片上移yOffset -= 2;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);}break;case 83:case 115:{		// sS 图片下移yOffset += 2;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);}break;case 65:case 97:{		// aA 图片左移xOffset -= 2;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);}break;case 68:case 100:{		// dD 图片右移xOffset += 2;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);}break;case 73:{		// I 图片上边复原if (startRow > 0) {startRow -= 1;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);} else {startRow = 0;}}break;case 105:{		// i 图片上边裁剪if (startRow < endRow - 1) {startRow += 1;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);} else {startRow = endRow - 1;}}break;case 75:{		// K 图片下边复原if (endRow < input.size().height) {endRow += 1;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);} else {endRow = input.size().height;}}break;case 107:{		// k 图片下边裁剪if (endRow > startRow + 1) {endRow -= 1;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);} else {endRow = startRow + 1;}}break;case 74:{		// J 图片左边恢复if (startCol > 0) {startCol -= 1;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);} else {startCol = 0;}}break;case 106:{		// j 图片左边裁剪if (startCol < endCol - 1) {startCol += 1;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);} else {startCol = endCol - 1;}}break;case 76:{		// L 图片右边复原if (endCol < input.size().width) {endCol += 1;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);} else {endCol = input.size().width;}}break;case 108:{		// l 图片右边裁剪if (endCol > startCol + 1) {endCol -= 1;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);} else {endCol = startCol + 1;}}break;case 43:{		// + 上下翻转up_down = !up_down;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);}break;case 45:{		//  - 左右翻转left_right = !left_right;imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);}break;case 48:{		// 0 复原scale = 1.0;					// 缩放比例angle = 0;						// 旋转角度xOffset = 0;					// 水平平移量yOffset = 0;					// 竖直平移量startRow = 0;					// 裁剪起始行endRow = input.size().height;	// 裁剪结束行startCol = 0;					// 裁剪起始列endCol = input.size().width;	// 才接结束列up_down = false;				// 上下翻转left_right = false;				// 左右翻转imageOperate1(image, input, angle, scale, xOffset, yOffset, startRow, endRow, startCol, endCol, up_down, left_right);}break;default:break;}imshow("原图", image);}
}int main(void) {Mat image = imread("图.jpeg", IMREAD_COLOR);if (image.empty()) {printf("path image NULL!\n");return -1;}imshow("原图", image);key_demo1(image);waitKey(0);destroyAllWindows();return 0;
}

运行截图

2. 旋转、缩放、裁剪、平移案例

#include <stdio.h>
#include <Windows.h>
#include "opencv2/opencv.hpp"using namespace cv;// 图片旋转
Mat imageRotate(Mat input, double angle) {angle *= -1;// get the center coordinates of the image to create the 2D rotation matrixPoint2f center((input.cols - 1) / 2.0, (input.rows - 1) / 2.0);// using getRotationMatrix2D() to get the rotation matrixMat rotation_matix = getRotationMatrix2D(center, angle, 1.0);Mat newImage;warpAffine(input, newImage, rotation_matix, input.size());//namedWindow("测试图片旋转", WINDOW_FREERATIO);//imshow("测试图片旋转", newImage);imshow("测试显示图片", newImage);return newImage;
}// 图片缩放
Mat imageZoom(Mat input, float scaleW, float scaleH) {//float scaleW = 0.5; // 定义新图像的大小,宽度缩小到80%//float scaleH = 0.5;  //定义新图像的大小,高度缩小到80%int width = int(input.cols * scaleW);//定义想要扩大或者缩小后的宽度,src.cols为原图像的宽度,乘以80%则得到想要的大小,并强制转换成int型int height = int(input.rows * scaleH);//定义想要扩大或者缩小后的高度,src.cols为原图像的高度,乘以80%则得到想要的大小,并强制转换成int型cv::Mat dst;resize(input, dst, cv::Size(width, height));//缩放图像//namedWindow("测试图片缩放", WINDOW_FREERATIO);//imshow("测试图片缩放", dst);imshow("测试显示图片", dst);return dst;
}// 图片裁剪
Mat imageCut(Mat input, int startRow, int endRow, int startCol, int endCol) {Mat cropped_image = input(Range(startRow, endRow), Range(startCol, endCol));//namedWindow("测试裁剪图片", WINDOW_FREERATIO);//imshow("测试裁剪图片", cropped_image);imshow("测试显示图片", cropped_image);return cropped_image;
}// 图像平移
Mat imageTranslation(Mat srcImage, int xOffset, int yOffset)
{Size dst_sz = srcImage.size();//定义平移矩阵Mat t_mat = Mat::zeros(2, 3, CV_32FC1);t_mat.at<float>(0, 0) = 1;t_mat.at<float>(0, 2) = xOffset; //水平平移量t_mat.at<float>(1, 1) = 1;t_mat.at<float>(1, 2) = yOffset; //竖直平移量//根据平移矩阵进行仿射变换Mat TranslationMat;warpAffine(srcImage, TranslationMat, t_mat, dst_sz);//namedWindow("测试平移图片", WINDOW_FREERATIO);//imshow("测试平移图片", TranslationMat);imshow("测试显示图片", TranslationMat);return TranslationMat;
}int main(void) {Mat image =imread("123.png");//namedWindow("测试显示图片", WINDOW_FREERATIO);	// WINDOW_FREERATIO:可以手动调节大小//imshow("测试显示图片", image);//waitKey(0);double angle = 120;Mat imgRotate = imageRotate(image, angle);waitKey(0);float scale = 0.5;Mat imgZoom = imageZoom(imgRotate, scale, scale);waitKey(0);Mat imgCut = imageCut(imgZoom, 50, 80, 200, 300);waitKey(0);imageTranslation(imgCut, 10, 20);waitKey(0);destroyAllWindows();return 0;
}

3. 往图片中写入中文文字

记录一个类型转换:

    // char* 转 wchar_t*
    wchar_t wcha[255] = { 0 };
    MultiByteToWideChar(CP_ACP, 0, text, strlen(text), wcha, 255);

putTextCN.h

#pragma once
#include <windows.h>
#include <string>
#include <opencv2/opencv.hpp>using namespace cv;// 内部调用
static void GetStringSize(HDC hDC, const char* str, int* w, int* h);
// 内部调用
static void putTextZH(Mat dst, const char* str, Point org, Scalar color, int fontSize,const char *fn, bool italic, bool underline, bool lfWeight);// 外部调用,往图片中写入文字
extern void putTextZh(InputOutputArray     img,const char *text,Point     org,int     fontSize,Scalar     color,const char *font = "Arial",bool italic = false,bool underline = false,bool lfWeight = false);

putTextCN.cpp

#include "putTextCN.h"static void GetStringSize(HDC hDC, const char* str, int* w, int* h) {SIZE size;GetTextExtentPoint32A(hDC, str, strlen(str), &size);if (w != 0) *w = size.cx;if (h != 0) *h = size.cy;
}static void putTextZH(Mat dst, const char* str, Point org, Scalar color, int fontSize, const char* fn, bool italic, bool underline, bool lfWeight) {CV_Assert(dst.data != 0 && (dst.channels() == 1 || dst.channels() == 3));int x, y, r, b;if (org.x > dst.cols || org.y > dst.rows) return;x = org.x < 0 ? -org.x : 0;y = org.y < 0 ? -org.y : 0;LOGFONTA lf;lf.lfHeight = -fontSize;lf.lfWidth = 0;lf.lfEscapement = 0;lf.lfOrientation = 0;if (true == lfWeight) {    // 粗体lf.lfWeight = 700;} else {lf.lfWeight = 400;}	lf.lfItalic = italic;       // 斜体lf.lfUnderline = underline; // 下划线lf.lfStrikeOut = 0;lf.lfCharSet = DEFAULT_CHARSET;lf.lfOutPrecision = 0;lf.lfClipPrecision = 0;lf.lfQuality = PROOF_QUALITY;lf.lfPitchAndFamily = 0;strcpy_s(lf.lfFaceName, fn);HFONT hf = CreateFontIndirectA(&lf);HDC hDC = CreateCompatibleDC(0);HFONT hOldFont = (HFONT)SelectObject(hDC, hf);int strBaseW = 0, strBaseH = 0;int singleRow = 0;char buf[1 << 12];strcpy_s(buf, str);char *bufT[1 << 12];  // 这个用于分隔字符串后剩余的字符,可能会超出。//处理多行{int nnh = 0;int cw, ch;const char* ln = strtok_s(buf, "\n", bufT);while (ln != 0) {GetStringSize(hDC, ln, &cw, &ch);strBaseW = max(strBaseW, cw);strBaseH = max(strBaseH, ch);ln = strtok_s(0, "\n", bufT);nnh++;}singleRow = strBaseH;strBaseH *= nnh;}if (org.x + strBaseW < 0 || org.y + strBaseH < 0) {SelectObject(hDC, hOldFont);DeleteObject(hf);DeleteObject(hDC);return;}r = org.x + strBaseW > dst.cols ? dst.cols - org.x - 1 : strBaseW - 1;b = org.y + strBaseH > dst.rows ? dst.rows - org.y - 1 : strBaseH - 1;org.x = org.x < 0 ? 0 : org.x;org.y = org.y < 0 ? 0 : org.y;BITMAPINFO bmp = { 0 };BITMAPINFOHEADER& bih = bmp.bmiHeader;int strDrawLineStep = strBaseW * 3 % 4 == 0 ? strBaseW * 3 : (strBaseW * 3 + 4 - ((strBaseW * 3) % 4));bih.biSize = sizeof(BITMAPINFOHEADER);bih.biWidth = strBaseW;bih.biHeight = strBaseH;bih.biPlanes = 1;bih.biBitCount = 24;bih.biCompression = BI_RGB;bih.biSizeImage = strBaseH * strDrawLineStep;bih.biClrUsed = 0;bih.biClrImportant = 0;void* pDibData = 0;HBITMAP hBmp = CreateDIBSection(hDC, &bmp, DIB_RGB_COLORS, &pDibData, 0, 0);CV_Assert(pDibData != 0);HBITMAP hOldBmp = (HBITMAP)SelectObject(hDC, hBmp);//color.val[2], color.val[1], color.val[0]SetTextColor(hDC, RGB(255, 255, 255));SetBkColor(hDC, 0);//SetStretchBltMode(hDC, COLORONCOLOR);strcpy_s(buf, str);const char* ln = strtok_s(buf, "\n", bufT);int outTextY = 0;while (ln != 0) {TextOutA(hDC, 0, outTextY, ln, strlen(ln));outTextY += singleRow;ln = strtok_s(0, "\n", bufT);}uchar* dstData = (uchar*)dst.data;int dstStep = dst.step / sizeof(dstData[0]);unsigned char* pImg = (unsigned char*)dst.data + org.x * dst.channels() + org.y * dstStep;unsigned char* pStr = (unsigned char*)pDibData + x * 3;for (int tty = y; tty <= b; ++tty) {unsigned char* subImg = pImg + (tty - y) * dstStep;unsigned char* subStr = pStr + (strBaseH - tty - 1) * strDrawLineStep;for (int ttx = x; ttx <= r; ++ttx) {for (int n = 0; n < dst.channels(); ++n) {double vtxt = subStr[n] / 255.0;int cvv = vtxt * color.val[n] + (1 - vtxt) * subImg[n];subImg[n] = cvv > 255 ? 255 : (cvv < 0 ? 0 : cvv);}subStr += 3;subImg += dst.channels();}}SelectObject(hDC, hOldBmp);SelectObject(hDC, hOldFont);DeleteObject(hf);DeleteObject(hBmp);DeleteDC(hDC);
}extern void putTextZh(InputOutputArray     img,const char *text,Point     org,int     fontSize,Scalar     color,const char  *font,bool italic,bool underline, bool lfWeight) {Mat src = img.getMat();putTextZH(src, text, org, color, fontSize, font, italic, underline, lfWeight);
}

main.cpp

#include "putTextCN.h"/* 绘制文字 */
void putText_demo(Mat &image, char *text) {putTextZh(image, text, Point(150, 50), 20, Scalar(0, 0, 0), "宋体");imshow("绘制文字", image);
}int main(void) {// 正常:IMREAD_COLOR// 灰度:IMREAD_GRAYSCALEMat image = imread("图.jpeg", IMREAD_COLOR);if (image.empty()) {printf("path image NULL!\n");return -1;}imshow("原图", image);char str[] = "测试OpenCV绘制文字";putText_demo(image, str);waitKey(0);destroyAllWindows();return 0;
}

运行截图


四、总结

opencv对图片一些简单的操作,我也就只会这些简单的了,也是在B站看视频学习后记录下来的代码,具体其他高深的的操作就不会了!


http://chatgpt.dhexx.cn/article/mIGcYlN6.shtml

相关文章

VS2017搭建OpenCV环境(新手详细教程)

整体流程如下&#xff1a; 下载Visual Studio2017版本下载OpenCV3.4.1版本配置环境变量在Visual Studio2017中引入头文件、库文件、链接库环境测试 说明&#xff1a;没有必要根据博主的博客下载与博客相应的版本&#xff0c;不同版本之间只需要改一点点东西即可 1、下载安装V…

《OpenCV联合C++》第一课:OpenCV下载及环境配置

1.下载OpenCV软件 官网下载Releases - OpenCV 下载对应文件即可 下载后导出到本地 导出中。。。 2.环境变量配置 导入对应文件夹下面路径..\opencv\build\x64\vc15\bin 3.文件夹内文件拷贝指定路径 打开文件夹下面路径.\opencv\build\x64\vc15\bin 将bin目录下面的opencv_wor…

OpenCV入门教程,超详细OpenCV入门教程!10小时让你轻松掌握opencv的使用

OpenCV是一个基于BSD许可&#xff08;开源&#xff09;发行的跨平台计算机视觉和机器学习软件库&#xff0c;可以运行在Linux、Windows、Android和mac OS 操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C 类构成&#xff0c;同时提供了Python、Ruby、MATLAB等语言的接…

VS+OpenCV+VC超详细的配置教程

写在前面的话 版权声明&#xff1a;转载请注明出处&#xff01;博主是一个小菜鸟&#xff0c;并且非常玻璃心&#xff01;如果文中有什么问题&#xff0c;请友好地指出来&#xff0c;博主查证后会进行更正。每篇文章都是博主现阶段的理解&#xff0c;如果理解的更深入的话&…

OpenMV入门介绍

目录 一、OpenMV是什么二、OpenART mini与OpenMV对比三、图像处理背景知识1.像素和分辨率2. 帧率3.RGB三原色4.LAB颜色空间 四、OpenMV图像处理方法1.感光元件自动增益/白平衡/曝光窗口ROI 2.画图画线画框画圆画十字写字示例 3. 寻找色块&#xff08;颜色识别&#xff09;find_…

最新opencv-c++安装及配置教程(VS2019 C++ opencv4.4.0)

以前写过opencv python的安装教程&#xff0c;后来有一些同学开始私信我如何安装及配置opencv c。 本文是以最新的版本入手&#xff0c;一步步详解opencv c 的安装及配置过程。&#xff1a; 第一步&#xff0c;下载解压opencv 算法库 进入到以下链接&#xff1a;https://opencv…

超详细:VS配置OpenCV教程,需要收藏

目录 安装环境说明 下载OpenCV 配置OpenCV开发环境 属性表 测试 可能存在的问题 安装环境说明 操作系统&#xff1a;Windows10 OpenCV版本&#xff1a;OpenCV2和OpenCV3 VS版本&#xff1a;VS2015或者VS2017 下载OpenCV OpenCV下载地址&#xff1a;Home - OpenCV或者直…

【OpenCV教程合集版】一文入门和精通OpenCV(C/C++)

文章目录&#xff08;OpenCV版本4.6.0&#xff09; 1.数据类型2.矩阵基本操作2.1 全零矩阵2.2 全一矩阵2.3 单位矩阵2.4 矩阵转置2.5 求逆矩阵2.6 逗号式分隔创建矩阵2.7 矩阵定义(只列出常用的)2.7.1 数据类型Scalar 2.8 通过ptr与at函数遍历矩阵2.8.1 Vec类型 2.9 通过迭代器…

openCV超详细入门教程(python版)

涉及内容&#xff1a; 背景提取颜色过滤边缘检测用于对象识别的特征匹配一般对象识别 你将需要两个主要的库&#xff0c;第三个可选&#xff1a;python-OpenCV&#xff0c;Numpy 和 Matplotlib。 一、加载图片 首先&#xff0c;我们正在导入一些东西&#xff0c;我已经安装了…

OpenCV的简单使用教程与基本函数(C++版本)

OpenCV的简单使用教程&#xff08;C&#xff09; OpenCV简介OpenCV的使用基础打开、显示和保存图像图像存储变量 Mat类图像元素的存储读入图像文件创建Mat类复制Mat类图像元素的访问OpenCV画图命令行交互界面 OpenCV简介 OpenCV是一个开源发行的跨平台计算机视觉和机器学习软件…

OpenMV入门

1. 什么是OpenMV OpenMV 是一个开源&#xff0c;低成本&#xff0c;功能强大的 机器视觉模块。 OpenMV上的机器视觉算法包括 寻找色块、人脸检测、眼球跟踪、边缘检测、标志跟踪 等。 以STM32F427CPU为核心&#xff0c;集成了OV7725摄像头芯片&#xff0c;在小巧的硬件…

OpenMV零基础教程

一、资料导航 “工欲善其事&#xff0c;必先利其器”。在正式学习OpenMV之前&#xff0c;你必须知道一条或几条OpenMV的学习途径。这里推荐星瞳科技的中文官网教程&#xff0c;这个教程里面包括了OpenMV IDE的下载和安装、OpenMV上手教程、OpenMV中文文档、OpenMV详细参数以及O…

C++版本OpenCv教程

C版本OpenCv教程(一)Mat—基本的图像容器 目标 我们有多种方法从现实世界获取数字图像:数码相机、扫描仪、计算机断层扫描和磁共振成像等等。在以上任何情况下&#xff0c;我们(人类)看到的都是图像。然而&#xff0c;当将其转换到我们的数字设备时&#xff0c;我们所记录的是…

VS配置OpenCV教程(超详细)

目录 安装环境说明 下载OpenCV 配置OpenCV开发环境 属性表 测试 可能存在的问题 安装环境说明 操作系统&#xff1a;Windows10 OpenCV版本&#xff1a;OpenCV2和OpenCV3 VS版本&#xff1a;VS2015或者VS2017 下载OpenCV OpenCV下载地址&#xff1a;http://opencv.org…

伺服控制原理 及RT and IRT

什么是伺服系统&#xff1f; 以物体的位置、方向、速度等为控制量&#xff0c;以跟踪输入给定制的任意变化为目的&#xff0c;所构成的自动闭环控制系统。 伺服系统组成&#xff1a; 伺服系统是具有负反馈的闭环自动控制系统&#xff0c;由控制器、伺服驱动器、伺服电机和反…

ERTEC200P-2 PROFINET设备完全开发手册(3-1)

3. 读写周期数据 PROFINET的基本通讯模型如下图&#xff1a; Profinet 是基于标准以太网技术的应用层协议&#xff0c;支持4种类型的数据通道 标准通道&#xff1a;参数化及配置&#xff0c;读诊断数据&#xff0c;设备信息(I&M)&#xff0c;资产信息 (AMR) ;&#xff08…

ERTEC200P-2 PROFINET设备完全开发手册(8-2)

8.2 IRT通讯原理及API PROFINET RT通讯的特点&#xff1a; 典型的PROFINET网络如下图所示。 其中&#xff1a; T1: 采样输入 T2: IO背板周期 T3: Profinet I/O 通讯周期 T4: CPU组织块OB1执行周期 T5: Profinet I/O 通讯周期 T6: IO背板周期 T7: 建立输出 在PRO…

多维IRT模型的EM估计

多维IRT模型的EM估计 MIRT &#xff08;Multidimensional Item Response Theory&#xff09;多维项目反应理论。与一维项目反应理论的区别只是在于对于潜在变量的 θ i \theta_{i} θi​ 的建模&#xff0c;一个是unidimensional latent trait θ i \theta_{i} θi​&#xf…

R语言IRT理论:扩展Rasch模型等级量表模型lltm、 rsm 和 pcm模型分析心理和教育测验数据可视化

最近我们被客户要求撰写关于IRT理论的研究报告&#xff0c;包括一些图形和统计输出。 摘要 我们首先介绍扩展 Rasch 模型的方法论&#xff0c;然后是一般程序描述和应用主题,包括简单的 Rasch 模型、评级量表模型、部分信用模型及其线性扩展。这种线性结构的结合允许对协变量…

ERTEC200P-2 PROFINET设备完全开发手册(8-1)

8.1 IRT通讯实验 这里我们使用APP3 IsoApp&#xff0c;修改源代码usrapp_cfg.h的宏为 #define EXAMPL_DEV_CONFIG_VERSION 3 使能App3&#xff0c;对应的主程序为“usriod_main_isoapp.c” 编译后下载运行。打开4.2建立的TIA项目&#xff0c;添加等时模式组织块&#xff0c…