基于Cpp的OpenCV4.8入门学习笔记(二)

文章目录

  • 前言
  • 一、OpenCV图像的一些基本操作(day 02)
    • 16. OpenCV中提供的随机数生成
    • 17. 绘制和填充多边形,以五边形为例
    • 18. 鼠标事件控制绘画,截取ROI区域
    • 19. 图像的像素类型转换与归一化操作
    • 20. 图像的放缩与插值
    • 21. 图像的翻转(flip,镜像操作)
    • 22. 图像旋转
    • 23. 读取写入视频流文件
    • 24. 图像通道统计,输出直方图
    • 25. 续24绘制直方图
    • 26. 图像卷积操作之均值模糊
    • 27. 图像卷积操作之高斯模糊
    • 28. 图像卷积之高斯双边模糊
  • 总结


前言

  续本专栏第一篇文章,该部分是入门学习笔记的第二部分,建议读者先从第一部分的笔记看起,循序渐进,第一部分有经典的15个例子,第二部分有13个例子

一、OpenCV图像的一些基本操作(day 02)

16. OpenCV中提供的随机数生成

RNG rng(123);	//123表示随机数种子,随机数种子控制随机数的生成,相同种子的RNG对象生成的随机数序列是一样的rng.uniform(0,512); 	//生成[0,512)范围的随机数

17. 绘制和填充多边形,以五边形为例

Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);//存储点集合
vector<Point> ps;//初始化点
ps.push_back(Point(100, 100));
ps.push_back(Point(350, 100));
ps.push_back(Point(450, 280));
ps.push_back(Point(320, 450));
ps.push_back(Point(80, 400));//绘制多边形,第三个参数表示是否将多边形闭合,第三个参数表示是否绘制闭合的多边形
polylines(canvas, ps, true, Scalar(0, 0, 255), 8, LINE_AA, 0);//填充多边形
fillPoly(canvas, ps, Scalar(0, 0, 255), LINE_AA, 0);//绘制轮廓和填充多边形
vector<vector<Point>> pss;	//创建点集合数组
pss.push_back(ps);		
drawContours(canvas, pss, -1, Scalar(0, 0, 255), -1, LINE_AA);	//第三个参数为-1表示绘制所有的点集合,第五个参数为-1表示填充轮廓,大于0绘制多边形

18. 鼠标事件控制绘画,截取ROI区域

Point sp(-1, -1);	//记录开始位置
Point ep(1, 1);		//记录结束位置
Mat tmp;	//保存最原始的图片//绑定鼠标事件, x, y表示鼠标在canvas里面的位置
static void OnMouse(int event, int x,int y, int flags, void* userdata) {if (event == EVENT_LBUTTONDOWN) {	//左键按下,初始化开始坐标位置sp.x = x;sp.y = y;cout << "Start point: " << sp << endl;}else if (event == EVENT_LBUTTONUP) {	//左键抬起,初始化结束坐标位置ep.x = x;ep.y = y;Rect rect(sp, ep);imshow("mouse_event", tmp);if (sp.x != ep.x && sp.y != ep.y) {		//当在mouse_event窗口点击且没有移动时,rect为NULL,创建图像矩阵失败Mat roi = tmp(rect).clone();imshow("ROI", roi);		//截取图像的矩形区域sp.x = -1;sp.y = -1;}}else if (event == EVENT_MOUSEMOVE) {Mat image = tmp.clone();ep.x = x;ep.y = y;if (sp.x > 0 && sp.y > 0) {image = tmp.clone();	//每次移动都用原始图像覆盖,只显示当前移动所创建的矩形rectangle(image, sp, ep, Scalar(0, 0, 150), 2, LINE_AA, 0);imshow("mouse_event", image);}}
}//在一个普通函数中设置鼠标事件回调函数
void MouseDrawingDemo() {Mat src;imshow("mouse_event", src);	//在设置鼠标事件回调函数之前创建窗口tmp = src.clone();		//创建原始图像副本setMouseCallback("mouse_event", OnMouse, NULL);
}

19. 图像的像素类型转换与归一化操作

Mat src, dst;cout << src.type() << endl;				//输出图像的像素类型 
this->src.convertTo(dst, CV_32FC3);		//像素类型转换
cout << dst.type() << endl;/*param third:归一化的上限param fourth:归一化的下限param fifth:归一化的类型
*/
normalize(dst, dst, 1.0, 0, NORM_MINMAX);	//转换为float类型的像素后,进行归一化操作imshow("src", src);
imshow("normalize_dst", dst);

20. 图像的放缩与插值

图像的放缩:即放大或缩小图像的尺寸

图像的插值:在图像进行放大或者缩小的过程中,图像的像素点会变少或者变多,这时图像的信息就需要通过某种方法来进行获取,插值法就是旨在 通过某些规则/规范/约束,获取这些多出坐标点的像素值,常见的线性插值包括:一阶线性插值(最近邻近插值)、双线性插值核双三次插值

Mat src;
Mat zoomin, zoomout;
int width = src.cols;
int height = src.rows;
imshow("src",src);//线性插值法
resize(src, zoomin, Size(width / 2, height / 2), 0, 0, INTER_LINEAR);
imshow("zoomin", zoomin);
resize(src, zoomout, Size(1.5 * width, 1.5 * height), 0, 0, INTER_LINEAR);
imshow("zoomout", zoomout);

21. 图像的翻转(flip,镜像操作)

OpenCV提供flip函数,可以实现三种翻转(镜像)操作:x轴、y轴和y = x对称。

Mat src, dst;imshow("src", src);flip(src, dst, 0);	//x轴对称翻转
imshow("flip(0)", dst);flip(src, dst, 1);	//y轴对称翻转
imshow("flip(1)", dst);flip(src, dst, -1);	//y=x对称翻转 
imshow("flip(-1)", dst);

22. 图像旋转

根据仿射变换矩阵 M 控制图像的旋转方式,仿射变换矩阵M中每个元素如下,其中,x和y表示图像的中心点位置,a = scale*cos(angle),b = scale*sin(angle),angle表示放大系数,angle表示角度

[ a b ( 1 − a ) ⋅ x − b ⋅ y − b a b ⋅ x + ( 1 − a ) ⋅ y ] \begin{bmatrix} a& b& (1-a)\cdot x-b\cdot y\\ -b& a& b\cdot x+(1-a)\cdot y \end{bmatrix} [abba(1a)xbybx+(1a)y]

重点关注第三列的元素:第一行第三列和第二行第三列元素分别表示图像经过旋转和缩放后,图像中心点在x轴和y轴的平移量,这个平移量保证了图像旋转之后,中心点x和y的值不变

	Mat src, dst, M;int w = src.cols;int h = src.rows;/*第一步,获取仿射变换矩阵param first: 中心点位置param second: 旋转角度param third: 放大系数*/M = getRotationMatrix2D(Point(w / 2, h / 2), 45, 1.0);double cos = M.at<double>(0, 0);double sin = M.at<double>(0, 1);//求出旋转后图像的宽度和高度double nw = w * cos + h * sin;double nh = w * sin + h * cos;//第二步,修改仿射变换矩阵的偏置值M.at<double>(0, 2) += (nw / 2 - w / 2);M.at<double>(1, 2) += (nh / 2 - h / 2);//第三步,进行仿射变换warpAffine(this->src, dst, M, Size(nw, nh));imshow("src", this->src);imshow("rotate 45°", dst);

23. 读取写入视频流文件

VideoCapture capture(0);		//参数为0,打开默认摄像头
Mat frame;//获取视频属性
int frame_width = this->video.get(CAP_PROP_FRAME_WIDTH);
int frame_height = this->video.get(CAP_PROP_FRAME_HEIGHT);
int total_count = this->video.get(CAP_PROP_FRAME_COUNT);	//视频总帧数
double fps = this->video.get(CAP_PROP_FPS);	/*创建视频写入对象param second: 视频编解码格式param last: 控制视频颜色
*/
VideoWriter write_object("D:\\test.mp4", this->video.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);	//最后一个参数视频颜色while (1) {int flag = waitKey(100/6);		//程序阻塞可以控制帧率		if (flag == 27) break;this->video.read(frame);		//将视频中一帧图像提取到frame图像矩阵中flip(frame, frame, 1);			//图像沿y轴翻转write_object.write(frame);		//以帧的形式写入视频流文件if (frame.empty()) break;imshow("frame", frame);
}//release视频资源,最好主动释放,因为摄像头属于硬件资源,便于以后多线程控制访问
capture.release();
write_object.release();

24. 图像通道统计,输出直方图

//存储通道分离
vector<Mat> bgr;
split(this->src, bgr);
//定义绘制直方图参数变量
const int channels[1] = { 0 };	
const int bins[1] = { 256 };	//通道取值的个数
float hranges[2] = { 0,255 };	//通道值的取值范围
const float* ranges[1] = { hranges };	//指针变量数组Mat b_hist;
Mat g_hist;
Mat r_hist;//计算三个通道的直方图
calcHist(&bgr[0], 1, 0, Mat(), b_hist, 1, bins, ranges);
calcHist(&bgr[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
calcHist(&bgr[2], 1, 0, Mat(), r_hist, 1, bins, ranges);

25. 续24绘制直方图

//直方图的基本参数
int hist_w = 512;
int hist_h = 400;
//cvRound函数对浮点数进行四舍五入
int bin_w = cvRound((double)hist_w / bins[0]);		//直方图横轴每个元素所占像素点大小
Mat HistImage = Mat::zeros(Size(hist_w, hist_h), CV_8UC3);
HistImage = Scalar(255, 255, 255);	//直方图纯白背景//归一化直方图数据
normalize(b_hist, b_hist, 0, HistImage.rows, NORM_MINMAX, -1, Mat());
normalize(g_hist, g_hist, 0, HistImage.rows, NORM_MINMAX, -1, Mat());
normalize(r_hist, r_hist, 0, HistImage.rows, NORM_MINMAX, -1, Mat());//绘制直方图曲线
for (int i = 1; i < bins[0]; ++i) {Point p1(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1, 0)));Point p2(bin_w * (i), hist_h - cvRound(b_hist.at<float>(i, 0)));line(HistImage,  p1, p2, Scalar(255, 0, 0), 2, LINE_AA, 0);Point p3(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1, 0)));Point p4(bin_w * (i), hist_h - cvRound(g_hist.at<float>(i, 0)));line(HistImage, p3, p4, Scalar(0, 255, 0), 2, LINE_AA, 0);Point p5(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1, 0)));Point p6(bin_w * (i), hist_h - cvRound(r_hist.at<float>(i, 0)));line(HistImage, p5, p6, Scalar(0, 0, 255), 2, LINE_AA, 0);
}//显示直方图
imshow("HistImage", HistImage);

26. 图像卷积操作之均值模糊

OpenCV中,对图像进行模糊操作的主要目的是降低图像的噪声,通常采用卷积核的方式。

均值卷积:对卷积核内的元素求平均值代替卷积核覆盖图像范围的中心位置

Mat dst;
/*均值卷积(卷积核系数都是同值)操作函数,自定义卷积操作为3*3大小param third: 卷积核的大小param fourth: -1表示默认改变像素点位置是卷积核的中心位置
*/
blur(this->src, dst, Size(3, 3), Point(-1, -1));
imshow("src", this->src);
imshow("Convolution Blur", dst);

27. 图像卷积操作之高斯模糊

对需要改变卷积核中心位置的像素点进行高斯函数计算,具体的,计算整个核覆盖的像素点高斯函数值,然后求和,得出核的新像素点大小。

Mat	dst;
GaussianBlur(this->src, dst, Size(2, 2), 10);
imshow("src", this->src);
imshow("Gaussian Blur", dst);

28. 图像卷积之高斯双边模糊

对于一张图像,非轮廓的部分进行模糊,轮廓部分进行原有信息保存(像素值差异大的进行保留)

Mat dst;
bilateralFilter(this->src, dst, 0, 100, 10);
imshow("src",src);
imshow("bilateralFilter", dst);

总结

  至此,基于Cpp的OpenCV4.8入门学习笔记到这里就已经结束了,这28个例子非常适合基于Cpp的OpenCV4入门学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/46621.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(leecode学习)14. 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;"fl"示例 2&#xff1a; 输入…

day02.08.成员运算符•二

# 成员运算符&#xff08;掌握&#xff09; # in, not in print(3 in [3,4,5]) # print("name" in "abcnamehaha") # print(name not in {"name": "ikun", "age": 30}) # 身份运算符&#xff08;了解&#xff09; # is…

SWDIO管脚作为GPIO

下面是使用FRDM-K32L2B3开发板和SDK中的frdmk32l2b_gpio_led_output程序做了一些测试&#xff0c;configure SWDIO pin as GPIO pin的流程。 查看手册&#xff0c;找到SWDIO对应的管脚&#xff0c;可以看到PTA3对应的SWDIO管脚。 2.修改Demo程序&#xff0c;在程序中设置SWDIO…

npm和yarn清理缓存命令

yarn清除缓存 1、查看yarn全局缓存目录 yarn cache dir2、清除缓存 yarn cache cleannpm 清除缓存 1、将node-modules文件夹先删除 2、清理缓存命令&#xff1a; npm cache clean --force3、重新安装一次即可 npm install /cnpm install

【杰理蓝牙开发】AC632 开发板烧录实例

AC632 开发板烧录实例 0. 个人简介 && 授权须知1. 硬件板卡介绍2. 代码烧录2.1 使用USB接口烧录2.2 使用串口烧录 3. 为什么要用烧录器供电&#xff1f; 0. 个人简介 && 授权须知 &#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c…

代码随想录训练营第三十六天 1049最后一块石头的重量II 494目标和

第一题&#xff1a; 原题链接&#xff1a;1049. 最后一块石头的重量 II - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 首先确认这是一道01背包问题的题目&#xff0c;如何转换&#xff1a;剩下尽可能小的重量&#xff0c;如何剩下呢&#xff1f;跟分割等和子集很…

论文略读:LoRA Learns Less and Forgets Less

202405 arxiv 1 主要思想 LORA相比于全参数训练&#xff0c;学的少&#xff0c;但忘的也少 2 实验分析 2.1 训练的表现 在编程和数学任务中&#xff0c;LoRA相比全参数微调表现出明显的劣势 2.2 遗忘的表现 这边的遗忘&#xff0c;是指在数据集A上预训练&#xff0c;然后在…

18.x86游戏实战-找角色人物名字

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

c语言复习

0概念复习 gcc 旨在编译 C 语言代码。g 旨在编译 C 语言代码。 1.定义常用 #define pi 3.14 int m,n,i,sum,k1,count0,t; #include <ctype.h> #include <string.h> 2.函数常用 3.应试回答和八股 char x[5]{a&#xff0c;b&#xff0c;\0&#xff0c;c&#xff0c…

Checkpoint log is not found or is corrupted. Job not submitted.

问题 Checkpoint log is not found or is corrupted. Job not submitted. 解决 这个功能现在LSF需要第三方软件才能支持了&#xff0c;比如通过脚本集成blcr&#xff0c;blcr提供checkpoint&#xff0c;提交作业时-k是必须的&#xff0c;这个参数要设置存放checkpoint log的…

Linux编程乐趣《简单、有趣、好玩的Linux命令》

文章目录 一、黑客帝国&#xff08;cmatrix&#xff09;1.1 centOS 手动安装&#xff1a;1.2 . 运行1.3 . 效果 二、cal命令三、htop四、sl:蒸汽火车五、cowsay:会说话的小牛六、boxes七、pv 一、黑客帝国&#xff08;cmatrix&#xff09; 1.1 centOS 手动安装&#xff1a; #…

【数学建模与优化】:解析与实践

目录 数学建模概述 1. 什么是数学模型 2. 数学模型的分类 2.1 按应用领域分类 2.2 按建模方法分类 2.3 按是否考虑随机因素分类 2.4 按变量的连续性分类 2.5 按对对象内部规律了解程度分类 2.6 按变量的基本关系分类 2.7 按是否考虑时间变化分类 3. 数学规划及优化模…

易语言数据类型和插入数据类型-cnblog

易语言数据类型 基本数据类型 基本数据类型有6种:数值型、逻辑型、日期时间型、文本型、字节集型(字节型组合)、子程序指针型。数值型:0到9加. 数值型又包括:字节型、短整数型、整数型、长整数型、小数型、双精度小数型。 2.特殊数据 易语言特殊数据类型是指基本数据类型之外的…

【嵌入式Linux】<总览> 网络编程(更新中)

文章目录 前言 一、网络知识概述 1. 网路结构分层 2. socket 3. IP地址 4. 端口号 5. 字节序 二、网络编程常用API 1. socket函数 2. bind函数 3. listen函数 4. accept函数 5. connect函数 6. read和recv函数 7. write和send函数 三、TCP编程 1. TCP介绍 2.…

观察者模式:构建响应式系统的基石

在软件开发中&#xff0c;我们经常需要处理对象之间的通信问题&#xff0c;特别是在用户界面设计和事件驱动编程中。观察者模式&#xff08;Observer Pattern&#xff09;是一种行为设计模式&#xff0c;它允许一个对象&#xff08;称为主题或被观察者&#xff09;在其状态发生…

基于vite的vue脚手架工具整合:ts、jsx、eslint、prettier、stylelint、tailwind...

为了帮助vue新手更高效的学习vue3的基础知识、组件开发以及项目方案整合&#xff0c;小卷给大家整理了一个10分钟搞定《基于vite的vue脚手架工具整合》的教程。所有工具都是目前最新的版本&#xff0c;实践和调试过&#xff0c;没有一行多余的配置。

C语言之qsort函数

一、qsort 1.库函数qsort qsort是库函数&#xff0c;直接可以用来排序数据&#xff0c;底层使用的是快速排序。 qsort函数可以排序任意类型的数据。 2.头文件 #include<stdlib.h> 3.参数讲解 void*类型的指针是无具体类型的指针&#xff0c;这种类型的指针的不能直接解…

逻辑分析仪小试(DOING)

PDD买的&#xff0c;价格很nice 有一个小遗憾&#xff0c;接口是mini-usb&#xff0c;这种线找了半天&#xff0c;终于发出来一根&#xff0c;插上去直接灯就亮了。 网上找了一些教程&#xff0c;才发现这个原来是美国saleae的山寨产品。。。但是群众们都一片叫好。 所以配套…

vue3上传图片,进行图片压缩(image-compressor.js)

在图片上传的过程中&#xff0c;如果图片体量过大&#xff0c;会很影响效率&#xff0c;并且在做某些特殊业务的时候&#xff0c;可能对上传图片的大小有限制&#xff0c;我们要么就对上传的文件进行限制&#xff0c;要么就对图片进行压缩后再上传&#xff0c;我这里采用了comp…

[C/C++入门][ifelse]10、反向输出一个三位数(求整数的各位数的值)

我们解决编程问题&#xff0c;可以从数学的角度来解析这个问题——如何从一个三位数中分别提取百位、十位和个位的数字&#xff0c;我们可以使用基础的除法和乘法概念。 数位的概念 首先&#xff0c;我们需要了解数位的概念。在十进制系统中&#xff0c;每个位置代表不同的数…