openCV自学入门笔记

opencv-3.4.0编译

(注:确保cuda版本为9.0,确保FFmpeg已安装)

#必要的依赖项
sudo apt-get install build-essential
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev

#源码
git clone https://github.com/opencv/opencv.git
#git clone https://github.com/opencv/opencv_contrib.git

#编译
cd opencv
mkdir build
cd build
#Run cmake [<some optional parameters>] <path to the OpenCV source directory>
#注意:如果`cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local ..`不起作用,请在-D后使用空格
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..
make -j12
sudo make install

一、openCV应用(Mat类)

opencv中常见的与图像操作有关的数据容器有Mat,cvMat和IplImage,这三种类型都可以代表和显示图像,但是,Mat类型侧重于计算,数学性较高,openCV对Mat类型的计算也进行了优化。而CvMat和IplImage类型更侧重于“图像”,opencv对其中的图像操作(缩放、单通道提取、图像阈值操作等)进行了优化。
Mat是opencv2.0推出的处理图像的新的数据结构,现在越来越有趋势取代之前的cvMat和lplImage,相比之下Mat最大的好处就是能够更加方便的进行内存管理,不再需要程序员手动管理内存的释放。
opencv2.3中提到Mat是一个多维的密集数据数组,可以用来处理向量和矩阵、图像、直方图等等常见的多维数据。
OpenCV 将颜色读取为 BGR(蓝绿色红色),但大多数计算机应用程序读取为 RGB(红绿蓝)

头文件、命名空间
#include<opencv2/opencv.hpp>
using namespace cv;
初始化Mat(读取图像imread())
        Mat image =imread("*.jpg", [ImreadModes]); //读取一个jpg文件到image对象中
        Mat( int rows, int cols, int type ); //指定行、列、类型、(初始化数据)
            注:[ImreadModes]

            enum ImreadModes {
                   IMREAD_UNCHANGED            = -1, //不进行转化,比如保存为了16位的图片,读取出来仍然为16位。(载入源图像,并添加alpha通道)
                   IMREAD_GRAYSCALE            = 0,  //进行转化为灰度图,比如保存为了16位的图片,读取出来为8位,类型为CV_8UC1。(Y=0.3R+0.59G+0.11B)
                   IMREAD_COLOR                = 1,  //进行转化为三通道彩色图像。
                   IMREAD_ANYDEPTH             = 2,  //如果图像深度为16位则读出为16位,32位则读出为32位,其余的转化为8位。读取任意深度的图片
                   IMREAD_ANYCOLOR             = 4,  //如果设置了,那么就载入任意可能的颜色格式而不进行转换. (常用)
                   IMREAD_LOAD_GDAL            = 8,  //使用GDAL驱动读取文件,GDAL是一个在X/MIT许可协议下的开源栅格空间数据转换库。它利用抽象数据模型来表达所支持的各种文件格式。它还有一系列命令行工具来进行数据转换和处理。
                   IMREAD_REDUCED_GRAYSCALE_2  = 16, //图像总是转换为单通道灰度图,且尺寸缩减为1/2
                   IMREAD_REDUCED_COLOR_2      = 17, //图像总是转换为彩色3通道BGR且尺寸缩减为1/2.
                   IMREAD_REDUCED_GRAYSCALE_4  = 32, //同上,灰度,缩减为1/4.
                   IMREAD_REDUCED_COLOR_4      = 33, //同上,彩色,缩减为1/4.
                   IMREAD_REDUCED_GRAYSCALE_8  = 64, //同上,灰度,缩减为1/8.
                   IMREAD_REDUCED_COLOR_8      = 65, //同上,彩色,缩减为1/8.
                   IMREAD_IGNORE_ORIENTATION   = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.
                 };

        image.cols; //矩阵的列数,例:1920
        image.rows; //矩阵的行数,例:1080
        image.data; //指向矩阵的数据单元的指针
        image.size; //矩阵大小,例:1080 x 1920
        image.flags; //0-11位共同代表type即通道数和数据类型,14位代表Mat的内存是否连续
        image.channels(); //通道数
        image.step[0~1]; //setp[0]: 线的数据量大小,单位为字节。setp[1]: 点的数据量大小(step[i]是Mat类中十分重要的一个属性,表示第i维的总大小,单位字节)
        image.empty(); //判断是否为空
在窗口显示图像
        namedWindow(vod_id, CV_WINDOW_NORMAL); //CV_WINDOW_NORMAL窗口可调整,默认WINDOW_AUTOSIZE
        imshow("name", image);
        resizeWindow(vod_id, 1920, 1080);
        waitKey(3*1000);//显示需要延时ms,等待用户按任意键
关闭窗口显示
        destroyWindow("name");
        destroyAllWindows();
        引申:判断窗口是否还在(cvGetWindowHandle("name"))
调整图像大小(resize())
        Mat image2; //定义一个新mat对象
        resize(image, image2, Size(30,30)); //调整目标大小为30*30
        调整矩阵维度:Mat::reshape(int cn, int rows=0)
        cn: 表示通道数(channels), 如果设为0,则表示保持通道数不变,否则则变为设置的通道数。
        rows: 表示矩阵行数。 如果设为0,则表示保持原有的行数不变,否则则变为设置的行数。
编码、压缩图像(imencode())
        std::vector<uchar> data_encode; //用于保存编码后的数据流
        vector<int> param = vector<int>(2);
        param[0]=CV_IMWRITE_JPEG_QUALITY;
        param[1]=95;//default(95) 0-100
        imencode(".png", image, data_encode, param); //编码为png格式,image:Mat格式,data_encode:vector<uchar>格式
解码图像(imdecode())
        Mat img_decode; //定义一个新mat对象,用于保存解码后的数据
        img_decode = imdecode(data_encode, [ImreadModes]); //data_encode:可以是Mat格式,也可以是vector<uchar>格式
保存图像(imwrite())
        vector<int> encode_param= vector<int>(2);
        encode_param[0]=IMWRITE_JPEG_QUALITY;
        encode_param[1]=Cr; //压缩比:default(95) 0-100
        imwrite(“*.jpg”, img_decode, endoe_param); //保存为jpg格式图像,encode_param为保存参数。

        注:[ImwriteFlags]

        enum ImwriteFlags {
               IMWRITE_JPEG_QUALITY        = 1,  //For JPEG,它可以是从0到100的质量(越高越好),默认值95。
               IMWRITE_JPEG_PROGRESSIVE    = 2,  //启用jpeg功能(进步的),0或1,默认值为false。
               IMWRITE_JPEG_OPTIMIZE       = 3,  //启用jpeg功能(最优化),0或1,默认值为false。
               IMWRITE_JPEG_RST_INTERVAL   = 4,  //!< JPEG restart interval, 0 - 65535, default is 0 - no restart.——jpeg重新启动间隔
               IMWRITE_JPEG_LUMA_QUALITY   = 5,  //!< Separate luma quality level, 0 - 100, default is 0 - don't use.——分离腔质量水平
               IMWRITE_JPEG_CHROMA_QUALITY = 6,  //!< Separate chroma quality level, 0 - 100, default is 0 - don't use.——分离色度质量水平

               //对于PNG,它可以是0到9之间的压缩级别。较高的值意味着较小的大小和较长的压缩时间。如果指定,策略将更改为IMWRITE_png_strategy_default(z_default_strategy)。默认值为1(最佳速度设置)。

               IMWRITE_PNG_COMPRESSION     = 16, //!< For PNG, it can be the compression level from 0 to 9. A higher value means a smaller size and longer compression time. If specified, strategy is changed to IMWRITE_PNG_STRATEGY_DEFAULT (Z_DEFAULT_STRATEGY). Default value is 1 (best speed setting).
               IMWRITE_PNG_STRATEGY        = 17, //!< One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_RLE

                                      enum ImwritePNGFlags {
                                             IMWRITE_PNG_STRATEGY_DEFAULT      = 0, //!< Use this value for normal data.
                                             IMWRITE_PNG_STRATEGY_FILTERED     = 1, //!< Use this value for data produced by a filter (or predictor).Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better.——对于由过滤器(或预测器)生成的数据,使用该值。过滤后的数据主要由具有某种随机分布的小值组成。在这种情况下,将调整压缩算法以更好地压缩它们。
                                             IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, //!< Use this value to force Huffman encoding only (no string match).——使用此值仅强制哈夫曼编码(无字符串匹配)
                                             IMWRITE_PNG_STRATEGY_RLE          = 3, //!< Use this value to limit match distances to one (run-length encoding).——使用此值将匹配距离限制为一(运行长度编码)。
                                             IMWRITE_PNG_STRATEGY_FIXED        = 4  //!< Using this value prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications.——使用该值可防止使用动态哈夫曼码,从而为特殊应用提供更简单的解码器。
                                           };

               IMWRITE_PNG_BILEVEL         = 18, //!< Binary level PNG, 0 or 1, default is 0.——二进制级别png,0或1,默认值为0。
               IMWRITE_PXM_BINARY          = 32, //!< For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1.——对于PPM、PGM或PBM,它可以是二进制格式标志0或1。默认值为1。
               IMWRITE_EXR_TYPE            = (3 << 4) + 0, /* 48 */ //!< override EXR storage type (FLOAT (FP32) is default)
               IMWRITE_WEBP_QUALITY        = 64, //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used.
               IMWRITE_PAM_TUPLETYPE       = 128,//!< For PAM, sets the TUPLETYPE field to the corresponding string value that is defined for the format
               IMWRITE_TIFF_RESUNIT = 256,//!< For TIFF, use to specify which DPI resolution unit to set; see libtiff documentation for valid values
               IMWRITE_TIFF_XDPI = 257,//!< For TIFF, use to specify the X direction DPI
               IMWRITE_TIFF_YDPI = 258 //!< For TIFF, use to specify the Y direction DPI
             };
分离图像矩阵通道(split()):// void split(const Mat& src,Mat *mvBegin);
                std::vector<Mat> channels;
                Mat aChannels[3];
                split(src, aChannels);              //利用数组分离  //src为要分离的Mat对象
                split(src, channels);               //利用vector对象分离  
                //注意:opencv中,RGB三个通道是反过来的 //可能有人会问为什么分离出的通道都是黑白灰,而不是红绿蓝。原因是分离后为单通道,相当于分离通道的同时把其他两个通道填充了相同的数值。
                imshow("B",channels[0]);
                imshow("G",channels[1]);
                imshow("R",channels[2]);

        引申:合并图像通道(merge())
矩阵数据类型:// CV_(S|U|F)C //S = 符号整型 U = 无符号整型 F = 浮点型
        CV_8UC1:是指一个8位无符号整型单通道矩阵。
        CV_32FC2:是指一个32位浮点型双通道矩阵。
        CV_8UC1         CV_8SC1         CV_16UC1         CV_16SC1 
        CV_8UC2         CV_8SC2         CV_16UC2         CV_16SC2 
        CV_8UC3         CV_8SC3         CV_16UC3         CV_16SC3 
        CV_8UC4         CV_8SC4         CV_16UC4         CV_16SC4 
        CV_32SC1         CV_32FC1         CV_64FC1 
        CV_32SC2         CV_32FC2         CV_64FC2 
        CV_32SC3         CV_32FC3         CV_64FC3 
        CV_32SC4         CV_32FC4         CV_64FC4

        Mat::convertTo(MatTemp2, CV_8U) //拷贝 //把矩阵matTemp转为unsing char类型的矩阵,注在转换过程中有可能数值上会出现一些变化,这个要注意
Mat图像拷贝(clone())
        Mat img_copy = img.clone(); //将img拷贝到img_copy
对坐标为(14,25)的像素重新赋值为25
        img_copy.at<uchar>(14,25) = 25; //8U类型的RGB彩色图像可以使用<Vec3b>,3通道float类型的矩阵可以使用<Vec3f>
报告矩阵是否连续
        bool cv::Mat::isContinuous() const //如果矩阵元素在每行末尾连续存储而没有间隙,则方法返回true。 否则,它返回false。 显然,对于1x1或1xN矩阵总是连续的。一般 用Mat :: create创建的矩阵总是连续的。 但是,如果使用Mat :: col,Mat :: diag等提取矩阵的一部分,或者为外部分配的数据构造矩阵头,则此类矩阵可能不再具有此属性。
返回一个指针指向image第一行第一个元素
        float *p = image.ptr<float>(0); //返回一个指针指向image第一行第一个元素。mat.ptr<...>(1)为第2行第一个元素;mat.ptr<...>(0)[1]为第一行第2个元素。
子矩阵Rect
        Mat A=testMat(Rect(0,1,1,2)); //函数Rect的第一个参数为起始的列,第二个参数为起始的行,第三个参数为子矩阵的列数,第四个参数为子矩阵的行数。

二、openCV应用(VideoCapture类)

构造函数:创建一个VideoCapture类的实例,如果传入对应的参数,可以直接打开视频文件或者要调用的摄像头。
        VideoCapture::VideoCapture()
        VideoCapture::VideoCapture(const string& filename) //filename – 打开的视频文件名
        VideoCapture::VideoCapture(int device) //device – 打开的视频捕获设备id ,如果只有一个摄像头可以填0,表示打开默认的摄像头。
VideoCapture::open //打开一个视频文件或者打开一个捕获视频的设备(摄像头)
        VideoCapture::open(const string& filename) //filename – 打开的视频文件。例:

        capture.open("rtsp://admin:admin123@192.168.1.102:554/cam/realmonitor?channel=1&subtype=0", CAP_FFMPEG);

        capture.open("/home/toson/example-content/Ubuntu_Free_Culture_Showcase/Nathan Haines - Ubuntu Through The Years.ogg");

        VideoCapture::open(int device) //device – 打开的视频捕获设备id ,如果只有一个摄像头可以填0,表示打开默认的摄像头。
VideoCapture.isOpened() //判断是否已经打开
VideoCapture.get(CV_CAP_PROP_POS_FRAMES)参数
        cv2.VideoCapture.get(0)     视频文件的当前位置(播放)以毫秒为单位
        cv2.VideoCapture.get(1)     基于以0开始的被捕获或解码的帧索引(当前帧数)
        cv2.VideoCapture.get(2)     视频文件的相对位置(播放):0=电影开始,1=影片的结尾。
        cv2.VideoCapture.get(3)     在视频流的帧的宽度
        cv2.VideoCapture.get(4)     在视频流的帧的高度
        cv2.VideoCapture.get(5)     帧速率
        cv2.VideoCapture.get(6)     编解码的4字-字符代码
        cv2.VideoCapture.get(7)     视频文件中的帧数(总帧数)
        cv2.VideoCapture.get(8)     返回对象的格式
        cv2.VideoCapture.get(9)     返回后端特定的值,该值指示当前捕获模式
        cv2.VideoCapture.get(10)     图像的亮度(仅适用于照相机)
        cv2.VideoCapture.get(11)     图像的对比度(仅适用于照相机)
        cv2.VideoCapture.get(12)     图像的饱和度(仅适用于照相机)
        cv2.VideoCapture.get(13)     色调图像(仅适用于照相机)
        cv2.VideoCapture.get(14)     图像增益(仅适用于照相机)(Gain在摄影中表示白平衡提升)
        cv2.VideoCapture.get(15)     曝光(仅适用于照相机)
        cv2.VideoCapture.get(16)     指示是否应将图像转换为RGB布尔标志
        cv2.VideoCapture.get(17)     × 暂时不支持
        cv2.VideoCapture.get(18)     立体摄像机的矫正标注(目前只有DC1394 v.2.x后端支持这个功能)
VideoCapture.read(frame) //读取视频流为Mat图像
        Mat frame; //当前视频帧
        capture.read(frame);
        capture >> frame;
VideoCapture.set(CV_CAP_PROP_BUFFERSIZE, 3) //设置缓存帧数量
        cv2.VideoCapture.set(CV_CAP_PROP_POS_FRAMES, 10)     //基于以0开始的被捕获或解码的帧索引(当前帧数)
cvtColor(frame, frame, COLOR_BGR2GRAY); // 颜色空间转换(变换为灰度图)

三、程序

img_resize.cpp:我用来压缩图片和调整大小用的。
//
// Created by toson on 19-2-22.
//
#include "common.h"
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
#include <string.h>
#include <fstream>

using namespace std;
using namespace cv;

/*********************************************
名称:image_resize
功能:图片大小压缩
输入:
 filename:   文件路径名
 size_cols:  输出文件列像素值(列)
 size_rows:输出文件行像素值(行)
返回值:
true  成功
false 失败
*********************************************/
int image_resize(string filename, int size_cols, int size_rows) {
    try {
        cout << "img_resize test." << endl;
        //读取图片
        Mat img = imread(filename);
        //显示图片
        //imshow("she_img_0", img);
        //waitKey(100 * 1000);
        //pause();//system("pause");

        //压缩图片大小
        resize(img, img, Size(size_cols, size_rows), 0, 0, CV_INTER_LINEAR);
        //显示压缩后的图片
        //    imshow("she_img_1_resize", img);
        //    waitKey(100 * 1000);

        //保存压缩后的图片
        filename.insert(filename.find_last_of('.'), "_resize_"+ to_string(size_cols) + "_" + to_string(size_rows));
        cout << "Save as " << filename << endl;
        imwrite(filename, img);
    }
    catch (exception &e) {
        cout << e.what() << endl;
        return false;
    }
    return true;
}

/*********************************************
名称:image_encode
功能:图片编码压缩
输入:
 filename:文件路径名
 file_ext:  输出文件格式
 Cr:              压缩比:default(95) 0-100
返回值:
true  成功
false 失败
*********************************************/
bool image_encode(string filename, const String file_ext, const int Cr = 95)
{
    try{
        //read a image
        Mat img = imread(filename);
        //display the image
    //    imshow("img_0", img);
    //    waitKey(10 * 1000);
    //    destroyWindow("simg_0");

        //the image stream size
        vector<uchar> img_data;
        imencode(".bmp", img, img_data);
        cout << "The image stream size(bmp): " << img_data.size() << endl;

        //data stream to mat image
        Mat image = imdecode(img_data, CV_LOAD_IMAGE_COLOR);
//        cout << "imshow stream image" << endl;
//        imshow("stream image", image);
//        waitKey(10 * 1000);
//        destroyWindow("stream image");

        //set encode parameter
        vector<int> encode_param= vector<int>(2);
        encode_param[0]=CV_IMWRITE_JPEG_QUALITY;
        encode_param[1]=Cr;//default(95) 0-100
        //start encode the image
        vector<uchar> encoded_data;//buffer for coding
        imencode(file_ext, image, encoded_data, encode_param);
        cout<<"image size(" << file_ext << "): "<<encoded_data.size()<<endl;

        //save JPG encode as file *_decode.jpg
        filename.erase(filename.find_last_of('.'));
        filename = filename + "_encode_"+ to_string(Cr) + "%" + file_ext;
        cout << "Save as " << filename << endl;
        ofstream outfile;
        outfile.open(filename);
        string encoded_data_str(encoded_data.begin(), encoded_data.end());
        outfile << encoded_data_str;
        outfile.close();
//        Mat encode_img = imdecode(encoded_data, CV_LOAD_IMAGE_COLOR);
//        imwrite(filename, encode_img);
    }
    catch  (exception& e)  {
        cout << e.what() << endl;
        return false;
    }
    return true;
}

int main(){
    cout << "img_to_stream test" << endl;

    image_resize("/home/toson/emotion_demo/she.bmp", 960, 540);

    image_encode("/home/toson/emotion_demo/she.bmp", ".jpg", 95);

    cout << "end." << endl;
    //sleep(1000);
    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值