美文网首页
图形图像处理算法(4)---- OpenCV 基础类的使用

图形图像处理算法(4)---- OpenCV 基础类的使用

作者: 特立独行的佩奇 | 来源:发表于2023-03-19 22:06 被阅读0次

    基础图像容器Mat

    Mat 是一个类,它由两部分的内容组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向所有像素值的矩阵,因为OpenCV 是一个图像处理库,包含了大量的图像处理函数,为了解决图像在不同的库中进行传递的问题,Mat 类使用了引用计数机制,拷贝构造函数和赋值运算符只复制信息头和矩阵指针,不复制矩阵
    下面的例子只复制矩阵头,不复制图像数据

    Mat A,C
    A = imread("1.jpg", CV_LOAD_IMAGE_COLOR);
    MatB(A);
    C = A;
    

    要拷贝图形的像素值,使用下面 copyTo 和 或者 clone 函数

    //Mat F = mSrcMat.clone();
    //imshow("clone F", F);
    
    Mat M;
    mSrcMat.copyTo(M);
    imshow("copy_to_M", M);
    

    Mat 类的基本属性如下:
    rows 行数 cols 列数 channel 通道数 dims 维数 depth 单行的字节数 size 返回一个Size 类型

    cout << "mSrcMat source rows:" << mSrcMat.rows << " cols:" << mSrcMat.cols << " channels: " << mSrcMat.channels() << endl;
    cout << " dims: " << mSrcMat.dims << " depth: " << mSrcMat.depth() << " steps(stride): " << mSrcMat.step << " size: " << mSrcMat.size << endl;
    

    图像载入函数 imread

    Mat imread( const String& filename, int flags = IMREAD_COLOR );
    第一个参数:OpenCV 支持下面类型的图像载入
    Windows bitmaps - *.bmp, *.dib
    JPEG files - *.jpeg, *.jpg, *.jpe
    JPEG 2000 files - *.jp2
    Portable Network Graphics - *.png
    Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm

    第二个参数 常用的选择如下:
    IMREAD_UNCHANGED = -1, //按照图像原样读取,保留Alpha通道(第4通道)
    IMREAD_GRAYSCALE = 0, //IMREAD_COLOR 将图像转成单通道灰度图像后读取
    IMREAD_COLOR = 1, //将图像转换成3通道BGR彩色图像
    IMREAD_ANYDEPTH = 2, //保留原图像的16位、32位深度,不声明该参数则转成8位读取
    IMREAD_ANYCOLOR = 4, //以任何可能的颜色读取图像

    可以通过 empty 函数判断是否read 正常

    图像显示函数 imshow

    void imshow(const String& winname, InputArray mat);
    第一个参数 表示要显示的窗体标志名称
    第二个参数 填写要显示的图像

    输出图像到文件 imwrite

    bool imwrite( const String& filename, InputArray img, const std::vector<int>& params = std::vector<int>());
    第一个参数表示要写入的文件名,输出文件格式用文件名的后缀进行区分
    第二个参数是 Mat 类型的图像容器
    第三个参数表示为特定格式保存的参数编码
    对于 JPEG 文件,用 CV_IMWRITE_JPEG_QUALITY表示图像质量 (0 ~ 100)
    对于 PNG 格式图片,使用 CV_IMWRITE_PNG_COMPRESSION (0 ~ 9),较高的值表示较小的压缩尺寸和更长的压缩时间

    void basicCvDemo::basicCvImgWrite() {
    // PXM BINARY
    vector<int> comParams{ CV_IMWRITE_PXM_BINARY, 0 };
    {
        
        imwrite("HusKey_output_PXM0.ppm", mSrcMat, comParams);
        comParams.clear();
        comParams.push_back(CV_IMWRITE_PXM_BINARY);
        comParams.push_back(1);
        imwrite("HusKey_output_PXM1.ppm", mSrcMat, comParams);
    }
    
    //JPEG qualicity
    {
        comParams.clear();
        comParams.push_back(CV_IMWRITE_JPEG_QUALITY);
        comParams.push_back(0);
        imwrite("HusKey_output_para0.jpg", mSrcMat, comParams);
    
        comParams.clear();
        comParams.push_back(CV_IMWRITE_JPEG_QUALITY);
        comParams.push_back(30);
        imwrite("HusKey_output_para30.jpg", mSrcMat, comParams);
    
        comParams.clear();
        comParams.push_back(CV_IMWRITE_JPEG_QUALITY);
        comParams.push_back(70);
        imwrite("HusKey_output_para70.jpg", mSrcMat, comParams);
    }
    
    //PNG  压缩级别
    {
        comParams.clear();
        comParams.push_back(CV_IMWRITE_PNG_COMPRESSION);
        comParams.push_back(1);
        imwrite("HusKey_output_para1.png", mSrcMat, comParams);
    
        comParams.clear();
        comParams.push_back(CV_IMWRITE_PNG_COMPRESSION);
        comParams.push_back(5);
        imwrite("HusKey_output_para5.png", mSrcMat, comParams);
    
        comParams.clear();
        comParams.push_back(CV_IMWRITE_PNG_COMPRESSION);
        comParams.push_back(9);
        imwrite("HusKey_output_para9.png", mSrcMat, comParams);
    }
    //bmp 
    {
        imwrite("HusKey_output.bmp", mSrcMat);
    }
    }
    

    Mat 的构造方法

    • 直接使用 Mat 构造函数
      Mat demoMat(300, 300, CV_8UC3, Scalar(0, 0, 255)); // BGR
      300x300 表示 width 和 height
      CV_8UC3 对于CV_[位数][是否带符号]C[通道数] 表示 8位 unsigned 类型,每个像素是三个元素组成的三通道
      Scalar(0, 0, 255) 表示单个 pixel 的内容,用于初始化Mat 类型

    • 使用 create 函数开辟空间
      注意 create 不能对创建的 Mat 类型进行初始化

    • 使用 matlab 的形式 zeros ones 初始化

    {
        Mat demoMat(300, 300, CV_8UC3, Scalar(0, 0, 255)); // BGR
        imshow("demoMat", demoMat);
    }
    
    {
        int sz[3] = { 200,200};
        Mat demoMat(2, sz, CV_8UC3, Scalar(0, 0, 255)); // BGR Scalar::all(0)
        imshow("demoMat", demoMat);
    }
    
    {
        Mat demoMat;
        demoMat.create(200, 200, CV_8UC(2)); // 不能设置初值 只能开辟空间
    }
    
    {
        //Mat demoMat = Mat::ones(100, 100, CV_32F);
        Mat demoMat = Mat::zeros(100, 100, CV_8UC3);
        imshow("demoMat", demoMat);
    }
    

    滑动条的创建和使用

    滑动条的效果如下如所示:


    trackbar.jpg

    用滑动条可以快速的调整程序中的参数值,滑动条的创建流程如下:

    • 创建一个namedWindow,Trackbar 是依附在 namedWindow 之上的
    • createTrackbar 函数创建一个可以调整数值的滑动条,参数中包含一个回调函数,关联的值改变的时候会调用到回调函数
    void basicCvDemo::onTrackBarChanged(int pos, void* userdata) {
        cout << "pos: " << pos << endl;
        double srcAlpha = (double)pos / alphaValueMax;
        double srcBeta = 1.0f - srcAlpha;
    
        addWeighted(mSrcAplhaMat, srcAlpha, mDstAplhaMat, srcBeta, 0.0f, mOutputMat);
    
        imshow("alphaBlendWindow", mOutputMat);
    }
    
    
    void basicCvDemo::alphaBlendUsingTarckBar() {
        int alphaValueSlider = 50; //初始值
    
        const char* windowName = "alphaBlendWindow";
        namedWindow(windowName, 1);
    
        char trackBarName[50] = { 0 };
        sprintf_s(trackBarName, "alpha: %d", alphaValueSlider);
    
    
        createTrackbar(trackBarName, windowName, &alphaValueSlider, alphaValueMax, basicCvDemo::onTrackBarChanged);
        //onTrackBarChanged(alphaValueSlider, nullptr); // 每次改变都调用回调函数
    }
    

    这里使用了addWeighted 函数,用于实现不同的混合效果

    Mat 类中访问像素的几种方式

    • 使用at 函数 获取一个3/4 channel 的Vector 类型
    • 使用指针模板直接访问像素,但是仅仅适用于 8位无符号整数类型的Mat
    • 使用 data 属性获取指向像素区的指针
    Mat demoMat(300, 300, CV_8UC4, Scalar(0, 0, 255)); // 4 channels
    
    
    // using at 
    {
        Vec4b& rgba = demoMat.at<Vec4b>(0, 0);
        printf("Pixels at (0,0) : %d %d %d %d\n", rgba[0], rgba[1], rgba[2], rgba[3]);
    }
    
    //using ptr  比 at 快,但是仅仅适用于 8位无符号整数类型的Mat
    {
        int i = 0;
        int j = 0;
        int pixel_value = demoMat.ptr<uchar>(i)[j];
    }
    
    {
        unsigned char* ptr = demoMat.data;
    
        printf("Pixels at(0,0) %d %d %d %d \n", ptr[0], ptr[1], ptr[2], ptr[3]);
        printf("Pixels at(0,1) %d %d %d %d \n", ptr[4], ptr[5], ptr[6], ptr[7]);
        printf("Pixels at(0,1) %d %d %d %d \n", ptr[8], ptr[9], ptr[10], ptr[11]);
    }
    

    相关文章

      网友评论

          本文标题:图形图像处理算法(4)---- OpenCV 基础类的使用

          本文链接:https://www.haomeiwen.com/subject/pxwyrdtx.html