OpenCV 2 计算机视觉编程手册

第1章 接触图像
第2章 操作像素
第6章 图像滤波
附录 OpenCV3 介绍及代码导读

勘误
我的困惑
下一步计划

<div id="Section1">第1章 接触图像</div>

  • OpenCV 库的结构
  • 载入、显示及保存图像

OpenCV 库的结构

  • sources文件夹下的子文件夹:
    • doc 文件夹中包含的是文档 + include 文件夹中是所有头文件
    • modules 文件夹中包含所有的源程序
    • samples 文件夹中则是许多简短的学习用范例

第 2 页讲了下怎么编译的,对于新版 OpenCV 来说已经没有必要了,解压后的 build 文件夹就是编译好的内容。

第 3 页介绍了各模块的功能,还有推荐的声明方式,为什么要用这种声明方式呢?

第 6 页提到,为了遵循 ANSI C++ 标准,在用 Visual Studio 建立工程时选择 Application Settings 时,没有勾选 Precompiled Header 选项,这是 Visual Studio 的预编译头文件特性,可以加速编译过程。

载入、显示及保存图像

  • 声明图像变量

 

cv::Mat image;

创建宽高都为0的图像,返回值是一个结构体,

  • 图像读取、解码以及内存分配

 

image = cv::imread("img.jpg");
  • 检查图像是否被正确读取

 

if (!image.data) {
    // 图像尚未创建……
}

此处的成员变量data事实上是指向已分配的内存块的指针,包括图像数据。当不存在数据时,它被简单设置为0.

  • 声明一个需要进行图像显示的窗口,接着指定需要显示的图像:

 

cv::namedWindow("Original Image");  // 定义窗口
cv::imshow("Original Image", image); // 显示图像

显示图像的这条语句之所以还要出现窗口名称,是为了指定究竟把图像显示到哪个窗口去,因为可能存在多个窗口。

  • 图像翻转

 

cv::Mat result;
cv::flip(image, result, 1); // 1表示水平翻转
                            // 0表示垂直翻转
                            // 负数表示既有水平也有垂直翻转
  • 等待用户输入

 

cv::waitKey(0); //括号中填的数字是毫秒数,0为一直等待

如果没有这句话,显示的图像会一闪而过。

  • 将图像写到磁盘

 

cv::imwrite("output.bmp", result);

文件的后缀名决定了图像保存时的编码格式。

  • 指定初始尺寸

 

cv::Mat ima(240, 320, CV_8U, cv::Scalar(100));

CV_8U对应的是单字节的像素图象,字母U意味着无符号的(Unsigned)。对于彩色图像,需要指定3个通道(CV_8UC3)。

当 cv::Mat 对象离开作用域后,分配的内存将自动释放,从而避免内存泄漏的困扰。
另外,cv::Mat 实现了引用计数以及浅拷贝,当图像之间进行赋值时,图像数据并没有发生复制,两个对象都指向同一块内存块。这也可用于参数传值的图像,以及返回值传值的图像。引用计数的作用是当所有引用内存数据的对象都被析构后,才会释放内存块。如果你希望创建的图像拥有原始图像的崭新拷贝,那么可以使用copyTo()方法。

 

cv::Mat image2, image3;
image2 = result; // 两幅图像拥有同一份数据
result.copyTo(image3); // 创建新的拷贝

如果翻转output图像,并显示image2和image3,可以看到image2页翻转了,而image3没有变。

同理,函数返回其实也是一次浅拷贝过程。

 

cv::Mat function() {
    // 创建图像
    cv::Mat ima(240, 320, CV_8U, cv::Scalar(100));
    // 并返回它
    return ima;
}

// 得到灰度图
cv::Mat gray = function();

在函数function内,ima只是个局部变量,在离开作用域时应当被析构掉,但由于他所关联的引用计数表示内部图像正在被另一个对象gray所引用,因此内存块并不会被释放。

<div id="Section2">第2章 操作像素</div>

  • 彩色或灰度图像存取像素值

 

void salt(cv::Mat &image, int n) {
    for (int k = 0; k < n; k++) {
        // rand() 是随机数生成函数
        int i = rand() % image.cols;
        int j = rand() % image.rows;
        if (image.channels() == 1) { // 灰度图
            image.at<uchar>(j,i) = 255;
        } else if (image.channels() == 3) { // 彩色图
            image.at<cv::Vec3b>(j,i)[0] = 255;
            image.at<cv::Vec3b>(j,i)[1] = 255;
            image.at<cv::Vec3b>(j,i)[2] = 255;
        }
    }
}
  • 类 cv::Mat 有若干成员函数可以获取图像的属性。公有成员变量 cols 和 rows 给出了图像的宽和高。成员函数 at(int y, int x) 可以用来存取图像元素。 但是必须在编译期知道图像的数据类型,因为 cv::Mat 可以存放任意数据类型的元素。这也是这个函数用模板函数来实现的原因。所以 at 方法要指定数据类型,而且 at 方法本身不会进行任何数据类型转换。

  • cv::Vec3b,即由三个 unsigned char 组成的向量。

 

image.at<cv::Vec3b>(j,i)[channel] = value;

索引值 channel 标明了颜色通道号。
类似的,还有二元素向量类 cv::Vec2b 和四元素向量类 cv::Vec4b,s 代表 short,i 代表 int,f 代表 float,d 代表 double。所有这些类型都是使用模板类 cv::Vect<T, N> 定义的,其中 T 代表类型,N 代表向量中的元素个数。

  • 有时候使用 cv::Mat 的成员函数会很麻烦,因为返回值的类型必须通过在调用时通过模板参数指定。因此,OpenCV 提供了类 cv::Mat_,它是 cv::Mat 的一个模板子类。在事先知道矩阵类型的情况下,使用 cv::Mat_ 可以带来一些便利。这个类额外定义了一些方法,但是没有任何成员变量,所以此类的指针或者引用可以直接进行相互类型转换。该类重载了操作符 (),允许我们可以通过它直接存取矩阵元素。因此,假设有一个 uchar 类型的矩阵,我们可以这样写:

 

cv::Mat_<uchar> im2 = image; // im2 指向 image
im2(50, 100) = 0; // 存取第 50 行,100列

由于 cv::Mat_ 的元素类型在创建实例的时候已经声明,操作符 () 在编译期就知道要返回的数据类型。使用操作符 () 得到返回值和使用 cv::Mat 的 at 方法得到的返回值是完全一致的,而且写起来更加简洁。

  • 双重循环遍历所有像素值:

 

void colorReduce(cv::Mat &image, int div = 64
OpenCV2计算机视觉编程手册》是一本非常权威和实用的书籍,涵盖了计算机视觉领域中使用OpenCV2库进行编程的各个方面。这本书的作者是Adrian Kaehler和Gary Bradski,两位都是OpenCV的资深专家。 该书分为三个主要部分。第一部分介绍了OpenCV计算机视觉的基础知识,包括图像处理和计算机视觉的基本概念、OpenCV库的结构和使用方法等。第二部分着重介绍了OpenCV中常用的图像处理和计算机视觉算法,如特征提取、图像匹配、目标检测和跟踪等。读者可以通过具体的示例代码和实战项目来深入理解这些算法的原理和实现方法。第三部分介绍了OpenCV在实际应用中的各种案例和项目,包括人脸识别、车牌识别、物体跟踪等。 该书的特点之一是注重理论与实践的结合。作者不仅介绍了算法的原理和数学基础,还提供了大量的代码示例和实践项目,帮助读者从理论到实践的过渡。另外,书中的示例代码都是基于Python和C++语言的,这两种语言是计算机视觉领域常用的编程语言,方便读者学习和实践。 总之,《OpenCV2计算机视觉编程手册》是计算机视觉领域的一本重要参考书籍,对于初学者和已有一定基础的开发者都非常有价值。通过阅读该书,读者可以系统地学习OpenCV库的使用和计算机视觉算法的原理,掌握实现各种计算机视觉任务的方法和技巧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值