导图社区 opencv-c机器人视觉向
这是一篇关于opencv-c机器人视觉向的思维导图,主要内容包括:Chapter1 读取图片/视频/摄像头,Chapter2 基础函数,Chapter8 图像形态学,Chapter9 矩的计算,Chapter10 图像滤波,Chapter11 图像分割,Chapter12 单目视觉*,Chapter13 跟踪算法*,Chapter6 颜色检测。
编辑于2025-03-28 11:03:28这是一篇关于十二月计划(11.29-12.31)的思维导图,主要内容包括:计划,目标,每日任务,调整。通过系统的学习和积累,提升各科成绩。
这是一篇关于十一月计划11.1-11.30的思维导图,主要内容包括:计划,目标,每日任务(1 2),调整。通过系统的学习和积累,提升各科成绩,
"十月冲刺计划:高效突破薄弱项,稳步提升各科成绩!我的1031031计划围绕三大核心:主科巩固与理科强化。数学主攻函数和不等式英语每天过单词 续写训练,目标120分物理专练步步高十个专题,冲刺75分生物通过试卷打卡突破80分。技术科目保持85分,语文利用零碎时间积累素材。每日固定任务包括国师第二阶段、英语3500词、续写素材收集,同时兼顾语文课、演讲等校园事务。时间管理上注重排队、早饭前等碎片化利用。
社区模板帮助中心,点此进入>>
这是一篇关于十二月计划(11.29-12.31)的思维导图,主要内容包括:计划,目标,每日任务,调整。通过系统的学习和积累,提升各科成绩。
这是一篇关于十一月计划11.1-11.30的思维导图,主要内容包括:计划,目标,每日任务(1 2),调整。通过系统的学习和积累,提升各科成绩,
"十月冲刺计划:高效突破薄弱项,稳步提升各科成绩!我的1031031计划围绕三大核心:主科巩固与理科强化。数学主攻函数和不等式英语每天过单词 续写训练,目标120分物理专练步步高十个专题,冲刺75分生物通过试卷打卡突破80分。技术科目保持85分,语文利用零碎时间积累素材。每日固定任务包括国师第二阶段、英语3500词、续写素材收集,同时兼顾语文课、演讲等校园事务。时间管理上注重排队、早饭前等碎片化利用。
opencv-c++ 机器人视觉向
Chapter1 读取图片/视频/摄像头
模块/功能
从文件读取图片
Mat cv::imread(const String &filename, int flags = IMREAD_COLOR)
从文件加载图像。函数imread从指定文件加载图像并返回。 如果无法读取图像(由于缺少文件、权限不正确、格式不受支持或无效),该函数将返回一个空矩阵( Mat::data==NULL )。在彩色图像的情况下,解码图像的通道将以 B G R (不是RGB)顺序存储。
Mat img = imread(path);
void cv::imshow(cosnst String &winnanme, InputArray mat)
在指定窗口中显示图像。这个函数后面应该是 cv::waitKey 函数,它显示指定毫秒的图像。否则,它不会显示图像。例如,waitKey(0) 将无限显示窗口,直到有任何按键(适用于图像显示)。 waitKey(25) 将显示一帧 25 毫秒,之后显示将自动关闭。(如果你把它放在一个循环中读取视频,它会逐帧显示视频)
imshow("Image", img);
int cv::waitKey(int delay = 0)
等待按下的键。函数 waitKey 无限等待按键事件(当 delay≤0 时)或延迟毫秒,当它为正时。由于操作系统在切换线程之间有最短时间,因此该函数不会完全等待延迟毫秒,它会至少等待延迟毫秒,具体取决于当时您计算机上正在运行的其他内容。如果在指定的时间过去之前没有按下任何键,则返回被按下键的代码或 -1。
waitKey(0); //显示图片不会一闪而过
实例
#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; int main() { string path = "Resources/test.png";//要试记得改路径 Mat img = imread(path); imshow("Image", img); waitKey(0); //显示图片不会一闪而过 return 0; }
从文件读取视频
要捕获视频,需要创建一个VideoCapture对象。它的参数可以是视频文件的名称或设备索引。以下是OpenCV3.4.6中VideoCapture类构造函数
VideoCapture()
默认构造函数,创建一个空的VideoCapture对象。
VideoCapture(int index)
创建一个VideoCapture对象并打开默认的相机设备。
VideoCapture(const String& filename, int apiPreference = CAP_ANY)
创建一个VideoCapture对象并打开指定的视频文件。
VideoCapture(const String& filename, int apiPreference, bool openCamera)
创建一个VideoCapture对象并打开指定的视频文件或相机设备。
VideoCapture(const String& filename, int apiPreference, std::vector<int> params)
创建一个VideoCapture对象并打开指定的视频文件或相机设备,并设置额外的参数。
VideoCapture(cv::io::Handle handle, int apiPreference = CAP_ANY)
创建一个VideoCapture对象并打开指定的文件句柄。
成员函数
virtual bool cv::VideoCapture::isOpened() const
如果视频捕获已经初始化,则返回true。如果先前对 VideoCapture 构造函数或VideoCapture::open()的调用成功,则该方法返回 true。
virtual bool cv::VideoCapture::read(OutputArray image)
抓取、解码并返回下一个视频帧。
virtual double cv::VideoCapture::get(int proId) const
返回指定的VideoCapture属性。
virtual double cv::VideoCapture::set(int proId, double value)
在VideoCapture中设置一个属性。
实例
#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; int main() { string path = "Resources/test_video.mp4";//要试记得改路径 VideoCapture cap(path); //视频捕捉对象 Mat img; while (true) { cap.read(img); imshow("Image", img); waitKey(1); } return 0; }
读摄像头
实例
#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; int main() { VideoCapture cap(0); Mat img; while (true) { cap.read(img); imshow("Image", img); waitKey(1); } return 0; }
Chapter2 基础函数
void cv::cvtColor(InputArray src, OutputArray dst, int code, int dstCn = 0)
将图像从一种颜色空间转换为另一种颜色空间。该函数将输入图像从一种颜色空间转换为另一种颜色空间。在从 RGB 颜色空间转换的情况下,应明确指定通道的顺序(RGB 或 BGR)。man请注意,OpenCV 中的默认颜色格式通常称为 RGB,但实际上是 BGR(字节反转)。因此,标准(24 位)彩色图像中的第一个字节将是 8 位蓝色分量,第二个字节将是绿色,第三个字节将是红色。 然后第四、第五和第六个字节将是第二个像素(蓝色,然后是绿色,然后是红色),依此类推。
概念
颜色空间
颜色空间就好比一幅画布,用来描述可见颜色的范围,就像画布上绘制的图案一样。不同的颜色空间可以用不同的画笔、调色板和调色技巧,来呈现出不同的色彩效果。常见的颜色空间有RGB、CMYK、HSV等,它们之间的差异主要在于描述颜色的方式不同,就像不同的画家选择不同的画笔和技法来表现自己的作品一样。
RGB
三种颜色的LED灯混合就能显示出彩色图片
缺点
受亮度影响大
亮度增加则RGB三个通道的值都收增加(例如你想提取图像中的红色,但只要亮度一变化,这套阈值就废了
对人来说不直观,就比如人无法想象出R:G:B=1.5:1.6:0.7是什么颜色
HSV
对颜色容忍度更高,能设立一套阈值来提取途中特定的颜色(而不受亮度干扰)——H通道截取一段即可,S和V做辅助
void cv::GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, doube sigmaY = 0, int borderType = BORDER_DEFAULT)
使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积。
概念
高斯滤波器
高斯滤波器可以看作是一种“模糊器”。就像我们在摄影或者电影中经常使用的滤镜一样,高斯滤波器通过使图像变得更加均匀来减少噪声和细节。 想像一下,你拍摄了一张照片,但是由于照相机的颤动或者光线条件的不好,图片上出现了很多小的噪点。在使用高斯滤波器之前,这些噪点将会非常明显。然而,如果你使用了高斯滤波器,它将会从像素周围的相邻像素中计算出一个新像素值,使得原始图像中的噪点将得到一定的模糊和平滑,从而使图像的质量更加清晰和自然。 这种模糊处理的程度取决于高斯核的大小和标准差。高斯核类似于一个小型的网格,可以看作是一组权重系数或者是滤波器中进行加权平均的像素值。当我们将高斯核应用于每个像素时,它会考虑周围像素的值,从而计算出一个新的像素值。由于在计算该值时,像素距离中心点越远,其权重系数越小。这样,就可以实现对图像进行模糊处理,从而减少噪点和细节。 需要注意的是,高斯滤波器虽然可以减少噪声和细节,但也会降低图像的细节和清晰度。因此,它在某些情况下可能不适用,具体取决于应用场景和需求。
卷积
卷积是一种数学运算,它通常用于信号和图像处理中。 在信号和图像处理中,我们可以将图像或信号看作是一个由一系列数字组成的矩阵或向量。卷积的基本思想是将一个小的数值核(通常称为卷积核或滤波器)从左到右、从上到下地滑动到整个矩阵或向量上,并在每个位置上进行一定的计算。计算的方式是将此位置上的矩阵或向量内的值与卷积核内的值对应相乘,然后相加得到一个新的值。这个新的值就代表了矩阵或向量在该位置上的卷积结果。 在实际应用中,卷积通常用于平滑、锐化、边缘检测、特征提取等图像处理任务中。卷积在深度学习中也有很重要的作用,例如卷积神经网络中的卷积层就是通过卷积运算实现对输入图像的特征提取。
void cv::Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false)
使用 Canny 算法在图像中查找边缘。
Canny算法的优点在于它能够在图像中找到非常明显的边缘,而忽略掉一些不显眼的边缘。同时,它还能够在不同的图像中使用相同的参数,以获得相似的结果。因此,Canny算法在计算机视觉和图像处理中得到了广泛的应用,如车辆识别、人脸识别、物体检测等。
Mat cv::getStructuringElement(int shape, Size ksize, Point anchor = Point(-1, -1))
返回指定大小和形状的结构元素,用于形态学操作。该函数构造并返回可以进一步传递给腐蚀、扩张或形态学的结构元素。 但是您也可以自己构建任意二进制掩码并将其用作结构元素。
概念
腐蚀:就像水中的一块海绵,它会吸收水中的一切,让周围的水位都下降,最终会使水位降低到它所在的位置。
在数字图像处理中,腐蚀就是将一个固定大小和形状的模板(也称为结构元素)从图像中滑动,当模板完全覆盖图像中的一个像素时,将这个像素周围的像素值按照结构元素的形状进行比较,如果这些像素都大于或等于中心像素的值,则将中心像素的值保留下来,否则将其设为零。这个过程就像海绵吸收水一样,将周围的像素"吸收"到中心像素中,其结果是物体或图形边缘被磨损或消失。
扩张:就像在一张纸上涂上大量的颜料,颜料会从中心点不断扩散出去,让周围的区域被染色。
在数字图像处理中,扩张则是将一个结构元素从图像中滑动,当结构元素覆盖到图像中的一个像素时,将这个像素周围的像素值与中心像素的值进行比较,如果这些像素中有任意一个像素大于等于中心像素的值,则将中心像素的值保留下来,否则将其设为零。这个过程就像颜料从中心点不断扩散出去一样,将中心像素的颜色或灰度值向周围像素扩散,最终产生区域和轮廓的扩大效果。
形态学的结构元素:就像一个自定义的形状的橡皮图章,可以用它来涂抹在图片上,只有这个形状内的像素会被改变,外面的像素不变。
在数字图像处理中,形态学的结构元素就是一个自定义的模板或形状,常用于腐蚀和扩张操作中。如方形、圆形、十字形、椭圆形等,可以根据需要自由定义。在图像处理中,结构元素决定了腐蚀和膨胀操作的效果,通过不同大小和形状的结构元素,可以改变图像的形态、尺寸和纹理,实现对图像的形态学处理。
void cv::dilate(InputArray src, OutputArray dst, InuputArray kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue())
使用特定的结构元素膨胀图像。
void cv::erode(InputArray src, OutputArray dst, InuputArray kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue())
使用特定的结构元素腐蚀图像。
实例
#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; int main() { string path = "resources/test.png"; Mat img = imread(path); Mat imgGray, imgBlur, imgCanny, imgDil, imgErode; cvtColor(img, imgGray, COLOR_BGR2GRAY); //灰度化 GaussianBlur(img, imgBlur, Size(3, 3), 3, 0); //高斯模糊 Canny(imgBlur, imgCanny, 25, 75); //边缘检测 Mat kernel = getStructuringElement(MORPH_RECT, Size(3,3)); dilate(imgCanny, imgDil, kernel); erode(imgDil, imgErode, kernel); imshow("Image", img); imshow("ImageGray", imgGray); imshow("ImageBlur", imgBlur); imshow("ImageCanny", imgCanny); imshow("ImageDilation", imgDil); imshow("ImageErode", imgErode); waitKey(0); return 0; }
灰度化
高斯模糊
边缘检测
膨胀
腐蚀
Chapter8 图像形态学
膨胀
腐蚀
开与闭
开:腐蚀再膨胀,去除微小干扰块。
闭:膨胀再腐蚀,填充闭合区域。·
形态学梯度
基本梯度:膨胀图 - 腐蚀图
内梯度:原图 - 腐蚀图
外梯度:膨胀图 - 原图
这里opencv只能直接实现基本梯度,在使用API:morphologyEx 时,调用MORPH_GRADIENT方法即可。
内梯度、外梯度没有直接的API,一般通过已有API间接实现。
其余形态学操作
Chapter9 矩的计算
Chapter10 图像滤波
Chapter11 图像分割
Chapter12 单目视觉*
Chapter13 跟踪算法*
Chapter6 颜色检测
void cv::inRange (InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst)
检查数组元素是否位于其他两个数组的元素之间。
void cv::namedWindow (const String &winname, int flags = WINDOW_AUTOSIZE)
创建一个窗口。函数namedWindow创建一个可用作图像和轨迹栏占位符的窗口。创建的窗口由它们的名称引用。如果同名的窗口已经存在,则该函数不执行任何操作。
int cv::createTrackbar (const String &trackbarname, const String &winname, int *value, int count, TrackbarCallback onChange = 0, void *userdata = 0)
创建一个trackbar并将其附加到指定窗口。函数createTrackbar创建一个具有指定名称和范围的trackbar(滑块或范围控件),分配一个变量值作为与trackbar同步的位置,并指定回调函数onChange为 在跟踪栏位置变化时被调用。创建的轨迹栏显示在指定的窗口winname中。
实例
#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; Mat imgHSV, mask; // 输入图像的HSV颜色空间表示(可以更方便地调整颜色阈值,并更好地检测出指定颜色的物体)和颜色过滤器的输出二值化图像 int hmin = 0, smin = 110, vmin = 153; // 颜色过滤器的下限 int hmax = 19, smax = 240, vmax = 255; // 颜色过滤器的上限 int main() { string path = "resources/lambo.png"; // 输入图像的路径 Mat img = imread(path); // 读取输入图像 cvtColor(img, imgHSV, COLOR_BGR2HSV); // 将输入图像转换到HSV颜色空间 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, 2555); while (true) { Scalar lower(hmin, smin, vmin); // 根据轨迹条的值设置颜色过滤器的下限 Scalar upper(hmax, smax, vmax); // 根据轨迹条的值设置颜色过滤器的上限 inRange(imgHSV, lower, upper, mask); // 根据颜色过滤器的下限和上限,计算符合条件的像素,输出二值化图像 imshow("Image", img); // 在窗口中展示原始图像 imshow("Image HSV", imgHSV); // 在窗口中展示HSV颜色空间的图像 imshow("Image Mask", mask); // 在窗口中展示颜色过滤器的输出二值化图像 waitKey(1); // 在两帧图像之间暂停一段时间 } return 0; }
原图(检测枫红色)
HSV图像
颜色检测后输出二值化图像
参数轨迹条
概念辨析
BGR/HSV
将图像从BGR(或RGB)颜色空间转换为HSV颜色空间可以更方便地调整颜色阈值,并更好地检测出指定颜色的物体。在BGR颜色空间中,颜色由三个通道(蓝色、绿色、红色)组成,而在HSV颜色空间中,颜色由三个参数(色相、饱和度、亮度)组成。HSV颜色空间中的色相参数可以帮助我们更方便地调整图像的颜色范围,而饱和度和亮度参数可以帮助我们控制图像的鲜艳度和亮度,从而更好地检测出指定颜色的物体。因此,将图像从BGR颜色空间转换为HSV颜色空间是一种非常常用的处理方法。
H(色调),S(饱和度)和V(亮度)
颜色过滤器
颜色过滤器是一种图像处理工具,可用于从图像中提取特定颜色的像素。它通常用于计算机视觉和机器人领域中的目标检测和跟踪。它基于预定义的颜色范围来过滤图像并提取所需颜色的像素。颜色过滤器可以使用不同的颜色空间(例如RGB、HSV等)和不同的参数(例如颜色范围、颜色通道、亮度、饱和度等)来实现不同的目标检测效果。在实际应用中,颜色过滤器可以用于道路标志检测、人脸跟踪、工业自动化、医学成像等各种领域。
想象你正在一张彩色照片中寻找一个颜色为红色的物体。你可以使用颜色过滤器,将除了红色之外的所有颜色都过滤掉,只显示红色的像素。这就像在一堆彩色珠子中寻找红色珠子。使用颜色过滤器就像是将所有的珠子都过滤一遍,只保留红色珠子,使它们在最终结果中更加明显和突出。颜色过滤器可以帮助计算机更加有效地处理图像,提取出我们想要的信息和关键特征。它是许多计算机视觉和机器人应用中非常实用的工具。
轨迹条
Chapter5 透视变换
Mat cv::getPerspectiveTransform (const Point2f src[], const Point2f dst[])
返回相应 4 个点对的 3x3 透视变换。
void cv::warpPerspective (InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar &borderValue=Scalar())
对图像应用透视变换。
实例(图像扫描用的比较多)
#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; float w = 250, h = 350; Mat matrix, imgWarp; int main() { string path = "Resources/cards.jpg"; Mat img = imread(path); Point2f src[4] = { {529, 142}, {771, 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)); for (int i = 0; i < 4; i++) { circle(img, src[i], 10, Scalar(0, 0, 255), FILLED); } imshow("Image", img); imshow("ImageWarp", imgWarp); waitKey(0); return 0; }
Chapter4 绘制形状和文字*
Mat(int rows, int cols, int type, const Scalar &s)
重载的构造函数
void cv::circle(InputOutputArray img, Point center, int radius, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
函数 cv::circle 用给定的中心和半径绘制一个简单的或实心圆。
void cv::rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
void cv::rectangle(Mat &img, Rect rec, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
绘制一个简单的、粗的或填充的右上矩形。函数 cv::rectangle 绘制一个矩形轮廓或两个对角为 pt1 和 pt2 的填充矩形。
void cv::line (InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
绘制连接两点的线段。函数line绘制图像中 pt1 和 pt2 点之间的线段。
void cv::putText (InputOutputArray img, const String &text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=LINE_8, bool bottomLeftOrigin=false)
绘制一个文本字符串。函数 cv::putText 在图像中呈现指定的文本字符串。无法使用指定字体呈现的符号将替换为问号。
Chapter3 调整和剪裁
void cv::resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation = INTER_LINEAR)
调整图像的大小。函数 resize 将图像 src 的大小缩小到或最大到指定的大小。请注意,不考虑初始 dst 类型或大小。相反,大小和类型是从 src、dsize、fx 和 fy 派生的。
实例
#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; int main() { string path = "resources/test.png"; Mat img = imread(path); Mat imgResize, imgCrop; cout << img.size() << endl; resize(img, imgResize, Size(), 0.5, 0.5); Rect roi(200, 100, 300, 300); imgCrop = img(roi); imshow("Image", img); imshow("ImageResieze", imgResize); imshow("ImageCrop", imgCrop); waitKey(0); return 0; }
参考文献
https://blog.csdn.net/Star_ID/article/details/122656593
InsCode AI
Chapter7 形状/轮廓检测
void cv::findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point())
在二值图像中查找轮廓。
参数
概念辨析
形状/轮廓
形状通常是一个封闭的图形,具有一定的几何属性,例如矩形、圆形和多边形等。我们可以使用OpenCV中提供的函数来创建、绘制和操作这些形状。形状通常用于标识和处理特定区域,例如在图像分割、对象识别和检测等方面。
轮廓是形状的边界线,通常表示为一组连续的点。在OpenCV中,我们通常使用轮廓来描述和分析图像中的对象。可以使用一些轮廓函数来检测、提取和分析轮廓。
因此,形状是由一组连续的轮廓所定义的,形状的属性可以通过对其轮廓进行分析来获得。在OpenCV中,我们可以使用形状和轮廓来实现许多图像处理和计算机视觉任务,例如图像分割、对象检测和跟踪等。