OpenCV | 入门

OpenCV | 入门

安装

参考教程

基础知识

V G A = 640 × 480 VGA = 640 \times 480 VGA=640×480
H D = 1280 × 720 HD = 1280 \times 720 HD=1280×720
F H D = 1920 × 1080 FHD = 1920 \times 1080 FHD=1920×1080
4 K = 3840 × 2160 4K = 3840 \times 2160 4K=3840×2160
这些都表示了固定的像素,例如 VGA,代表在宽度上 640 像素(px),在高度上 480 像素。我们可以把这些像素看成一个一个框。
对于黑白图像 Binary Image, 用 0 代表黑色,用 1 代表白色。

对于 8 位,可以表示 2 8 = 256 2^8 = 256 28=256 个级别,也就是 0 ~ 255。一个灰度图像(Gray Scale Image) 也就是 8 Bit or 256 Level 的。
OpenCV学习笔记——HSV颜色空间超极详解&inRange函数用法及实战

显示图像

图片与代码放在同个目录下。

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>using namespace std;
using namespace cv;int main()
{/* Importing Images */string path = "../dog.jpeg";Mat img = imread(path);imshow("Image", img);waitKey(0);
}

播放视频

#include<opencv2/opencv.hpp>using namespace cv;
using namespace std;int main()
{string path = "../Megamind.avi";VideoCapture cap(path);Mat img;while(1){cap.read(img);imshow("Image", img);waitKey(3); // 添加延时}return 0;
}

将图片转换为灰度图像

string path = "../dog.jpeg";
Mat img = imread(path);
Mat imgGray;/* 转换图像颜色 */
cvtColor(img, imgGray, COLOR_BGR2GRAY);imshow("Image", img);
imshow("Image Gray", imgGray);
waitKey(0);

模糊图像

Mat imgBlur;
GaussianBlur(img, imgBlur, Size(7, 7), 5, 0);
imshow("Image Blur", imgBlur);

边缘检测

Mat imgCanny;
Canny(imgBlur, imgCanny, 50, 150);
imshow("Image Canny", imgCanny);


对于 Canny 函数

void cv::Canny(InputArray image, OutputArray edges, double lowThreshold, double highThreshold, int apertureSize = 3);/*
image:输入图像,应该是灰度图像。 
edges:输出图像,即检测到的边缘图像。 
lowThreshold:低阈值,用于双阈值检测。 
highThreshold:高阈值,用于双阈值检测。 
apertureSize:指定Sobel算子的大小,默认为3。
*/

图像膨胀

Mat imgDil;
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
dilate(imgCanny, imgDil, kernel);
imshow("Image Dilate", imgDil);


getStructuringElement 函数返回一个结构元素(卷积核)。

Mat kernel = cv2.getStructuringElement(a,b,c);/*
a 设定卷积核的形状,不同卷积核(形状、大小)对图形的腐蚀、膨胀操作效果不同。MORPH_RECT(函数返回矩形卷积核)  MORPH_CROSS(函数返回十字形卷积核)  MORPH_ELLIPSE(函数返回椭圆形卷积核)
b 设定卷积核的大小用 (x, y) 表示,表示卷积核有 x 行 y 列。
c 表示描点的位置,一般 c = 1,表示位于中心。
*/

图像腐蚀

Mat imgErode;
erode(imgDil, imgErode, kernel);
imshow("Image Erode", imgErode);

调整图片大小

输出图片的尺寸

cout << img.size() << endl;


对其进行增大

Mat imgResize;resize(img, imgResize, Size(640, 480));imshow("Image Resize", imgResize);


如果使用比例进行缩小,缩小到 二分之一

resize(img, imgResize, Size(), 0.5, 0.5);

裁剪图片

用 Rect 裁剪一块矩形

Mat imgCrop;Rect roi(300, 300, 250, 150); // x 坐标 y 坐标 宽度 高度
imgCrop = img(roi);imshow("Image Crop", imgCrop);

创建图片

创建一张蓝色的图片

Mat img(512, 512, CV_8UC3, Scalar(255, 0, 0));imshow("Image", img);

绘制图形

绘制圆圈

// White Image
Mat img(512, 512, CV_8UC3, Scalar(255, 255, 255));circle(img, Point(256, 256), 155, Scalar(0, 69, 255));imshow("Image", img);

增加圆圈的厚度
circle(img, Point(256, 256), 155, Scalar(0, 69, 255), 10);

填满圆圈
circle(img, Point(256, 256), 155, Scalar(0, 69, 255), FILLED);

绘制矩形

rectangle(img, Point(130, 226), Point(382, 286), Scalar(255, 255, 255), 3);
// 两个 Point 分别代表矩形左上角坐标和右下角坐标

将矩形填满
rectangle(img, Point(130, 226), Point(382, 286), Scalar(255, 255, 255), FILLED);

绘制一条线

line(img, Point(130, 296), Point(382, 296), Scalar(255, 255, 255), 2);

添加文字

putText(img, "Birdy's Workshop", Point(137, 262), FONT_HERSHEY_DUPLEX, 0.75, Scalar(0, 69, 255));

给文字添加厚度
putText(img, "Birdy's Workshop", Point(137, 262), FONT_HERSHEY_DUPLEX, 0.75, Scalar(0, 69, 255), 2);

Warp images

原图像:

int main()
{   string path = "../image/cards.jpg";float w = 250, h = 350;Mat img = imread(path);Mat matrix, imgWarp;Point2f src[4] = {{529, 142}, {779, 190}, {405, 395}, {674, 457}};Point2f dst[4] = {{0.0f, 0.0f}, {w, 0.0f}, {0.0f, h}, {w, h}};matrix = getPerspectiveTransform(src, dst);warpPerspective(img, imgWarp, matrix, Point(w, h));imshow("Image", img);imshow("Image Warp", imgWarp);waitKey(0);return 0;
}

圈出选中的四个角

for(int i = 0; i < 4; i ++){circle(img, src[i], 10, Scalar(0, 0, 255), FILLED);}imshow("Image", img);

颜色检测

原图像

HSV 颜色系统

Hue 色相
Saturation 饱和度
Value 色调、纯度

转换 HSV

将图像转换为 hsv 空间可以更容易识别颜色。

Mat imgHSV;cvtColor(img, imgHSV, COLOR_BGR2HSV);imshow("Image HSV", imgHSV);

Mask

Mat mask;int hmin = 0, smin = 110, vmin = 153;
int hmax = 19, smax= 240, vmax = 255;Scalar lower(hmin, smin, vmin);
Scalar upper(hmax, smax, vmax);
inRange(imgHSV, lower, upper, mask);imshow("Image Mask", mask);


上述代码中的 hmin、smin、vim … 一系列的值如果通过每次手动修改去找到适合的就会非常麻烦。可以通过创建轨道的方式进行动态修改。

int main()
{string path = "../image/lambo.png";Mat img = imread(path);Mat imgHSV, mask;cvtColor(img, imgHSV, COLOR_BGR2HSV);int hmin = 0, smin = 110, vmin = 153;int hmax = 19, smax= 240, vmax = 255;namedWindow("Trackbars", (640, 200));createTrackbar("Hue Min", "Trackbars", &hmin, 179);createTrackbar("Hue Max", "Trackbars", &hmax, 179);createTrackbar("Sat Min", "Trackbars", &smin, 255);createTrackbar("Sat Max", "Trackbars", &smax, 255);createTrackbar("Val Min", "Trackbars", &vmin, 255);createTrackbar("Val Max", "Trackbars", &vmax, 255);while(1){Scalar lower(hmin, smin, vmin);Scalar upper(hmax, smax, vmax);inRange(imgHSV, lower, upper, mask);imshow("Image", img);imshow("Image HSV", imgHSV);imshow("Image Mask", mask);waitKey(1);}return 0;
}


调节之后:

检测不同颜色物体

#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;int main()
{string path = "../image/shapes.png";Mat img = imread(path);Mat imgHSV, mask;int hmin = 0, smin = 0, vmin = 0;int hmax = 179, smax= 255, vmax = 255;cvtColor(img, imgHSV, COLOR_BGR2HSV);namedWindow("Trackbars", (640, 200));createTrackbar("Hue Min", "Trackbars", &hmin, 179);createTrackbar("Hue Max", "Trackbars", &hmax, 179);createTrackbar("Sat Min", "Trackbars", &smin, 255);createTrackbar("Sat Max", "Trackbars", &smax, 255);createTrackbar("Val Min", "Trackbars", &vmin, 255);createTrackbar("Val Max", "Trackbars", &vmax, 255);while(1){Scalar lower(hmin, smin, vmin);Scalar upper(hmax, smax, vmax);inRange(imgHSV, lower, upper, mask);imshow("Image", img);imshow("Image HSV", imgHSV);imshow("Image Mask", mask);waitKey(1);}waitKey(0);return 0;
}


检测轮廓、形状

#include<opencv2/opencv.hpp>using namespace cv;
using namespace std;int main()
{string path = "../image/shapes.png";Mat img = imread(path);Mat imgGray, imgBlur, imgCanny, imgDil, imgErode; cvtColor(img, imgGray, COLOR_BGR2GRAY);GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);Canny(imgBlur, imgCanny, 25, 75);Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));dilate(imgCanny, imgDil, kernel);imshow("Image", img);imshow("Image Gray", imgGray);imshow("Image Blur", imgBlur);imshow("Image Canny", imgCanny);imshow("Image Dil", imgDil);waitKey(0);return 0;
}


当我们放大 ImgCanny 也就是边缘检测的图像,会发现三角形边有很明显的毛躁和缝隙。

而放大膨胀后的图像,发现这些毛躁和缝隙变少,所以一般用膨胀后的图像来作为边缘检测的图像。

绘制轮廓

#include<opencv2/opencv.hpp>using namespace cv;
using namespace std;void getContours(Mat imgDil, Mat img)
{vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);drawContours(img, contours, -1, Scalar(255, 0, 255), 2);
}int main()
{string path = "../image/shapes.png";Mat img = imread(path);Mat imgGray, imgBlur, imgCanny, imgDil, imgErode; // PreprocessingcvtColor(img, imgGray, COLOR_BGR2GRAY);GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);Canny(imgBlur, imgCanny, 25, 75);Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));dilate(imgCanny, imgDil, kernel);getContours(imgDil, img);imshow("Image", img);// imshow("Image Gray", imgGray);// imshow("Image Blur", imgBlur);// imshow("Image Canny", imgCanny);// imshow("Image Dil", imgDil);waitKey(0);return 0;
}


但是我们发现,小噪点也被勾勒了轮廓。
我们想去除这些噪点的轮廓。

打印每个图形面积

for(int i = 0; i < contours.size(); i ++){int area = contourArea(contours[i]);cout << area << endl;}

通过输出每个图形的面积,我们发现,噪点面积为 185.

我们可以简单设置如果面积在 1000 以上才回绘制轮廓

void getContours(Mat imgDil, Mat img)
{vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);// drawContours(img, contours, i, Scalar(255, 0, 255), 2);for(int i = 0; i < contours.size(); i ++){int area = contourArea(contours[i]);cout << area << endl;if(area > 1000) {drawContours(img, contours, i, Scalar(255, 0, 255), 2);}}
}

可以发现噪点没有被绘制轮廓。

图像轮廓点进行多边形拟合

approxPolyDP 函数主要功能是把一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合。

void getContours(Mat imgDil, Mat img)
{vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);vector<vector<Point>> conPoly(contours.size());for(int i = 0; i < contours.size(); i ++){int area = contourArea(contours[i]);cout << area << endl;if(area > 1000) {float peri = arcLength(contours[i], true);approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);cout << conPoly[i].size() << endl;}}
}

可以看到它绘制了很多点,然后将它们连接,而不是绘制圆

输出每个图形点的个数:

图形边界矩形

void getContours(Mat imgDil, Mat img)
{vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);vector<vector<Point>> conPoly(contours.size());vector<Rect> boundRect(contours.size());for(int i = 0; i < contours.size(); i ++){int area = contourArea(contours[i]);cout << area << endl;if(area > 1000) {float peri = arcLength(contours[i], true);approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);cout << conPoly[i].size() << endl;boundRect[i] = boundingRect(conPoly[i]);rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);}}
}

输出形状名称

void getContours(Mat imgDil, Mat img)
{vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);vector<vector<Point>> conPoly(contours.size());vector<Rect> boundRect(contours.size());for(int i = 0; i < contours.size(); i ++){int area = contourArea(contours[i]);cout << area << endl;string objectType;if(area > 1000) {float peri = arcLength(contours[i], true);approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);cout << conPoly[i].size() << endl;boundRect[i] = boundingRect(conPoly[i]);rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);int objCor = (int)conPoly[i].size();if(objCor == 3) {objectType = "Tri"; // 如果点数为 3}else if(objCor == 4) {objectType = "Rect"; // 点数为 4}else {objectType = "Circle";}putText(img, objectType, {boundRect[i].x, boundRect[i].y - 5}, FONT_HERSHEY_DUPLEX, 0.75, Scalar(0, 69, 255)); // 显示文本}}
}


但是上述代码知识简单将长方形和正方形都定义为矩形,那么该如何分辨长方形和正方形呢?
我们用宽高比来判断。

else if(objCor == 4) {// objectType = "Rect";float aspRatio = (float)boundRect[i].width / (float)boundRect[i].height;if(aspRatio > 0.95 && aspRatio < 1.05)objectType = "Square";elseobjectType = "Rectangle";
}


OPENCV——C++版图像形状简单识别

人脸识别

#include<opencv2/opencv.hpp>using namespace cv;
using namespace std;int main()
{string path = "../image/test.png";Mat img = imread(path);CascadeClassifier faceCascade;faceCascade.load("../haarcascade_frontalface_default.xml");if(faceCascade.empty())puts("None!");vector<Rect> faces;faceCascade.detectMultiScale(img, faces, 1.1, 10);for(int i = 0; i < faces.size(); i ++){rectangle(img, faces[i].tl(), faces[i].br(), Scalar(255, 0, 255), 3);}imshow("Image", img);waitKey(0);return 0;
}

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

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

相关文章

大语言模型教程与实践(开源)

1.简介 大语言模型&#xff08;Large Language Models, LLMs&#xff09;的兴起确实始于OpenAI在2018年发布的GPT&#xff08;Generative Pre-trained Transformer&#xff09;&#xff0c;这一开创性工作引领了自然语言处理领域的新纪元。随后&#xff0c;2022年底ChatGPT的横…

代码随想录算法训练营DAY40\DAY41|C++动态规划Part.3|343.整数拆分、96.不同的二叉搜索树

DAY40休息日&#xff0c;本篇为DAY41的内容 文章目录 343.整数拆分思路dp含义递推公式&#xff08;难点&#xff09;初始化遍历顺序打印 CPP代码数学方法归纳证明法 96.不同的二叉搜索树思路dp含义递推公式初始化遍历顺序打印 CPP代码题目总结 343.整数拆分 力扣题目链接 文章…

Windows系统下安装Mosquitto的步骤(7)

接前一篇文章&#xff1a;Windows系统下安装Mosquitto的步骤&#xff08;6&#xff09; 本文内容参考&#xff1a; Windows下搭建MQTT服务器_mqtt服务器软件-CSDN博客 Enable SSL/TLS Connection | EMQX Enterprise Docs 特此致谢&#xff01; 上一回讲解了使用MQTTX图形界面…

C/C++开发,opencv-ml库学习,K近邻(KNN)应用

目录 一、k近邻算法 1.1 算法简介 1.2 opencv-k近邻算法 二、cv::ml::KNearest应用 2.1 数据集样本准备 2.2 KNearest应用 2.3 程序编译 2.4 main.cpp全代码 一、k近邻算法 1.1 算法简介 K近邻算法&#xff08;K-Nearest Neighbor&#xff0c;KNN&#xff09;基本原理是…

uniapp 微信开发工具上访问正常,真机调试一直跨域报错

微信小程序真机调试时&#xff0c;出现跨域问题&#xff0c;需要同时在后端设置多种允许跨域的设置&#xff1a; // 指定允许其他域名访问 header(Access-Control-Allow-Origin:*); // 响应类型 header(Access-Control-Allow-Methods:GET,POST,OPTION); // 响应头设置 header(…

【实验】根据docker部署nginx并且实现https

环境准备 systemctl stop firewalld setenforce 0 安装docker #安装依赖包 yum -y install yum-utils device-mapper-persistent-data lvm2 #设置阿里云镜像 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #安装最新版…

Unity 编辑器工具 - 资源引用查找器

在Unity项目开发过程中&#xff0c;管理和维护资源之间的引用关系是至关重要的。当然我们项目也是需要这个功能 毕竟项目大了之后查找资源引用还是交给 资源引用查找器 比较好。 功能概述 资源引用查找器允许开发者选择一个目标资源&#xff0c;并在整个项目中查找引用了该资…

记录vue报错问题 in ./node_modules/axios/lib/platform/index.js

今天这个问题困扰了我许久 报错内容如下&#xff1a; 最初一直以为是我没装axios&#xff0c;又重新装了一次&#xff0c;后面才发现是axios版本原因&#xff0c;真的总是被版本的原因困住真的很烦 解决方法如下&#xff1a; 将axios的版本改为1.5.0 1、打开项目的文件夹“…

wireshark的安装使用及相关UDP、TCP、 ARP

初步了解&#xff1a; 进入wireshark后如图&#xff1a; 从图中可以看到很多网络连接在操作的时候我们需要监测哪些 我们可以直接在本地的运行框中输入ipconfig来查看 如图&#xff1a; 从以上图片中我们可以清楚地看到哪些网络连接已经连接的我们只需要按需监测他们即可 但…

JSP与JavaBean

目录 一、JavaBean是什么 二、创建JavaBean 三、在JSP中使用JavaBean 1、按照Java语法直接使用 2、<jsp:useBean>动作 Bean的加载原理 scope属性的不同取值 3、<jsp:setProperty>动作 设置为一个表达式的值或字符序列 通过表单的参数的值来设置Bean的相应…

【C++】STL — List的接口讲解 +详细模拟实现

前言&#xff1a; 本章我们将学习STL中另一个重要的类模板list… list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是带头双向循环链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xf…

论文笔记ColdDTA:利用数据增强和基于注意力的特征融合进行药物靶标结合亲和力预测

ColdDTA发表在Computers in Biology and Medicine 的一篇一区文章 突出 • 数据增强和基于注意力的特征融合用于药物靶点结合亲和力预测。 • 与其他方法相比&#xff0c;它在 Davis、KIBA 和 BindingDB 数据集上显示出竞争性能。 • 可视化模型权重可以获得可解释的见解。 …

三种滤波(EKF、UKF、CKF)的对比,含MATLAB源代码

使用MATLAB模拟三维的滤波,包含扩展卡尔曼滤波EKF、无迹卡尔曼滤波UKF、容积卡尔曼滤波CKF。 状态更新和观测更新均为非线性的,模拟一定强度的机动性,可用于卡尔曼滤波方法的对比学习,自己修改成需要的运动模型后,可以用于组合导航(GPS+DVL形式)。 运行结果 真值的三轴…

Unity UGUI Image 点击事件忽略空白像素区域

我们会遇到图片不是方形的不规则图片。这个时候我们希望只有点击到图像内容本身才算点击&#xff0c;点击空白区域则不算点击。而UGUI对图片的处理是整个图片都会算作点击区域&#xff0c;这样不能满足于我们的使用需求了。 首先我们需要把图片本身的Read/Write 选项打开 然后…

Meta Llama 3 使用 Hugging Face 和 PyTorch 优化 CPU 推理

原文地址&#xff1a;meta-llama-3-optimized-cpu-inference-with-hugging-face-and-pytorch 了解在 CPU 上部署 Meta* Llama 3 时如何减少模型延迟 2024 年 4 月 19 日 万众期待的 Meta 第三代 Llama 发布了&#xff0c;我想确保你知道如何以最佳方式部署这个最先进的&…

时间日志格式的统一和定制

返回当前格式的时间没有错误&#xff0c;但是不符合中国人的阅读习惯 解决&#xff1a; 方案一&#xff1a;JsonFormat 解决后端 传到 前端格式问题 依赖&#xff1a; <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jack…

STM32:GPIO输出

文章目录 1、GPIO介绍1.1 GPIO的基本结构1.1 GPIO的位结构 2、 GPIO工作模式3、GPIO标准外设库接口函数3.1 RCC接口函数3.2 GPIO接口函数3.2.1 GPIO的读取函数3.2.1 GPIO的写入函数 4、GPIO的初始化 1、GPIO介绍 GPIO&#xff08;General Purpose Input Output&#xff09;通用…

Python设计模式 - 单例模式

定义 单例模式是一种创建型设计模式&#xff0c; 其主要目的是确保一个类只有一个实例&#xff0c; 并提供一个全局访问点来访问该实例。 结构 应用场景 资源管理&#xff1a;当需要共享某个资源时&#xff0c;例如数据库连接、线程池、日志对象等&#xff0c;可以使用单例模…

【UnityRPG游戏制作】Unity_RPG项目_玩法相关

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;就业…

【算法与数据结构】哈希表

文章目录 引入哈希函数介绍便利店的例子Python3 中的哈希表C 中的哈希表 应用将散列表用于查找防止重复将散列表用作缓存 哈希冲突与解决链地址法开放寻址 总结参考资料写在最后 引入 假设你在一家便利店上班&#xff0c;你不熟悉每种商品的价格&#xff0c;在顾客需要买单是时…