OpenCV

Table of Contents

1. OpenCV 简介

OpenCV (Open Source Computer Vision) is a library of programming functions mainly aimed at real-time computer vision, originally developed by Intel's research center in Nizhny Novgorod (Russia), later supported by Willow Garage and now maintained by Itseez.

参考:http://opencv.org/

1.1. 从源码安装 OpenCV 3.0.0

下面步骤的测试操作系统为 Mac OS 10.10。

Step 1. Download opencv-3.0.0.zip, and unzip it.

$ cd /full/path/to/opencv-3.0.0

Step 2. Make a build directory.

$ mkdir build
$ cd build

Step 3. Configure OpenCV installation.

$ cmake -D CMAKE_INSTALL_PREFIX=/full/path/to/opencv-3.0.0/build  ..

说明:这里设置安装时的位置为"/full/path/to/opencv-3.0.0/build",如果不配置,则会安装到系统的默认位置中。

Step 4. Compile the source code.

$ make

Step 5. Install library files and header files into CMAKE_INSTALL_PREFIX.

$ make install

1.1.1. 配置 pkg-config

Copy the pkg-config file opencv.pc to "/usr/local/lib/pkgconfig/opencv3.pc"

$ ln -s /full/path/to/opencv-3.0.0/build/lib/pkgconfig/opencv.pc /usr/local/lib/pkgconfig/opencv3.pc

注:这里没有真正复制,仅是创建了一个软链接。把 opencv.pc 改名为 opencv3.pc 的目的是避免系统中有多个版本的 OpenCV 时出现混乱。

1.1.2. 测试安装是否成功

编译一个自带的 sample,如人脸识别程序 facedetect.cpp。

$ cd /full/path/to/opencv-3.0.0/samples/cpp
$ g++ -ggdb `pkg-config --cflags --libs opencv3` facedetect.cpp -o /tmp/facedetect

测试上面编译出来的程序,如:

$ export DYLD_LIBRARY_PATH=/full/path/to/opencv-3.0.0/build/lib:$DYLD_LIBRARY_PATH
$ /tmp/facedetect

说明:DYLD_LIBRARY_PATH 是 Mac 系统中用于查找动态库的环境变量,相当于 Linux 中的环境变量 LD_LIBRARY_PATH。

当程序正常运行后,会启动摄像头。我拿了一个“抱婴腰凳”的说明书做测试,上面有 8 个人脸,识别的效果还不错,仅两个侧脸没有识别出来。如图 1 所示。

opencv_facedetect.jpg

Figure 1: OpenCV 人脸识别测试示例

1.2. 安装 Python 绑定

如果你只想在 Python 中使用 OpenCV,则安装 Python 绑定即可。如:

$ pip install opencv-python           # 仅安装OpenCV core modules
$ pip install opencv-contrib-python   # 安装OpenCV core modules和contrib modules(这个模块中包含一些有专利保护的算法,如SIFT等等)
$ python
Python 2.7.11 (default, Dec 26 2015, 17:47:15)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'3.0.0'

参考:
https://pypi.python.org/pypi/opencv-python
https://pypi.python.org/pypi/opencv-contrib-python

2. OpenCV 实例

2.1. 实例:加载和显示图像

2.1.1. Mat 类

在比较旧的 OpenCV 代码中,常用 IplImage 结构来保存加载图像。如:

#include "highgui.h"

int main( int argc, char** argv ) {
    IplImage* img = cvLoadImage( argv[1] );         /* old code */
    cvNamedWindow( "Example1", CV_WINDOW_AUTOSIZE );
    cvShowImage( "Example1", img );
    cvWaitKey(0);
    cvReleaseImage( &img );
    cvDestroyWindow( "Example1" );
}

IplImage 是一个 C 结构,对于一个大型程序来说,如果忘记使用 cvReleaseImage() 释放内存,会造成内存泄漏。

对于新写的程序,推荐使用 Mat类 来存储图片。它是一个 C++类,使用它时不用显式释放内存了(超过作用域时会自动释放内存)。

Mat 的基本介绍,可参考:Mat - The Basic Image Container
要操作 Mat 所表示图像中的每个像素,可参考:How to scan images, lookup tables and time measurement with OpenCV

2.1.2. Mat 类加载显示图像

下面是加载显示图片的实例。代码摘自:http://docs.opencv.org/2.4/doc/tutorials/introduction/display_image/display_image.html

// file display_image.cpp
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    if( argc != 2)
    {
        cout <<" Usage: display_image ImageToLoadAndDisplay" << endl;
        return -1;
    }

    Mat image;
    image = imread(argv[1], CV_LOAD_IMAGE_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;
}

用下面命令编译上面程序:

$ g++ `pkg-config --cflags --libs opencv3` display_image.cpp -o display_image

设置好环境变量 LD_LIBRARY_PATH(Mac 系统中对应为 DYLD_LIBRARY_PATH)后,测试程序:

$ ./display_image /Users/cig01/Downloads/opencv-3.0.0/samples/data/lena.jpg

启动正常后,会出现图 2 所示窗口。

opencv_mat_imread.jpg

Figure 2: OpenCV 实例:加载显示图片

2.2. 实例:反转灰度图像

下面是反转灰度图像的例子。

// file test_negative.cpp
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
  char* imageName = argv[1];

  Mat image = imread( imageName, 1 );

  if( argc != 2 || !image.data ) {
    cout <<" No image data" << endl;
    return -1;
  }

  namedWindow( "Original image", CV_WINDOW_AUTOSIZE );
  imshow( "Original image", image );

  Mat gray_image;
  cvtColor( image, gray_image, CV_BGR2GRAY );          // 先把彩色图像转换为灰度图像。

  namedWindow( "Gray image", CV_WINDOW_AUTOSIZE );
  imshow( "Gray image", gray_image );

  // 把灰度图像进行“反转变换”
  gray_image = 255 - gray_image;    // 矩阵整体操作,相当于访问每个像素,对其执行 255 - value 操作。

  namedWindow( "Gray image (negative)", CV_WINDOW_AUTOSIZE );
  imshow( "Gray image (negative)", gray_image );

  waitKey(0);
  return 0;
}

我们也可以显式地访问矩阵 Mat 中的每个元素,进行“反转变换”。如:

  for( int x = 0; x < gray_image.rows; x++ ) {
    for( int y = 0; y < gray_image.cols; y++ ) {
      gray_image.at<uchar>(x,y) = 255 - gray_image.at<uchar>(x,y);  // 灰度图像的像素在Mat中是用uchar表示的。
    }
  }

用迭代器也可以访问 Mat 中的每个像素。如上面代码中的两个 for 循环可以用下面代码代替:

  for (MatIterator_<uchar> it = gray_image.begin<uchar>(); it != gray_image.end<uchar>(); ++it) {
    *it = 255 - (*it);
  }

测试程序:

$ ./test_negative /Users/cig01/Downloads/opencv-3.0.0/samples/data/HappyFish.jpg

启动正常后,会出现如图 3 所示示例。

opencv_negative.jpg

Figure 3: OpenCV 实例:反转灰度图像

2.3. 实例:转换彩色图像为灰度图像

2.3.1. 函数 cvtColor

在 OpenCV 中,使用函数 cvtColor 可以把图像从一个“颜色空间”转换到另一个“颜色空间”。

OpenCV 默认使用的是“BGR 颜色空间”,在 cvtColor 函数的第 3 个参数中指定 CV_BGR2GRAY 可以把彩色图像转换为灰度图像。要进行其它空间转换的转换,可以指定其它一些值,如 CV_BGR2HSV/CV_BGR2YCrCb 等等。

2.3.2. 使用 cvtColor 转换彩色图像为灰度图像

下面是转换彩色图像为灰度图像的实例。代码摘自:http://docs.opencv.org/2.4/doc/tutorials/introduction/load_save_image/load_save_image.html

// file test_bgr2gray.cpp
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

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 )
  {
    cout <<" No image data" << endl;
    return -1;
  }

  Mat gray_image;
  cvtColor( image, gray_image, CV_BGR2GRAY );    // 用cvtColor可以对色彩空间进行转换(这里是把彩色图像转换为灰度图像)。

  imwrite( "/tmp/Gray_Image.jpg", gray_image );    // 用imwrite可以保存图像到文件

  namedWindow( imageName, CV_WINDOW_AUTOSIZE );
  namedWindow( "Gray image", CV_WINDOW_AUTOSIZE );

  imshow( imageName, image );
  imshow( "Gray image", gray_image );

  waitKey(0);
  return 0;
}

编译和测试如下:

$ g++ `pkg-config --cflags --libs opencv3` test_bgr2gray.cpp -o test_bgr2gray
$ ./test_bgr2gray /Users/cig01/Downloads/opencv-3.0.0/samples/data/lena.jpg

启动正常后,会出现图 4 所示窗口。

opencv_cvtColor.jpg

Figure 4: OpenCV 实例:转换彩色图像为灰度图像

2.4. 实例:高斯模糊

通过函数 GaussianBlur 可以对图像进行高斯模糊。下面是实例:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <string>

using namespace cv;
using namespace std;

int main(int argc, char *argv[])
{
    if( argc != 2) {
        cout <<" Usage: gaussianfilter ImageToProcess" << endl;
        return -1;
    }

    Mat srcImg;
    srcImg = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);

    namedWindow("orignal", 1);
    imshow("orignal", srcImg);

    Mat resImg;
    double sigma = 4.0;
    GaussianBlur(srcImg, resImg, Size(0, 0), sigma, sigma);  // Gaussian blur, 其中Size(0, 0)表示根据sigma计算核的大小

    namedWindow("Gaussian blur", 1);
    imshow("Gaussian blur", resImg);

    waitKey(0);
}

5 是运行上面程序进行高斯模糊的例子:

opencv_gaussian_blur.jpg

Figure 5: 高斯模糊实例

Author: cig01

Created: <2015-12-05 Sat>

Last updated: <2017-07-07 Fri>

Creator: Emacs 27.1 (Org mode 9.4)