Bootstrap

深入浅出(八)opencv2库

1. opencv2库

1.1 opencv2库下载

  1. 官方地址:https://sourceforge.net/projects/opencvlibrary/files/

2. 编译和部署

OpenCV 数据结构

基本数据结构

对于单通道图像,Mat.at(i,j)表示第i行j列的像素值
对于多通道图像,如RGB图像,Mat.at(i,j)[c],[c]表示某个通道在(i,j)位置的像素值。c取0就是B分量,取1就是G分量,取2就是R分量。

32 表示单精度
64 表示双精度
F  表示浮点
U  表示无符号
S  表示有符号
Cx 表示通道数,如RGB三通道
//矩阵类型          数据类型
  CV_8U      Mat.at<uchar>(y,x)        表示8位无符号整数(0255)
  CV_8S      Mat.at<schar>(y,x)        表示8位有符号整数(-128127)
  CV_16U     Mat.at<ushort>(y,x)       表示16位无符号整数(065535)
  CV_16S     Mat.at<short>(y,x)        表示16位有符号整数(-3276832767)
  CV_32S     Mat.at<int>(y,x)          表示32位有符号整数(-21474836482147483647)
  CV_32F     Mat.at<float>(y,x)        表示32位浮点数
  CV_64F     Mat.at<double>(y,x)       表示64位浮点数

图像类型

CV_8UC1
CV_8UC3
CV_32FC3

CV_8UC1转化为CV_8UC3

Mat dst;
Mat src(height, width, CV_8UC1, (unsigned char*) captureClient->data());
//法一
src.convertTo(dst, CV_8UC3);
//法二:该图像与灰度CV_8UC1时的外观相同,但它将是类型为CV_8UC3的3通道图像。
cvtColor(src, dst, COLOR_GRAY2RGB);

API

cv::imread 与 cv::imwrite

cv::imread 读图像列表

//官方API
cv::Mat imread( const String& filename, int flags = IMREAD_COLOR);
//示例
std::string file_path= "D:\work";
//示例一
cv::Mat image = cv::imread(file_path + "\\" + file_name);
//示例二
cv::Mat image = cv::imread(file_path + "/depth.tiff", cv::IMREAD_UNCHANGED);

cv::imwrite写图像

//官方API
bool imwrite( const String& filename, InputArray img,
              const std::vector<int>& params = std::vector<int>());
//示例
std::string file_path= "D:\work";
cv::Mat image; 
cv::imwrite(file_path+ "/image.bmp", image);

//深度图,tiff 格式
std::vector<int> compression;
compression.push_back(cv::IMWRITE_TIFF_COMPRESSION);
compression.push_back(0);
cv::imwrite("C:/Users/Desktop/123123/image_depth1.tiff", image_depth);
cv::imwrite("C:/Users/Desktop/123123/image_depth1.tiff", image_depth, compression);

示例接口

bool WriteImagelist(const std::string file_path, std::vector<cv::Mat> image_list) {
    for (unsigned int i = 0; i < image_list.size(); i++) {
        if (!cv::imwrite(file_path + "/image" + std::to_string(i) + ".bmp", image_list[i])) {
            return false;
        }
    }
    return true;
}

cv::imshow

cv::imshow("display title", image);
cv::waitKey(500);
cv::destroyWindow("display title");

cv::FileStorage

//读 json 文件
bool ReadSaveFile(cv::Mat& test_max, double& test_double) {
    std::string file_path = "D:/work";
    cv::FileStorage fs(file_path + "/test.json", cv::FileStorage::WRITE); 
    fs["Mat"]    >> test_max;
    fs["double"] >> test_double;
    fs.release();
    return true;
}
//写 json 文件
bool SaveFile() {
    //数据示例
    cv::Mat test_max;
    double test_double = 0.008;
    
    std::string file_path = "D:/work";
    cv::FileStorage fs(file_path + "/test.json", cv::FileStorage::WRITE); 
    fs << "Mat" << test_max;
    fs << "double" <<test_double;
    fs.release();
    return true;
}

cv::merge 与 cv::split

在图像处理中,有时需要对各个通道进行分离,分别处理;或者进行通道合并。

cv::split()用于实现图像通道的分离。

cv::Mat image;
cv::split(src,channels);
cv::Mat channel_red   = channels.at(2);
cv::Mat channel_green = channels.at(1);
cv::Mat channel_blue  = channels.at(0);

cv::merge()用于实现图像通道的合并,是split的逆向操作。

cv::Mat image;
std::vector<cv::Mat> channels;
cv::merge(channels, image);

附录一:获取文件夹下文件

//获取文件夹路径
#include <QFileDialog>
QString filePath = QFileDialog::getExistingDirectory(this, tr("Selet Path"), "./");
对比方法一和方法二
方法一能够输出每一个文件的名称,且只识别图像格式的文件,其他文件会被过滤。
方法二更加简单,不过文件夹下只能有图片格式的文件,否则存在隐患。
  1. 使用QT QFileDialog
#include <QFileDialog>
bool ReadImagelist(const QString file_path, std::vector<cv::Mat> image_list) {
    QDir dir(file_path);
    QStringList image_type_list;
    image_type_list << "*.bmp" << "*.jpg" << "*.png";//向字符串列表添加图片类型
    dir.setNameFilters(image_type_list);             //获得文件夹下图片的名字
    int ImageCount = dir.count();                    //获得dir里名字的个数,也表示文件夹下图片的个数
    for (int i=0;i < ImageCount; i++)
    {
        cv::Mat image = cv::imread((file_path + "\\" + dir[i]).toStdString());
        qDebug() << QString::number(222) + ": " + file_path + dir[i];//输出图片名
        image_list.push_back(image);
    }
    return true;
}
  1. 使用CV库
bool ReadImagelist(const std::string file_path, std::vector<cv::Mat> image_list) {
    std::vector<std::string> file_name;
    cv::glob(file_path, file_name, false);
    for (int i = 0; i < file_name.size(); i++)
    {
        cv::Mat image = cv::imread(file_name[i]);
        qDebug() << QString::number(111) + ": " + QString::fromStdString(file_name[i]);
        image_list.push_back(image);
    }
    return true;
}
;