【贪玩巴斯】角点预检测 涉及知识详解——「Opencv库以及内置函数namedWindow(),cvResizeWindow(),cvFindChessboardCorn的详解」2021-10-29

1.Opencv

定义:

OpenCV,它是一个图像和视频处理库,包含 C ++,C,Python 和 Java 的绑定。 OpenCV 用于各种图像和视频分析,如面部识别和检测,车牌阅读,照片编辑,高级机器人视觉,光学字符识别等等。
OpenCV作为强大的计算机视觉开源库,很大程度上参考了MatLab的实现细节和风格,比如说,在OpenCV2.x 版本以后,越来越多的函数实现了MatLab具有的功能,甚至干脆连函数名都一模一样(如 imread, imshow,imwriter等)。这一做法,不仅拉近了产品开发与学术研究的距离,并极大程度的提高了开发人员的研发效率,不得不说,Intel公司真的是一个伟大的公司。

在计算机内存中,数字图像以矩阵的形式存储和运算,比如,在MatLab中,图像读取之后对应一个矩阵,在OpenCV中,同样也是如此。

理解核心:

我们有多种方法可以获得从现实世界的数字图像:数码相机、扫描仪、计算机体层摄影或磁共振成像就是其中的几种。在每种情况下我们(人类)看到了什么是图像。但是,转换图像到我们的数字设备时我们的记录是图像的每个点的数值。

你看到的任何照片只是一个包含所有强度值的像素点矩阵。现在,我们如何获取和存储像素值可能根据最适合我们的需要而变化,最终可能减少计算机世界内的所有图像数值矩阵和一些其他的信息的描述基质本身。OpenCV 是一个计算机视觉库,其主要的工作是处理和操作,进一步了解这些信息。因此,你需要学习和开始熟悉它的第一件事是理解OpenCV 是如何存储和处理图像。

头文件:

#include <opencv2/opencv.hpp>
头文件定义类似如下:

#include <opencv2/opencv.hpp>

#ifndef_OPENCV_ALL_HPP_

#define_OPENCV_ALL_HPP_
#include “opencv2/core/core_c.h”
#include “opencv2/core/core.hpp”
#include “opencv2/flann/miniflann.hpp”
#include “opencv2/imgproc/imgproc_c.h”
#include “opencv2/imgproc/imgproc.hpp”
#include “opencv2/photo/photo.hpp”
#include “opencv2/video/video.hpp”
#include “opencv2/features2d/features2d.hpp”
#include “opencv2/objdetect/objdetect.hpp”
#include “opencv2/calib3d/calib3d.hpp”
#include “opencv2/m1/m1.hpp”
#include “opencv2/highgui/highgui_c.h”
#include “opencv2/highgui/highgui.hpp”
#include “opencv2/contrib/contrib.hpp”
#endif

opencv.hpp已经包含了OpenCV各模块的头文件,所以在编写core、objdetect、imgproc、photo、features2d、calib3d、m1、highgui、contrib模块的应用程序时,原则上仅写一句“# include <opencv2/opencv.hpp>”即可。

2.time.h

time.h 是C++常用标准库之一

有人总结成这么几句,的确是经典:
两个类型:
time_t:表示距离 UTC 时间 1970-01-01 00:00:00 的秒数。也叫做日历时,类型是 long
clock_t: 只用于程序计时,貌似其他的没它什么事。
struct tm:通常用于存储本地时。

常用函数:

clock: 获取程序开始执行后占用的处理器时间,返回值clock_t。
time: 获取当前系统时间(UTC时间)的time_t值。
ctime: 将time_t值转换为表示本地时间的字符串。
gmttime: 将time_t值转换为表示GMT时间的字符串。
localtime:将time_t转换为表示本地时间的strunct tm结构。
mktime: 将表示本地时间的struct tm转换为time_t。
asctime: 将struct tm转换为字符串形式。
difftime: 得到两个日历时之间的差值。
strftime: 自定义把结构体tm的日期与时间信息转换为制定的格式。

3.windows.h 头文件

WINDOWS.H是一个最重要的头文件,它包含了其他Windows头文件,这些头文件的某些也包含了其他头文件。这些头文件中最重要的和最基本的是:
1、WINDEF.H 基本数据类型定义。
2、WINNT.H 支持Unicode的类型定义。
3、WINBASE.H Kernel(内核)函数。
4、WINUSER.H 用户界面函数。
5、WINGDI.H 图形设备接口函数。

4.usingnamespace cv

开启cv命名空间
——
OpenCV的函数都位于cv这一命名空间下,为了调用OpenCV的函数,需要在每个函数前加上cv::,向编译器说明你所调用的函数处于cv命名空间。为了摆脱这种繁琐的工作,可以使用using namespace cv;指令,告诉编译器假设所有函数都位于cv命名空间下。

这样确实可以简化一点工作,但是有可能会造成别的麻烦,这样做需要冒和其他潜在的命名空间冲突的风险。
——如果函数foo()已经存在于cv和std(标准函数)的命名空间,你必须指定自己使用的是位于cv::foo()的函数还是位于std::foo()的函数。所以即使开启了cv的命名空间,显示的标明函数来自cv::命名空间能够避免一些不必要的麻烦,保持一个良好的编程风格。

Mat类详解

历史

在早期的OpenCV1.x版本中,图像的处理是通过IplImage(该名称源于Intel的另一个开源库Intel Image Processing Library ,缩写成IplImage)结构来实现的。早期的OpenCV是用C语言编写,因此提供的借口也是C语言接口,其源代码完全是C的编程风格。IplImage结构是OpenCV矩阵运算的基本数据结构。

到OpenCV2.x版本,OpenCV开源库引入了面向对象编程思想,大量源代码用C++重写,Mat类 (Matrix的缩写) 是OpenCV用于处理图像而引入的一个封装类。从功能上讲,Mat类在IplImage结构的基础上进一步增强,并且,由于引入C++高级编程特性,Mat类的扩展性大大提高,Mat类的内容在后期的版本中不断丰富,如果你查看Mat类的定义的话(OpenCV3.1\sources\modules\core\include\opencv2\core\mat.hpp),会发现其设计实现十分全面而具体,基本覆盖计算机视觉对于图像处理的基本要求。

具体含义

Mat本质上是由两个数据部分组成的类
矩阵头:(包含信息有矩阵的大小,用于存储的方法,矩阵存储的地址等)
一个指针:指向包含了像素值的矩阵(可根据选择用于存储的方法采用任何维度存储数据)。

矩阵头部的大小是恒定的。然而,矩阵本身的大小因图像的不同而不同,通常是较大的数量级。
因此,当在您的程序中传递图像并在有些时候创建图像副本,您需要花费很大的代价生成图像矩阵本身而不是图像的头部

OpenCV 是图像处理库,它包含大量的图像处理函数。若要解决的计算挑战,最终大部分时间你会使用库中的多个函数。由于这一原因图像传给库中的函数是一种常见的做法。我们不应忘记我们正在谈论往往是计算量相当大的图像处理算法

问题引入:——我们想要做的最后一件事是通过制作不必要的可能很大的图像的拷贝进一步降低您的程序的速度。

解决办法:——为了解决这一问题 OpenCV 使用引用计数系统
其思想是Mat的每个对象具有其自己的头,但可能他们通过让他们矩阵指针指向同一地址的两个实例之间共享该矩阵。

此外,拷贝运算符将只能复制矩阵头部,也还将复制指针到大型矩阵,但不是矩阵本身。

5.数据类型Point2f

理解

对Point2f 和vector的理解
——
Point2f表示Point类的两个数据x,y为float类型;
vector 表示存放四维int

point类简介

暂且将其称呼为:点类

作为opencv的基础类型,point类可能是最简单的。它的实现基于一个基础模板结构(由自己的模板派生而来),也可以从固定向量类(cv::Vec<>)转换得到。

cv::Point类与固定向量类之间最大的不同是他们的成员是通过名称变量访问的(mypoint.x,mypoint.y等)而不是通过下标访问(myvec[0],myvec[1]等)。和cv::Vec<>一样,Point类是通过别名调用作为一个正确模板的实例。这些别名可以是cv::Point2i,cv::Point2f,cv::Point2d或cv::Point3i,cv::Point3f,cv::Point3d。

由于它们是基于一个基础模板结构,所以它们可以成为任何类型的点,如整型和浮点型等。这里实际上由两个这样的模板,一个是给二维点提供的,另一个是给三维点提供的。Point类的巨大优势在于它们简单且开销小。原生上并没有对它们定义很多操作,但它们可以转换成更广义的类型,比如在需要的时候可以转换为固定向量类或者是固定矩阵类。

大多数程序中,Point类是通过类似于cv::Point2i和cv::Point3f这类别名来实例化的,这些别名的最后一个字母表示构造该点所需要的原语(b是一个无符号字符,s是一个短整型,i是一个32位整型,f是一个32位浮点数,d是一个64位浮点数)

6 Size类

Size类
相比Point类,
1.数据成员不同,Size类成员为width 和 height
2.不能转换成固定大小的Vector类,但Vector类和Point类可以转换成Size类

Size类存在三种别名 Size 、Size2i、Size2f,Size2d前面两个是等价的
typedef Size_ Size2i;
typedef Size_ Size2l;
typedef Size_ Size2f;
typedef Size_ Size2d;
typedef Size2i Size;

Size() 关于行列问题

https://blog.csdn.net/u010811512/article/details/71192471?ops_request_misc=&request_id=&biz_id=102&utm_term=Size(8,11)%20是先列后行?&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-71192471.first_rank_v2_pc_rank_v29&spm=1018.2226.3001.4187

7.opencv库中的namedWindow()函数

namedWindow()的功能就是新建一个显示窗口。
可以指定窗口的类型。

原型:void nameWindow(const string& winname,int flags = WINDOW_AUTOSIZE) ;

参数1:新建的窗口的名称。自己随便取。
参数2:窗口的标识,一般默认为WINDOW_AUTOSIZE 。
——
WINDOW_AUTOSIZE 窗口大小自动适应图片大小,并且不可手动更改。
WINDOW_NORMAL 用户可以改变这个窗口大小
WINDOW_OPENGL 窗口创建的时候会支持OpenGL

8.cvResizeWindow 和 cvMoveWindow 函数的使用

/* resize/move window /
CVAPI(void) cvResizeWindow( const char
name, int width, int height );
CVAPI(void) cvMoveWindow( const char* name, int x, int y );

cvResizeWindow():用来调整窗口的大小
width/height:以像素为单位,指定窗口中可以显示的部分
cvMoveWindow():将窗口移动到其左上角为x,y的位置

9.cvFindChessboardCorners

函数cvFindChessboardCorners试图确定输入图像是否是棋盘模式,并确定角点的位置。如果所有角点都被检测到且它们都被以一定顺序排布,函数返回非零值,否则在函数不能发现所有角点或者记录它们地情况下,函数返回0。例如一个正常地棋盘图右8x8个方块和7x7个内角点,内角点是黑色方块相互联通的位置。这个函数检测到地坐标只是一个大约的值,如果要精确地确定它们的位置,可以使用函数cvFindCornerSubPix。

函数形式
int cvFindChessboardCorners( const void* image, CvSize pattern_size, CvPoint2D32f* corners, int* corner_count=NULL, int flags=CV_CALIB_CB_ADAPTIVE_THRESH );

参数说明

Image:

输入的棋盘图,必须是8位的灰度或者彩色图像。

pattern_size:

棋盘图中每行和每列角点的个数。

Corners:

检测到的角点

corner_count:
输出,角点的个数。如果不是NULL,函数将检测到的角点的个数存储于此变量。

Flags:
各种操作标志,可以是0或者下面值的组合:

CV_CALIB_CB_ADAPTIVE_THRESH -使用自适应阈值(通过平均图像亮度计算得到)将图像转换为黑白图,而不是一个固定的阈值。

CV_CALIB_CB_NORMALIZE_IMAGE -在利用固定阈值或者自适应的阈值进行二值化之前,先使用cvNormalizeHist来均衡化图像亮度。

CV_CALIB_CB_FILTER_QUADS -使用其他的准则(如轮廓面积,周长,方形形状)来去除在轮廓检测阶段检测到的错误方块。

10.drawChessboardCorners()棋盘格角点的绘制

cv::drawChessboardCorners()的具体调用形式如下:

void cv::drawChessboardCorners(
	cv::InputOutputArray image, // 棋盘格图像(8UC3)即是输入也是输出
	cv::Size patternSize, // 棋盘格内部角点的行、列数
	cv::InputArray corners, // findChessboardCorners()输出的角点
	bool patternWasFound // findChessboardCorners()的返回值
);

第一个参数是棋盘格图像(8UC3)。

第二个参数是棋盘格内部角点的行、列,和cv::findChessboardCorners()指定的相同。

第三个参数是检测到的棋盘格角点。

第四个参数是cv::findChessboardCorners()的返回值。

11.waiteKey()

waitKey()是OpenCV中的内置函数。

语句waitKey(0);表示“暂停程序,等待一个按键输入”!也就是说,当程序执行到waitKey(0);时,程序被暂停运行,只有当你输入一个按键时,它才会继续运行。
  
语句waitKey()相当于waitKey()。语句waitKey(1000),表示程序暂停执行1000毫秒!

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贪玩巴斯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值