opencv_opencv3 - CSDN
opencv 订阅
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 [1]  它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。OpenCV用C++语言编写,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS,OpenCV主要倾向于实时视觉应用,并在可用时利用MMX和SSE指令, 如今也提供对于C#、Ch、Ruby,GO的支持。 [2] 展开全文
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 [1]  它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。OpenCV用C++语言编写,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS,OpenCV主要倾向于实时视觉应用,并在可用时利用MMX和SSE指令, 如今也提供对于C#、Ch、Ruby,GO的支持。 [2]
信息
开发商
OpenCV
软件授权
Intel、Willow Garage、NVIDIA等 [3]
软件名称
OpenCV
更新时间
2020-04-06
软件版本
OpenCV–4.3.0 [2]
软件平台
Linux、Windows、Android、Mac OS等
软件语言
C++
软件大小
1.16GB
opencv历史发展
OpenCV 拥有包括 500 多个C函数的跨平台的中、高层 API。它不依赖于其它的外部库——尽管也可以使用某些外部库。OpenCV 为Intel® Integrated Performance Primitives(IPP)提供了透明接口。这意味着如果有为特定处理器优化的 IPP 库,OpenCV 将在运行时自动加载这些库。 [4]  (注:OpenCV 2.0版的代码已显著优化,无需IPP来提升性能,故2.0版不再提供IPP接口) [5]  最新版本是3.4 ,2017年12月23日发布 [6]  。1999年1月,CVL项目启动。主要目标是人机界面,能被UI调用的实时计算机视觉库,为Intel处理器做了特定优化。2000年6月,第一个开源版本OpenCV alpha 3发布。2000年12月,针对linux平台的OpenCV beta 1发布。2006年,支持Mac OS的OpenCV 1.0发布。2009年9月,OpenCV 1.2(beta2.0)发布。2009年10月1日,Version 2.0发布。2010年12月6日,OpenCV 2.2发布。2011年8月,OpenCV 2.3发布。2012年4月2日,发布OpenCV 2.4。2014年8月21日,发布OpenCv 3.0 alpha。2014年11月11日,发布OpenCV 3.0 beta。2015年6月4日,发布OpenCV 3.0。2016年12月,发布OpenCV 3.2版(合并969个修补程序,关闭478个问题)2017年8月3日,发布OpenCV 3.3版(最重要的更新是把DNN模块从contrib里面提到主仓库)OpenCV 使用类BSDlicense,所以对非商业应用和商业应用都是免费(FREE)的。(细节参考 license)OpenCV提供的视觉处理算法非常丰富,并且它部分以C语言编写,加上其开源的特性,处理得当,不需要添加新的外部支持也可以完整的编译链接生成执行程序,所以很多人用它来做算法的移植,OpenCV的代码经过适当改写可以正常的运行在DSP系统和ARM嵌入式系统中,这种移植在大学中经常作为相关专业本科生毕业设计或者研究生课题的选题。
收起全文
  • 基于OpenCV最新版本OpenCV4开始,从基础开始,详解OpenCV核心模块Core、Imgproc、video analysis核心API与相关知识点,讲解从图像组成,像素操作开始,一步一步教你如何写代码,如何用API解决实际问题,从图像处理到...
  • Python+OpenCV计算机视觉

    2018-12-28 17:42:46
    Python+OpenCV计算机视觉系统全面的介绍。
  • OpenCV视频分析与对象跟踪实战视频培训课程概况:基于OpenCV新版本3.2 从基本的OpenCV视频读写与摄像头输入视频API讲解开始, 用原理与代码实现相结合的方式讲述了视频背景建模、前景ROI对象获取、特定颜色对象发现与...
  • OpenCV 概述

    2014-03-09 16:36:39
    OpenCV概述 OpenCV是Intel开元计算机视觉库,它有一系列开源的C函数和少量C++类构成,实现了图像处理和计算机视觉很多通用的算法。 OpenCV特点: 1.拥有包括300多个C函数的跨平台的中、高层API; 2.跨平台:...

    OpenCV概述

    OpenCV是Intel开元计算机视觉库,它有一系列开源的C函数和少量C++类构成,实现了图像处理和计算机视觉很多通用的算法。


    OpenCV特点:

    1.拥有包括300多个C函数的跨平台的中、高层API;

    2.跨平台:Windows/Linux;

    3.Free:无论是对于商业还是非商业应用;

    4.速度快;

    5.使用方便。


    OpenCV结构:


    CXCORE:包含数据结构、矩阵运算、数据变换、对象持久(Object Persistence)、内存管理、错误处理、动态连接、绘图、文本和基本的数学功能。

    CV:包含图形处理、图像结构分析、运动描述和跟踪、模式识别和摄像机标定。

    Machine Learning(ML):包含许多聚类,分类和数据分析函数。

    HighGUI:包含图形用户界面和图像/视频的读/写。

    CVCAM:摄像机接口,在OpenCV1.0以后的版本中被移除。


    OpenCV编码样式指南:

    文件命名:有CV和CVAUS库文件的命名必须服从于以下规则:

    1.所有的CV库文件名前缀为cv;

    2.混合的C/C++接口头文件扩展名为.h;

    3.纯C++接口头文件扩展名为.hpp;

    4.实现头文件扩展名为.cpp;

    5.为了与POSIX兼容,文件名都以小写字符组成。


    命名约定:

    1.OpenCV中使用大小写混合样式来标识外部函数、数据类型和类方法。

    2.宏全部使用大写字符,词间用下划线分隔。

    3.所有的外部或内部名称,若在多个文件中可见,则必须含有前缀:

       外部函数使用前缀cv;

       内部函数使用前缀lcv;

       数据结构(C结构体、枚举、联合体和类)使用前缀CV

       外部或某些内部宏使用前缀CV_

       内部宏使用前缀ICV_


    接口函数设计:

       为了保持库的一致性,以如下方式设计接口非常关键。函数接口元素包括:功能、名称、返回值、参数类型、参数顺序和参数默认值。

       函数功能必须定义良好并保持精简。函数应该容易镶入到使用其它OpenCV函数的不同处理过程。函数名称应该简单并能体现函数的功能。

       大多数函数名形式:cv<ActionName>


    图像处理---平滑处理

      “平滑处理”也称为“模糊处理”,是一项简单且使用频率很高的图像处理方法。平滑处理最常见的用途是用来减少图像上的噪声或者失真。目前OpenCV中,所有平滑处理操作都由cvSmooth函数实现。

    函数说明:

    void cvSmooth(const CvArr* src, CvArr* dst, int smoothtype=CV_GAUSSIAN, int param1=3, int param2=0, double param3=0, double param4=0);

      src和dst分别是平滑操作的输入头像和结果,cvSmooth()函数包含4个参数:param1-param4. 这些参数的含义取决于smoothtype的值。


    图像处理---图像形态学

      OpenCV为进行图像形态学变换提供了快速、方便的函数,基于形态学的转换是膨胀与腐蚀,他们能够实现多种功能:消除噪声,分隔出独立的图像元素以及在图像中连接相邻的元素。

      膨胀是指将一个图像(或图像中的一部分区域,称之为A)与核(称之为B)进行卷积。即,计算核B覆盖区域的像素最大值,并把这个最大值赋值给参考点指定的坐标。这样就会使图像中的高亮区域逐渐增大。

      腐蚀是膨胀的反操作。腐蚀操作要求计算核区像素的最小值。即,当核B与图像卷积时,计算被核B覆盖区域的最小像素值,并把这个值放到参考点。

      在OpenCV,利用cvErode()和cvDilate()函数实现上述变换:

    void cvErode(lplImage* src, lplIMage* dst, lpIlConvKernel* B=NULL, int iterations=1);

    void cvDilate(lplImage* src, lplIMage* dst, lpIlConvKernel* B=NULL, int iterations=1);

    该两个函数的第三个参数是核,默认值是NULL。当为空时,所使用的是参考点位于中心的3*3核。第四个参数是迭代的次数。

    开运算:将二值图像先腐蚀,然后,再膨胀,通常用来统计二值图像中的区域数。开运算则去除一些小的斑点。

    闭运算:将二值图像先膨胀,然后,再腐蚀,通常用来去除噪声引起的区域。闭运算使得小洞被填上,临近的目标连接到了一起(任何结构元容纳不下的小洞或者缝隙都会被填充)。

      对于连通区域分析,通常先采用腐蚀或者闭运算来消除纯粹由噪声引起的部分,然后用开运算来连接临近的区域。最显著的效果是,闭运算消除了低于临近点的孤立点,而,开运算是消除高于其临近点的孤立点。 


    图像处理---拉普拉斯变换

    OpenCV的拉普拉斯函数实现了拉普拉斯算子的离散模拟。

    OpenCV中,拉普拉斯变换函数为:

    void cvLaplace(const CvArr* src, CvArr* dst, int apertureSize=3);

    该函数通常把源图像和目标图像以及中控大小作为变量。源图像既可以是8位(无符号)图像,也可以是32位(浮点)图像。而目标图像必须是16位(有符号)或者32位(浮点)图像。因为拉普拉斯算子的形式是沿着X轴和Y轴的二次导数的和,这就意味着周围是更高值的单电或者小块会将使这个函数值最大化。反过来,周围是更低值的点将会是函数的负值最大化。反过来,周围是更低值的点将会是函数的负值最大化。基于这种思想,拉普拉斯也可以用于边缘检测。


    图像处理---Cannay算子

      Canny边缘检测法与基于拉普拉斯算法的不同点之一是在Canny算法中,首先在x和y方向求一阶导数,然后,组合为4个方向的导数。这些方向导数达到局部最大值的点就是组成边缘的候选点。另外,Canny算法的最终要的新特点是阈值的概念,如果一个像素的梯度大于上线阈值,则被认为是边缘像素,如果低于下限阈值,则被抛弃,如果介于二者时间,只有当其与高于上限阈值的像素连接时才会被接受。Canny推荐的上下限阈值比为2:1到3:1之间。

      void cvCanny(const CvArr* img, CvArr* edges, double lowThresh, double highThresh, int apertureSize=3);

      此函数是需要输入一张灰度图,输出也是灰度的。


      形态学操作

      形态学操作主要有四种:腐蚀、膨胀、开和闭。最基本的形态学操作是腐蚀和膨胀。其他的操作都可以通过腐蚀和膨胀推导出来。

      用集合论的观点介绍他们很繁琐。这里换一种思路,如下:

      我们先做一定的假设:对于一幅图像,前景(我们感兴趣的部分);背景(不感兴趣的部分)是黑色的。然后就可以望文生义一下了,腐蚀操作会使得前景变小,而膨胀会使得前景变大。这主要是当结构元(用来对图像处理的基本模板)作用于图像的边沿时,两种操作的定义引起的。腐蚀操作时,只有当整个结构元都在图像边沿内时,锚点(结构元与图像中每个像素对其的点,通常取作结构元的几何中心)对准的像素才会被保留,判为前景;否则,这个点判为背景。膨胀操作则是只要结构元与图像有交集时,锚点对准的像素就会被保留,判为前景。腐蚀可以用来消除一些小的误检测的前景;而膨胀则可以填充一些小洞。

      注意到,用3*3的模板腐蚀3次与用7*7的模板腐蚀一次效果是相同的。膨胀的结果可以类推。

      

    展开全文
  • Opencv学习(一)

    2018-10-05 16:12:06
    Opencv学习笔记(一) 1、Image Watch 图像监视是微软VisualStudio的插件,它允许您在调试应用程序时在内存映像中可视化。这有助于跟踪错误,或者简单地理解给定代码的操作。 可以在vs里面的工具--&amp;...

    1、Image Watch

    图像监视是微软VisualStudio的插件,它允许您在调试应用程序时在内存映像中可视化。这有助于跟踪错误,或者简单地理解给定代码的操作。

    可以在vs里面的工具-->扩展和更新里面获取Image Watch

    然后再视图-->其他窗口调用。

    2、Load and Display an Image

    Code

    #include <opencv2/core/core.hpp>
    #include <opencv2/imgcodecs.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <iostream>
    #include <string>
    using namespace cv;
    using namespace std;
    int main(int argc, char** argv)
    {
    	string imageName("1.jpg"); // by default
    	if (argc > 1)
    	{
    		imageName = argv[1];
    	}
    	Mat image;
    	image = imread(imageName.c_str(), IMREAD_COLOR); // Read the file
    	if (image.empty())                      // Check for invalid input
    	{
    		cout << "Could not open or find the image" << std::endl;
    		return -1;
    	}
    	namedWindow("Display window", WINDOW_AUTOSIZE); // Create a window for display.
    	imshow("Display window", image);                // Show our image inside it.
    	waitKey(0); // Wait for a keystroke in the window
    	return 0;
    }
    

    vs2017中使用命令行参数调试程序

    在这里插入图片描述

    Explanation

    现在我们调用CV::imRead函数,它加载由第一个参数指定的图像名称(ARGV〔1〕)。第二个参数指定了我们想要的图像的格式。

    IimeRead不变(<0)按原样加载图像(包括alpha通道,如果存在)

    IimeRead灰度(0)将图像加载为强度图像。

    IdRead颜色(> 0)以RGB格式加载图像

    image = imread(imageName.c_str(), IMREAD_COLOR); // Read the file
    

    在检查图像数据被正确加载之后,我们想要显示我们的图像,所以我们使用CV::NAMEDLE窗口函数创建OpenCV窗口。一旦创建了OpenCV,它们就会自动管理。为此,您需要指定它的名称以及它应该如何从大小的角度来处理它包含的图像的变化。

    如果不使用QT后端,则只支持WistWOWAutoSead。在这种情况下,窗口大小将占用它所显示的图像的大小。不允许调整大小!

    Qt上的Windows WORKWORD,您可以使用它来允许窗口调整大小。图像将根据当前窗口大小调整自身大小。通过使用该运算符,还需要指定是否希望图像保持其纵横比(WOWDOWKEEPRATIO)或不(WOWDOWFRIERATIO)。

    namedWindow( "Display window", WINDOW_AUTOSIZE ); // Create a window for display.
    

    最后,使用新的图像更新OpenCV窗口的内容,使用imshow函数。指定要更新的OpenCV窗口名称和在此操作期间要使用的图像:

     imshow( "Display window", image ); // Show our image inside it.
    

    因为我们希望我们的窗口显示出来,直到用户按下一个键(否则程序将结束得太快),我们使用CV::WaWiKEY函数,它的唯一参数是它等待用户输入的时间(毫秒测量)。零意味着永远等待。

    waitKey(0); // Wait for a keystroke in the window
    

    3、Load, Modify, and Save an Image

    Code:

    #include <opencv2/opencv.hpp>
    using namespace cv;
    using namespace std;
    int main(int argc, char** argv)
    {
    	char* imageName = argv[1];
    	Mat image;
    	image = imread(imageName, 1);
    	if (argc != 2 || !image.data)
    	{
    		printf(" No image data \n ");
    		return -1;
    	}
    	Mat gray_image;
    	cvtColor(image, gray_image, COLOR_BGR2GRAY);
    	imwrite("Gray_Image.jpg", gray_image);
    	namedWindow(imageName, WINDOW_AUTOSIZE);
    	namedWindow("Gray image", WINDOW_AUTOSIZE);
    	imshow(imageName, image);
    	imshow("Gray image", gray_image);
    	waitKey(0);
    	return 0;
    }
    

    Explanation

    1.imread不在赘述

    2. cv::cvtColor

    cvtColor( image, gray_image, COLOR_BGR2GRAY );

    参数:

    源图像(图像)

    目的地图像(GrayIX图像),在其中我们将保存转换后的图像。

    指示将执行什么类型的转换的附加参数。在这种情况下,我们使用CurryBGR2GRY(因为在彩色图像的情况下具有BGR默认信道顺序)。

    3.imwrite

    imwrite( “…/…/images/Gray_Image.jpg”, gray_image );

    参数:

    写入的图片名字

    写入的Mat

    4、Mat - The Basic Image Container

    MAT基本上是一个具有两个数据部分的类:矩阵标头(包含诸如矩阵的大小、用于存储的方法、地址是存储的矩阵等)和指向包含像素值的矩阵的指针(取决于选择用于存储的方法。矩阵头的大小是恒定的,但是矩阵本身的大小可以从图像到图像变化,并且通常是按数量级大的。

    OpenCV是一个图像处理库。它包含了大量的图像处理功能集合。为了解决计算上的挑战,大多数情况下,您将最终使用库的多个函数。因此,将图像传递给函数是一种常见的做法。我们不应该忘记,我们正在谈论图像处理算法,这往往是相当沉重的计算。我们想做的最后一件事是通过制作不必要的大图像拷贝来进一步降低程序的速度。

    为了解决这个问题,OpenCV使用一个参考计数系统。其思想是每个Mat对象都有自己的标头,但是矩阵可以通过它们的矩阵指针指向相同的地址而在它们的两个实例之间共享。此外,复制运算符只将标题和指针复制到大矩阵,而不是数据本身。

    Mat A, C;                          // creates just the header parts
    A = imread(argv[1], IMREAD_COLOR); // here we'll know the method used (allocate matrix)
    Mat B(A);                                 // Use the copy constructor
    C = A;                                    // Assignment operator
    

    最后,所有这些对象指向相同的单个数据矩阵。然而,它们的标题是不同的,使用它们中的任何一个进行修改也会影响所有其他的标题。在实际应用中,不同的对象只对同一基础数据提供不同的访问方法。然而,它们的标题部分是不同的。真正有趣的部分是,您可以创建仅引用完整数据的一个子段的标题。例如,为了在图像中创建感兴趣区域(ROI),您只需创建具有新边界的新标题:

    Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
    Mat E = A(Range::all(), Range(1,3)); // using row and column boundaries
    

    现在你可能会问,矩阵本身是否可能属于多个物体,当它不再需要时,它负责清理它。简短的回答是:最后一个使用它的对象。这是通过使用参考计数机制来处理的。每当有人复制垫对象的头时,矩阵的计数器就会增加。每当清空报头时,计数器就会减少。当计数器达到零时,矩阵也被释放。有时,您也希望复制矩阵本身,因此OpenCV提供CV::MAT::clone()CV::MAT::CopyTo()函数。

    Mat F = A.clone();
    Mat G;
    A.copyTo(G);
    

    现在修改F或G不会影响垫头所指向的矩阵。你需要记住的是:

    OpenCV函数的输出图像分配是自动的(除非另有说明)。

    你不需要考虑内存管理与opencvs C++接口。

    赋值运算符和复制构造函数只复制报头。

    可以使用CV::Mat:clone()CV::MAT::CopyTo()函数复制图像的底层矩阵。

    构造函数

    CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]

    CVY8UC3意味着我们使用8位长的无符号字符类型,每个像素都有三个来形成三个通道。这是预定义的多达四个频道号码。CV::标量是四元短向量。指定这个值,并且可以用自定义值初始化所有矩阵点。如果需要更多,可以用上宏创建类型,在括号中设置通道编号,如下所示。

    5.How to scan images, lookup tables and time measurement with OpenCV

    The iterator (safe) method

    迭代器方法被认为是一种更安全的方法,因为它从用户那里接管这些任务。所有你需要做的是询问图像矩阵的开始和结束,然后只需增加开始迭代器,直到达到结束。若要获取迭代器所指向的值,请使用*运算符(在它之前加上它)。

    Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
    {
        // accept only char type matrices
        CV_Assert(I.depth() != sizeof(uchar));
        const int channels = I.channels();
        switch(channels)
        {
        case 1:
            {
                MatIterator_<uchar> it, end;
                for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
                    *it = table[*it];
                break;
            }
        case 3:
            {
                MatIterator_<Vec3b> it, end;
                for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
                {
                    (*it)[0] = table[(*it)[0]];
                    (*it)[1] = table[(*it)[1]];
                    (*it)[2] = table[(*it)[2]];
                }
            }
        }
        return I;
    }
    

    在彩色图像的情况下,每列有三个UCHAR项。这可能被认为是一个短向量uChar项目。要访问第n个子列,我们使用简单的运算符[]访问。记住OpenCV迭代器经过列并自动跳转到下一行是很重要的。因此,在彩色图像的情况下,如果使用简单的UCHAR迭代器,则只能访问蓝色通道值。

    Mask operations on matrices

    矩阵上的掩码运算是相当简单的。想法是根据掩模矩阵(也称为内核)重新计算图像中的每个像素值。该掩模保持将调整相邻像素(和当前像素)对新像素值有多大影响的值。从数学的角度,我们用我们的指定值做加权平均。

    void Sharpen(const Mat& myImage, Mat& Result)
    {
        CV_Assert(myImage.depth() == CV_8U);  // accept only uchar images
        Result.create(myImage.size(), myImage.type());
        const int nChannels = myImage.channels();
        for(int j = 1; j < myImage.rows - 1; ++j)
        {
            const uchar* previous = myImage.ptr<uchar>(j - 1);
            const uchar* current  = myImage.ptr<uchar>(j    );
            const uchar* next     = myImage.ptr<uchar>(j + 1);
            uchar* output = Result.ptr<uchar>(j);
            for(int i = nChannels; i < nChannels * (myImage.cols - 1); ++i)
            {
                *output++ = saturate_cast<uchar>(5 * current[i]
                             -current[i - nChannels] - current[i + nChannels] - previous[i] - next[i]);
            }
        }
        Result.row(0).setTo(Scalar(0));
        Result.row(Result.rows - 1).setTo(Scalar(0));
        Result.col(0).setTo(Scalar(0));
        Result.col(Result.cols - 1).setTo(Scalar(0));
    }
    

    6、Adding (blending) two images using OpenCV

    合成两张图片

    Code:

    #include <opencv2/opencv.hpp>
    #include <iostream>
    using namespace cv;
    int main(int argc, char** argv)
    {
    	double alpha = 0.5; double beta; double input;
    	Mat src1, src2, dst;
    	std::cout << " Simple Linear Blender " << std::endl;
    	std::cout << "-----------------------" << std::endl;
    	std::cout << "* Enter alpha [0-1]: ";
    	std::cin >> input;
    	if (input >= 0.0 && input <= 1.0)
    	{
    		alpha = input;
    	}
    	src1 = imread("1.jpg");
    	src2 = imread("2.jpg");
    	if (!src1.data) { printf("Error loading src1 \n"); return -1; }
    	if (!src2.data) { printf("Error loading src2 \n"); return -1; }
    	namedWindow("Linear Blend", 1);
    	beta = (1.0 - alpha);
    	addWeighted(src1, alpha, src2, beta, 0.0, dst);
    	imshow("Linear Blend", dst);
    	imwrite("3.jpg", dst);
    	waitKey(0);
    	return 0;
    }
    

    Explanation

    addWeighted( src1, alpha, src2, beta, 0.0, dst);

    图片:src1,src2

    比例:alpha,beta,和为1

    新图片:dst

    7、Changing the contrast and brightness of an image! :

    一般的图像处理算子是一个获取一个或多个输入图像并产生输出图像的函数。

    图像变换可以看作:

    点算子(像素变换)

    邻域(基于区域)算子

    像素变换

    在这种图像处理变换中,每个输出像素的值仅取决于相应的输入像素值。

    这样的例子包括亮度和对比度调整以及颜色校正和变换。

    亮度和对比度调整

    两个常用的点过程是乘法和加法:

    g(x)=αf(x)+β

    参数α>0和β通常称为增益和偏置参数,有时这些参数分别用来控制对比度和亮度。

    可以将f(x)作为源图像像素和g(x)作为输出图像像素。然后,我们更方便地将表达式写成:

    g(i,j)=αf(i,j)+β

    Code

    #include <opencv2/opencv.hpp>
    #include <iostream>
    using namespace cv;
    double alpha; /*< Simple contrast control */
    int beta;  /*< Simple brightness control */
    int main(int argc, char** argv)
    {
    	Mat image = imread(argv[1]);
    	Mat new_image = Mat::zeros(image.size(), image.type());
    	std::cout << " Basic Linear Transforms " << std::endl;
    	std::cout << "-------------------------" << std::endl;
    	std::cout << "* Enter the alpha value [1.0-3.0]: "; std::cin >> alpha;
    	std::cout << "* Enter the beta value [0-100]: "; std::cin >> beta;
    	for (int y = 0; y < image.rows; y++) {
    		for (int x = 0; x < image.cols; x++) {
    			for (int c = 0; c < 3; c++) {
    				new_image.at<Vec3b>(y, x)[c] =
    					saturate_cast<uchar>(alpha*(image.at<Vec3b>(y, x)[c]) + beta);
    			}
    		}
    	}
    	namedWindow("Original Image", 1);
    	namedWindow("New Image", 1);
    	imshow("Original Image", image);
    	imshow("New Image", new_image);
    	imwrite("2.jpg", new_image);
    	waitKey();
    	return 0;
    }
    

    Explanation

    1.我们首先创建参数来保存用户输入的α和β:

    double alpha;
    int beta;
    

    2.我们使用cv::imread加载图像并将其保存在一个MAT对象中:

    Mat image = imread( argv[1] );
    

    3.我们使用CV::iMead加载图像并将其保存在一个Mat对象中:现在,因为我们将对该图像进行一些转换,所以我们需要一个新的Mat对象来存储它。此外,我们希望这具有以下特征:

    初始像素值等于零

    与原始图像相同大小和类型

    Mat new_image = Mat::zeros( image.size(), image.type() );
    

    4.现在,为了执行操作G(i,j)=αf(i,j)+β,我们将访问图像中的每个像素。由于我们正在使用BGR图像,我们将有三个像素(B,G和R)的值,所以我们也将分别访问它们。

    for( int y = 0; y < image.rows; y++ ) {
        for( int x = 0; x < image.cols; x++ ) {
            for( int c = 0; c < 3; c++ ) {
                new_image.at<Vec3b>(y,x)[c] =
                  saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta );
            }
        }
    }
    

    注意以下事项:

    为了访问图像中的每个像素,我们使用这个语法:图像。在<Vec3b>(Y,X)[C],其中Y是行,X是列,C是R,G或B(0, 1或2)。

    因为运算 αp(i,j)+β可以给出超出范围的值,或者不是整数(如果α是浮点数),我们使用cv::SudialType强制转换来确保值是有效的。

    5.最后,我们创建窗口和显示图像,通常的方式。

    	namedWindow("Original Image", 1);
    	namedWindow("New Image", 1);
    	imshow("Original Image", image);
    	imshow("New Image", new_image);
    	imwrite("2.jpg", new_image);
    	waitKey();
    

    8、Basic Drawing

    Point

    它代表一个2D点,由它的图像坐标x和y指定。我们可以将它定义为:

    Point pt;
    pt.x = 10;
    pt.y = 8;
    //Point pt = Point(10, 8);
    

    Scalar

    表示一个4元向量。在OpenCV中,类型标量被广泛用于传递像素值;

    在本教程中,我们将广泛使用它来表示BGR颜色值(3个参数)。如果不使用最后一个参数,则不必定义最后一个参数。

    让我们来看看一个例子,如果我们要求一个颜色参数,我们给出:

    Scalar( a, b, c )
    

    我们将定义一个BGR颜色,例如:蓝色= A,绿色= B和红色= C。

    Code

    #include <opencv2/core.hpp>
    #include <opencv2/imgproc.hpp>
    #include <opencv2/highgui.hpp>
    
    #define w 400
    
    using namespace cv;
    
    /// Function headers
    void MyEllipse( Mat img, double angle );
    void MyFilledCircle( Mat img, Point center );
    void MyPolygon( Mat img );
    void MyLine( Mat img, Point start, Point end );
    
    /**
     * @function main
     * @brief Main function
     */
    int main( void ){
    
      //![create_images]
      /// Windows names
      char atom_window[] = "Drawing 1: Atom";
      char rook_window[] = "Drawing 2: Rook";
    
      /// Create black empty images
      Mat atom_image = Mat::zeros( w, w, CV_8UC3 );
      Mat rook_image = Mat::zeros( w, w, CV_8UC3 );
      //![create_images]
    
      /// 1. Draw a simple atom:
      /// -----------------------
    
      //![draw_atom]
      /// 1.a. Creating ellipses
      MyEllipse( atom_image, 90 );
      MyEllipse( atom_image, 0 );
      MyEllipse( atom_image, 45 );
      MyEllipse( atom_image, -45 );
    
      /// 1.b. Creating circles
      MyFilledCircle( atom_image, Point( w/2, w/2) );
      //![draw_atom]
    
      /// 2. Draw a rook
      /// ------------------
    
      //![draw_rook]
      /// 2.a. Create a convex polygon
      MyPolygon( rook_image );
    
      //![rectangle]
      /// 2.b. Creating rectangles
      rectangle( rook_image,
             Point( 0, 7*w/8 ),
             Point( w, w),
             Scalar( 0, 255, 255 ),
             FILLED,
             LINE_8 );
      //![rectangle]
    
      /// 2.c. Create a few lines
      MyLine( rook_image, Point( 0, 15*w/16 ), Point( w, 15*w/16 ) );
      MyLine( rook_image, Point( w/4, 7*w/8 ), Point( w/4, w ) );
      MyLine( rook_image, Point( w/2, 7*w/8 ), Point( w/2, w ) );
      MyLine( rook_image, Point( 3*w/4, 7*w/8 ), Point( 3*w/4, w ) );
      //![draw_rook]
    
      /// 3. Display your stuff!
      imshow( atom_window, atom_image );
      moveWindow( atom_window, 0, 200 );
      imshow( rook_window, rook_image );
      moveWindow( rook_window, w, 200 );
    
      waitKey( 0 );
      return(0);
    }
    
    /// Function Declaration
    
    /**
     * @function MyEllipse
     * @brief Draw a fixed-size ellipse with different angles
     */
    //![my_ellipse]
    void MyEllipse( Mat img, double angle )
    {
      int thickness = 2;
      int lineType = 8;
    
      ellipse( img,
           Point( w/2, w/2 ),
           Size( w/4, w/16 ),
           angle,
           0,
           360,
           Scalar( 255, 0, 0 ),
           thickness,
           lineType );
    }
    //![my_ellipse]
    
    /**
     * @function MyFilledCircle
     * @brief Draw a fixed-size filled circle
     */
    //![my_filled_circle]
    void MyFilledCircle( Mat img, Point center )
    {
      circle( img,
          center,
          w/32,
          Scalar( 0, 0, 255 ),
          FILLED,
          LINE_8 );
    }
    //![my_filled_circle]
    
    /**
     * @function MyPolygon
     * @brief Draw a simple concave polygon (rook)
     */
    //![my_polygon]
    void MyPolygon( Mat img )
    {
      int lineType = LINE_8;
    
      /** Create some points */
      Point rook_points[1][20];
      rook_points[0][0]  = Point(    w/4,   7*w/8 );
      rook_points[0][1]  = Point(  3*w/4,   7*w/8 );
      rook_points[0][2]  = Point(  3*w/4,  13*w/16 );
      rook_points[0][3]  = Point( 11*w/16, 13*w/16 );
      rook_points[0][4]  = Point( 19*w/32,  3*w/8 );
      rook_points[0][5]  = Point(  3*w/4,   3*w/8 );
      rook_points[0][6]  = Point(  3*w/4,     w/8 );
      rook_points[0][7]  = Point( 26*w/40,    w/8 );
      rook_points[0][8]  = Point( 26*w/40,    w/4 );
      rook_points[0][9]  = Point( 22*w/40,    w/4 );
      rook_points[0][10] = Point( 22*w/40,    w/8 );
      rook_points[0][11] = Point( 18*w/40,    w/8 );
      rook_points[0][12] = Point( 18*w/40,    w/4 );
      rook_points[0][13] = Point( 14*w/40,    w/4 );
      rook_points[0][14] = Point( 14*w/40,    w/8 );
      rook_points[0][15] = Point(    w/4,     w/8 );
      rook_points[0][16] = Point(    w/4,   3*w/8 );
      rook_points[0][17] = Point( 13*w/32,  3*w/8 );
      rook_points[0][18] = Point(  5*w/16, 13*w/16 );
      rook_points[0][19] = Point(    w/4,  13*w/16 );
    
      const Point* ppt[1] = { rook_points[0] };
      int npt[] = { 20 };
    
      fillPoly( img,
            ppt,
            npt,
            1,
            Scalar( 255, 255, 255 ),
            lineType );
    }
    //![my_polygon]
    
    /**
     * @function MyLine
     * @brief Draw a simple line
     */
    //![my_line]
    void MyLine( Mat img, Point start, Point end )
    {
      int thickness = 2;
      int lineType = LINE_8;
    
      line( img,
        start,
        end,
        Scalar( 0, 0, 0 ),
        thickness,
        lineType );
    }
    

    Explanation

    1.由于我们计划画两个例子(原子和一个木棒),我们必须创建两个图像和两个窗口来显示它们。

    char atom_window[] = "Drawing 1: Atom";
    char rook_window[] = "Drawing 2: Rook";
    Mat atom_image = Mat::zeros( w, w, CV_8UC3 );
    Mat rook_image = Mat::zeros( w, w, CV_8UC3 );
    

    2.我们创建了绘制不同几何形状的函数。例如,为了画原子,我们使用了MyEngEs和MyFilledCircle:

    MyEllipse( atom_image, 90 );
    MyEllipse( atom_image, 0 );
    MyEllipse( atom_image, 45 );
    MyEllipse( atom_image, -45 );
    MyFilledCircle( atom_image, Point( w/2.0, w/2.0) );
    

    3.为了绘制木屋,我们采用了MyLoinrectangleMyPosion

    
    MyPolygon( rook_image );
    rectangle( rook_image,
           Point( 0, 7*w/8.0 ),
           Point( w, w),
           Scalar( 0, 255, 255 ),
           -1,
           8 );
    MyLine( rook_image, Point( 0, 15*w/16 ), Point( w, 15*w/16 ) );
    MyLine( rook_image, Point( w/4, 7*w/8 ), Point( w/4, w ) );
    MyLine( rook_image, Point( w/2, 7*w/8 ), Point( w/2, w ) );
    MyLine( rook_image, Point( 3*w/4, 7*w/8 ), Point( 3*w/4, w ) );
    

    4.让我们检查一下这些函数的内部内容:

    MyLine

    void MyLine( Mat img, Point start, Point end )
    {
        int thickness = 2;
        int lineType = 8;
        line( img, start, end,
              Scalar( 0, 0, 0 ),
              thickness,
              lineType );
    }
    

    正如我们所看到的,MyLayle只调用函数cv::Load,它执行以下操作:

    从点到点画一条线

    该线显示在图像IMG中。

    线条颜色由标量(0, 0, 0)定义,这是布莱克的RGB值。

    线的厚度设置为厚度(在这种情况下为2)。

    该线是8连通的(LyeType=8)。

    MyEllipse

    void MyEllipse( Mat img, double angle )
    {
        int thickness = 2;
        int lineType = 8;
        ellipse( img,
           Point( w/2.0, w/2.0 ),
           Size( w/4.0, w/16.0 ),
           angle,
           0,
           360,
           Scalar( 255, 0, 0 ),
           thickness,
           lineType );
    }
    

    从上面的代码中,我们可以看到函数cv::fillPoly绘制椭圆,使得:

    椭圆在图像IMG中显示。

    椭圆中心位于点**(w/2,w/2),并被封装在大小为的框中(w/4,w/16)**。

    椭圆旋转角度

    椭圆在0度和360度之间延伸一个弧。

    图形的颜色将是标量(255, 0, 0),这意味着蓝色在RGB值。

    椭圆的厚度为2。

    MyFilledCircle

    void MyFilledCircle( Mat img, Point center )
    {
        int thickness = -1;
        int lineType = 8;
        circle( img,
            center,
            w/32.0,
            Scalar( 0, 0, 255 ),
            thickness,
            lineType );
    }
    

    类似于椭圆函数,我们可以观察到圆圈作为参数接收:

    将显示圆的图像(IMG)

    以圆心为中心的圆的中心

    圆的半径:W/32

    圆的颜色:标量(0, 0, 255),表示BGR中的红色。

    由于厚度=1,将画圆填充。

    MyPolygon

    void MyPolygon( Mat img )
    {
        int lineType = 8;
        /* Create some points */
        Point rook_points[1][20];
        rook_points[0][0] = Point( w/4.0, 7*w/8.0 );
        rook_points[0][1] = Point( 3*w/4.0, 7*w/8.0 );
        rook_points[0][2] = Point( 3*w/4.0, 13*w/16.0 );
        rook_points[0][3] = Point( 11*w/16.0, 13*w/16.0 );
        rook_points[0][4] = Point( 19*w/32.0, 3*w/8.0 );
        rook_points[0][5] = Point( 3*w/4.0, 3*w/8.0 );
        rook_points[0][6] = Point( 3*w/4.0, w/8.0 );
        rook_points[0][7] = Point( 26*w/40.0, w/8.0 );
        rook_points[0][8] = Point( 26*w/40.0, w/4.0 );
        rook_points[0][9] = Point( 22*w/40.0, w/4.0 );
        rook_points[0][10] = Point( 22*w/40.0, w/8.0 );
        rook_points[0][11] = Point( 18*w/40.0, w/8.0 );
        rook_points[0][12] = Point( 18*w/40.0, w/4.0 );
        rook_points[0][13] = Point( 14*w/40.0, w/4.0 );
        rook_points[0][14] = Point( 14*w/40.0, w/8.0 );
        rook_points[0][15] = Point( w/4.0, w/8.0 );
        rook_points[0][16] = Point( w/4.0, 3*w/8.0 );
        rook_points[0][17] = Point( 13*w/32.0, 3*w/8.0 );
        rook_points[0][18] = Point( 5*w/16.0, 13*w/16.0 );
        rook_points[0][19] = Point( w/4.0, 13*w/16.0) ;
        const Point* ppt[1] = { rook_points[0] };
        int npt[] = { 20 };
        fillPoly( img,
                  ppt,
                  npt,
                      1,
                  Scalar( 255, 255, 255 ),
                  lineType );
    }
    

    为了画一个填充多边形,我们使用函数cv:fIyPull。我们注意到:

    多边形将绘制在IMG上。

    多边形的顶点是PPT中的点集。

    要绘制的顶点的总数是NPT

    绘制的多边形数仅为1个。

    多边形的颜色由标量(255, 255, 255)定义,这是白色的BGR值。

    rectangle

    rectangle( rook_image,
               Point( 0, 7*w/8.0 ),
               Point( w, w),
               Scalar( 0, 255, 255 ),
               -1, 8 );
    

    最后,我们有了cv::rectangle函数(我们没有为这个家伙创建一个特殊的函数)。我们注意到:

    矩形将绘制在Rookx图像上。

    矩形的两个相对顶点由**点(0, 7×w/8)**和点(w,w)**定义。

    矩形的颜色由标量(0, 255, 255)给出,这是黄色的BGR值。

    由于厚度值由** -1 **给出,矩形将被填充。

    9、Put Text, Point or Circle

        //插入文字  
        //参数为:承载的图片,插入的文字,文字的位置(文本框左下角),字体,大小,颜色  
        string words= "good luck";  
        putText( picture, words, Point( picture.rows/2,picture.cols/4),CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 0, 0) );  
        imshow("1.jpg",picture);  
    
    //参数为:承载的图像、圆心、半径、颜色、粗细、线型、最后一个0  
    circle(picture,center,r,Scalar(0,0,0));  
    

    椭圆

       //参数为:承载的图像、圆心、长短轴、径向夹角(水平面到长轴的夹角)、起始角度(长轴到起始边沿的夹角)、结束角度(长轴到结束点的夹角)、倾斜的矩形(可选项)、颜色、粗细、线性、偏移  
        ellipse(picture,center,Size( 250, 100 ),0,30,240,Scalar(0,0,0));  
    

    line:

        //画线  
        Point a = Point (600,600);  
        //参数为:承载的图像、起始点、结束点、颜色、粗细、线型  
        line(picture,a,center,Scalar(255,0,0));  
        imshow("1.jpg",picture);  
    

    矩形:

    //画矩形  
    //参数为:承载的图像、顶点、对角点、颜色(这里是蓝色)、粗细、大小  
    rectangle(picture,a,center,Scalar(255,0,0));  
    imshow("底板",picture); 
    

    10、Discrete Fourier Transform

    傅立叶变换将图像分解成其正弦和余弦分量。换句话说,它将将图像从其空间域转换到其频域。其思想是任何函数都可以用无穷窦和余弦函数之和精确地近似。

    变换的结果是复数。通过真实图像和复数图像或通过幅度和相位图像来显示这一点是可能的。然而,在整个图像处理算法中,只有幅度图像是有趣的,因为这包含了关于图像几何结构所需的所有信息。然而,如果你打算对这些表单中的图像做一些修改,然后你需要重新变换它,你就需要保存这两个。

    在这个示例中,我将展示如何计算和显示傅立叶变换的幅度图像。在数字图像的情况下是离散的。这意味着它们可以从给定的域值中获取一个值。例如,在基本灰度值中,图像值通常介于0和255之间。因此,傅立叶变换也需要是离散的类型,导致离散傅立叶变换(DFT)。每当你需要从几何的角度来确定图像的结构时,你就需要使用它。这里是要遵循的步骤(在灰度输入图像I的情况下):

    1.Expand the image to an optimal size将图像扩展到最佳大小。

    DFT的性能取决于图像的大小。它往往是最快的图像大小是倍数的二,三和五。因此,为了达到最大的性能,通常将一个边界值映射到图像以获得具有这些特征的大小是一个好主意。CV::GoDestaldDftsie()返回这个最佳大小,我们可以使用CV::CopyMaBurdReand()函数来扩展图像的边框:

    Mat padded;                            //expand input image to optimal size
    int m = getOptimalDFTSize( I.rows );
    int n = getOptimalDFTSize( I.cols ); // on the border add zero pixels
    copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));
    

    2.Make place for both the complex and the real values为复杂的和真实的价值创造位置。

    傅立叶变换的结果是复杂的。这意味着对于每个图像值,结果是两个图像值(每个分量一个)。此外,频域范围远大于其空间对应部分。因此,我们通常至少以浮点格式存储这些文件。因此,我们将将输入图像转换为这种类型,并将其扩展到另一个通道以保存复数值:

    Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    Mat complexI;
    merge(planes, 2, complexI);         // Add to the expanded another plane with zeros
    

    3.Make the Discrete Fourier Transform进行离散傅立叶变换。

    有可能进行就地计算(与输出相同的输入):

    
    

    4.Transform the real and complex values to magnitude将实数和复值变换为幅值。

    split(complexI, planes);                   // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
    magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
    Mat magI = planes[0];
    

    5.Switch to a logarithmic scale切换到对数刻度。

    结果表明,傅立叶系数的动态范围太大,不能在屏幕上显示。我们有一些小的和一些高度变化的值,我们不能像这样观察到。因此,高值将全部变为白色点,而小值则变为黑色。为了使用灰度值来可视化,我们可以将我们的线性尺度转换成对数尺度

    翻译成OpenCV代码:

    magI += Scalar::all(1);                    // switch to logarithmic scale
    log(magI, magI);
    

    6.Crop and rearrange

    magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));
    int cx = magI.cols/2;
    int cy = magI.rows/2;
    Mat q0(magI, Rect(0, 0, cx, cy));   // Top-Left - Create a ROI per quadrant
    Mat q1(magI, Rect(cx, 0, cx, cy));  // Top-Right
    Mat q2(magI, Rect(0, cy, cx, cy));  // Bottom-Left
    Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right
    Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);
    q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
    q2.copyTo(q1);
    tmp.copyTo(q2);
    
    

    请记住,在第一步,我们扩大了图像?是时候抛弃新引进的价值观了。为了可视化目的,我们也可以重新排列结果的象限,以便原点(0,0)对应于图像中心。

    7.Normalize.归一化。

    这是为了可视化目的再次进行的。我们现在有了大小,但是这仍然是我们的图像显示范围为0至1。我们使用CV::标准化()函数将我们的值标准化到这个范围

    normalize(magI, magI, 0, 1, NORM_MINMAX); // Transform the matrix with float values into a
                                              // viewable image form (float between values 0 and 1).
    

    11、文件的读入与写入XML

        cv::FileStorage(const string& source, int flags, const string& encoding=string());  
    

    参数:

    **source –**存储或读取数据的文件名(字符串),其扩展名(.xml 或 .yml/.yaml)决定文件格式。

    flags – 操作模式,包括:

    • FileStorage::READ 打开文件进行读操作
    • FileStorage::WRITE 打开文件进行写操作
    • FileStorage::APPEND打开文件进行附加操作
    • FileStorage::MEMORY 从source读数据,或向内部缓存写入数据(由FileStorage::release返回)

    encoding – 文件编码方式。目前不支持UTF-16 XML 编码,应使用 8-bit 编码

    演示写入数值、矩阵、多个变量、当前时间和关闭文件:

        // 1.create our writter  
            cv::FileStorage fs("test.yml", FileStorage::WRITE);  
              
            // 2.Save an int  
            int imageWidth= 5;  
            int imageHeight= 10;  
            fs << "imageWidth" << imageWidth;  
            fs << "imageHeight" << imageHeight;  
          
            // 3.Write a Mat  
            cv::Mat m1= Mat::eye(3,3, CV_8U);  
            cv::Mat m2= Mat::ones(3,3, CV_8U);  
            cv::Mat resultMat= (m1+1).mul(m1+2);  
            fs << "resultMat" << resultMat;  
          
            // 4.Write multi-variables   
            cv::Mat cameraMatrix = (Mat_<double>(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);  
            cv::Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0);  
            fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;  
          
            // 5.Save local time  
            time_t rawtime; time(&rawtime); //#include <time.h>  
            fs << "calibrationDate" << asctime(localtime(&rawtime));  
          
            // 6.close the file opened  
            fs.release();  
    
    展开全文
  • OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现)...

    立即学习:https://edu.csdn.net/course/play/4789/86618?utm_source=blogtoedu

    1.计算遍历耗时

    getTickCount()获取当前的cpu振动次数

    getTickFrequency()获取振动频率

    二者返回的都是64的long long型数据,计算ms数在*1000之前最好先强转成double型,然后用long long型变量接收

    2.如果字符串指针指向的内存没有值,则*出的返回值是0(\0字符串结束标识符)

    3.可以在项目属性C/C++中所有选项中设置优化,可以使得编译器做一些优化操作

    4.一次计时函数调用结束后,将上一次计时静态变量重新获取当前振动次数

    展开全文
  • OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现)...
    学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程—15628人已学习 
    课程介绍    
    201704271548142880.png
        OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。
    课程收益
        学会opencv视频编辑处理接口,能够理解阅读接口的源码
        利用opencv开发视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频融合、剪切
        学会调整视频的各种图像参数和算法,学会使用qt开发出跨平台视频编辑器界面并能与opencv高效结合
        学会ffmpeg工具抽取剪切音频并与视频合并
    讲师介绍
        夏曹俊更多讲师课程
        夏曹俊:南京捷帝科技有限公司创始人,南京大学计算机硕士毕业,有15年c++跨平台项目研发的经验,领导开发过大量的c++虚拟仿真,计算机视觉,嵌入式图像处理,云安全审计项目,比赛鹰眼系统,主编出版过《C++实训教程》,并同时熟悉php,c#,java,安卓项目研发。
    课程大纲
      第1章:环境准备
        1.opencv课程介绍_学员群559312905  15:39
        2.Windows下编译opencv源码  7:53
        3.Ubuntu下编译opencv源码  7:42
        4.windows 上创建opencv示例项目编译并执行  12:03
        5.ubuntu上创建opencv示例项目makefile编译并执行  7:14
        6.QT开发环境下载、项目创建、代码结构介绍  12:40
      第2章:OpenCV核心类型 Mat
        1.OpenCV Mat类型分析源码介绍、空间创建和释放  10:38
        2.遍历和修改连续的OpenCV Mat图像空间  10:49
        3.使用opencv接口实现运行记时函数用来分析执行效率  7:43
        4.遍历不连续的OpenCV Mat空间  5:49
        5.通过OpenCV ptr模板函数遍历Mat并测试其性能  8:36
        6.通过OpenCV at函数遍历Mat并捕获异常  7:57
        7.通过迭代器遍历Mat并总结遍历方法  5:25
        8.QT自定义opengl的Widget绘制Mat  18:33
      第3章:OpenCV图像处理
        1.通过ROI感兴趣区域来裁剪图像  7:25
        2.RGB、YUV、GRAY像素格式介绍opencv像素格式转换cvtColor接口讲解  6:33
        3.手动实现转换灰度图并与opencv提供的函数做性能对比  14:54
        4.通过OpenCV阈值函数threshold实现图像的二值化  8:40
        5.通过对Mat遍历修改图像亮度和对比度与convertTo性能对比  15:30
        6.图像尺寸调整算法介绍并手动实现近邻算法  5:38
        7.调用opencv的resize使用近邻算法并与自定义算法比较  16:27
        8.图像尺寸调整双线程插值算法讲解和性能测试  11:02
        9.高斯金字塔和拉普拉斯金字塔调整图像尺寸详解  11:30
        10.实现两幅图像混合blending  8:24
        11.图像旋转和镜像  6:28
        12.通过ROI实现图像并排合并  14:23
      第4章:OpenCV视频IO接口
        1.OpenCV VideoCapture打开摄像头接口讲解和源码分析  5:31
        2.OpenCV VideoCapture打开视频流接口讲解和源码分析  6:37
        3.VideoCapture release关闭和空间释放源码分析  4:12
        4.OpenCV read读取一帧视频接口讲解和源码分析  9:20
        5.使用OpenCV VideoCapture播放视频示例  12:22
        6.获取视频和相机的属性并分析获取视频属性的源码  12:54
        7.使用opencv实现视频播放位置跳转  9:38
        8.通过VideoWrite的open创建视频文件并分析源码  14:55
        9.通过VideoWrite的write创建视频文件并分析源码  9:58
        10.以h264格式录制并预览摄像机视频代码演示  11:31
      第5章:FFMpeg工具处理音频
        1.使用ffmpeg工具实现音频抽取、剪切和与视频合并  13:07
      第6章:XVideoEdit视频编辑器实战
        1.编辑器的需求分析和最终实现的功能介绍  5:56
        2.项目类图介绍和类功能讲解  6:09
        3.基于QT系统界面设计详解  4:39
        4.实战项目环境搭建、项目创建和配置  9:28
        5.完成视频编辑器播放界面并完成绘制视频widget重载  13:12
        6.详解通过qss完成界面风格设置,设置按钮圆角和渐变颜色  5:58
        7.通过qt界面打开外部视频并完成打开失败的界面提示  21:22
        8.使用opencv读取并解码视频通过信号槽机制发出绘制信号  13:49
        9.解码并使用播放视频,分析并解决QImage图像数据不连续问题  25:05
        10.视频播放器进度条(QSlider)显示播放进度  16:28
        11.通过QSlider滑动条拖动完成视频播放位置跳转  15:12
        12.调整视频亮度对比度1完成XImagePro类  12:56
        13.调整视频亮度对比度2完成XFilter类  15:49
        14.调整视频亮度对比度3完成界视频结果显示  18:29
        15.视频的导出1接口调用搭建和界面实现完成  17:21
        16.视频导出2功能实现  20:47
        17.完成播放暂停并使用qss设置播放暂停按钮样式效果  17:58
        18.视频图像旋转并导出  14:57
        19.视频上下左右镜像  7:27
        20.调整视频尺寸并导出  12:08
        21.通过图像金字塔调整视频尺寸  17:20
        22.通过ROI裁剪视频画面  18:10
        23.转换为灰度图视频并导出  18:33
        24.视频添加水印  24:23
        25.视频融合1-完成了打开第二个视频源  15:57
        26.视频融合2-完成了融合和导出  12:48
        27.完成了两路视频的横向合并  19:54
        28.音频类的抽取接口开发和测试  15:14
        29.完成视频中音频的的合并导出  16:46
        30.完成了视频的开始结束位置剪辑音频未处理  20:49
        31.完成了视频剪辑包含音频剪辑  16:02
      第7章:课程总结
        1.重复的删除  7:43
    大家可以点击【查看详情】查看我的课程
    展开全文
  • OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现)...
  • OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现)...
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程 夏曹...
  • Opencv概述

    2015-07-29 11:00:24
    opencv是什么 OpenCV是一个用于图像处理、分析、机器视觉方面的开源函数库.   无论你是做科学研究,还是商业应用,opencv都可以作为你理想的工具库,因为,对于这两者,它完全是免费的。 该库采用C及C++语言...
  • opencv是什么

    2011-05-02 15:27:00
    OpenCV是一个用于图像处理、分析、机器视觉方面的开源函数库. 无论你是做科学研究,还是商业应用,opencv都可以作为你理想的工具库,因为,对于这两者,它完全是免费的。该库采用C及C++语言编写,可以在windows, ...
  • OpenCV学习

    2018-07-24 19:19:01
    另一篇参考文献: 中文手册 ...的番外篇,因为严格来说不是在讲Python而是讲在Python下使用OpenCV。本篇将介绍和深度学习数据处理阶段最相关的基础使用,并完成4个有趣实用的小例子: - 延时摄影小程序 - 视频中...
  • 目录 1 背景 ...在本教程中,我们将了解OpenCV 3中引入的OpenCV目标跟踪API。我们将学习如何以及何时使用OpenCV 3中提供的8种不同的跟踪器BOOSTING,MIL,KCF,TLD,MEDIANFLOW,GOTURN,MOSS...
  • 一、Python OpenCV 入门欢迎阅读系列教程,内容涵盖 OpenCV,它是一个图像和视频处理库,包含 C ++,C,Python 和 Java 的绑定。 OpenCV 用于各种图像和视频分析,如面部识别和检测,车牌阅读,照片编辑,高级机器人...
  • opencv概述及安装步骤

    2014-04-13 21:52:13
    本科时对于Opencv这个名词只闻其名,一直不识庐山面目,也没想过以后有一天会用到它。近日由于课题原因,我只能拿出学长推荐给我那本《学习opencv》开始零基础...一) opencv概述 1)OpenCV的全称是:OpenSource Comp
  • 一、OPenCV的概念和结构OpenCV:开源的计算机视觉库,一般用C和C++ 编写OpenCV的结构共分为五个部分,分别是图像处理和视觉算法(CV)、机器学习库(ML)、图像和视频输入/输出库(HighGUI)、基本结构和算法,XML...
  • 一:OpenCV概述 1.opencv相关概念 图像处理 利用计算机对图像进行分析处理,达到所需结果的技术,一般指的是数字图像处理,通过数码设备得到的数字图像是一个很大的二维数组,数组的元素叫像素,像素的值叫灰度值...
  • OpenCV概述

    2011-09-13 15:06:21
    Intel® 开源计算机视觉库OpenCV 目录  [隐藏] 1 什么是OpenCV2 重要特性3 谁创建了它4 新特征5 从哪里下载 OpenCV6 如果在安装/运行/使用 OpenCV 中遇到问题7 OpenCV参考手册8 中文...
  • OpenCV概述和安装

    2020-04-19 16:11:12
    OpenCV概述 OpenCV 的理论支撑来源于《数字图像处理》,数字图像处理使用的都是一些比较传统的算法,而目前也添加了一些比较前沿的算法,虽然有深度学习算法,但是主流不是深度学习算法。【更新速度也没有深度学习...
1 2 3 4 5 ... 20
收藏数 3,982
精华内容 1,592
关键字:

opencv