• OpenCV3入门(四)图像的基础操作


    1、访问图像像素

    1)灰度图像

    2)彩色图像

    OpenCV中的颜色顺序是BGR而不是RGB。

    访问图像的像素在OpenCV中就是访问Mat矩阵,常用的有三种方法。

    •  at定位符访问

    Mat数据结构,操作灰度图像像素点:

    int gray_value = (int) image.at<uchar>(i , j) ;

    操作彩色图像像素点:

    int color_value = (int) image.at<Vec3b>(i , j) [k];

    • 指针访问
    for (int i = 0; i < mat.rows; i++)
    {
        uchar* row = mat.ptr<uchar>(i); // 行指针
        for (int j = 0; j < mat.cols; j++) // 遍历每一行
        {
            row[j] = (uchar)((j / 5) * 10); 
        }
    }
    • 迭代器iterator访问
    Mat_<Vec3b>::iterator it = M.begin<Vec3b>();//初始位置的迭代器
    Mat_<Vec3b>::iterator itend = M.end<Vec3b>();//终止位置的迭代器
    for (; it != itend; it++)
    {
        //处理BGR三个通道
        (*it)[0] = 182;//B
        (*it)[1] = 194;//G
        (*it)[2] = 154;//R
    }

    2、图像亮度、对比度调节

    图像亮度调节可以等效为图像的像素操作。如下面公式是一个线性的亮度调节。

    g(x)=a*f(x) + b

    其中:

    g(x):处理后的图像

    f(x):输入图像

    a:增益(放大倍数),用来控制图像的对比度

    b:偏置,用控制图像的亮度

    Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic4.bmp", IMREAD_GRAYSCALE);
    Mat M2 = Mat(M.rows, M.cols, CV_8UC1);
    cout << M.channels() << endl;
    cout << M.rows<<","<<M.cols << endl;
    
    float a = 0.5;
    float b = 10;
    for (int i = 0; i < M.rows; i++)
        for (int j = 0; j < M.cols; j++)
        {
            float pix = (float)M.at<uchar>(i, j);
            pix = a * (float)pix + b;
            if ((int)pix > 255) pix = 255;
            M2.at<uchar>(i, j) = (uchar) pix;
        }
    
    imshow("pic1", M);
    imshow("pic2", M2);
    waitKey(0);

    3、获取图像ROI区域

    图像的ROI(region of interest)是指图像中感兴趣区域、在OpenCV中图像设置图像ROI区域,实现对ROI区域操作。

    方法1:

    img(Rect(100, 100, 100, 100));

    Rect代表一个矩形,Rect_ (_Tp _x, _Tp _y, _Tp _width, _Tp _height),参数分别是x,y,width,height。

    方法2:

    img(Range(100, 200), Range(100,200));

    Range表示连续的行或列,Range (int _start, int _end);

    示例:

    Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic1.bmp");
    cout << M.rows<<","<<M.cols << endl;
    Mat roi = M(Rect(30, 50, 150, 170));
    
    imshow("pic1", M);
    imshow("roi", roi);

    4、图像混合

    图像线性混合,产生类似画中画的效果。

    h(x)=(1-a)*f(x) + b*g(x)

    a的取值范围为0到1之间,通过对两幅图的像素加权得到最终的输出图像,两幅图像的大小和类型必须完全一致(两个矩阵相加维度必须一致)。

    CV_EXPORTS_W void addWeighted(InputArray src1, double alpha, InputArray src2,

                       double beta, double gamma, OutputArray dst, int dtype = -1);

    例1:图片与背景图混合

    Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic1.bmp");
    cout << M.rows<<","<<M.cols << endl;
    Mat y(M.rows, M.cols, CV_8UC3, Scalar(0, 50, 100));
    Mat dst;
    addWeighted(M, 0.3, y, 0.7, 0.0, dst);
    
    imshow("pic1", M);
    imshow("y", y);
    imshow("add", dst);

    例2:两幅图像混合,先统一尺寸

    Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic1.bmp");
    Mat M2 = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic2.bmp");
    M2 = M2(Rect(0, 0, M.cols, M.rows)); //x,y,width,height
    cout << M.rows<<","<<M.cols << endl;
    cout << M2.rows << "," << M2.cols << endl;
    Mat dst;
    addWeighted(M, 0.7, M2, 0.3, 0.0, dst);
    
    imshow("pic1", M);
    imshow("pic2", M2);
    imshow("add", dst);

    5、图像多通道分离

    1)函数原型

    /** @brief Divides a multi-channel array into several single-channel arrays.
    @param src input multi-channel array.
    @param mvbegin output array; the number of arrays must match src.channels(); the arrays themselves are reallocated, if needed.
    */
    CV_EXPORTS void split(const Mat& src, Mat* mvbegin);
    
    /** @overload
    @param m input multi-channel array.
    @param mv output vector of arrays; the arrays themselves are reallocated, if needed.
    */

    2)图像颜色通道

    Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic5.bmp");
    vector<Mat> channels;
    split(M, channels);
    
    imshow("pic1", M);
    imshow("B", channels.at(0));
    imshow("G", channels.at(1));
    imshow("R", channels.at(2));
    /* 方法2
    Mat channels[3];
    split(M, channels);
    
    imshow("pic1", M);
    imshow("B", channels[0]);
    imshow("G", channels[1]);
    imshow("R", channels[2]);

     6、图像多通道合并

    图像合并函数mergesplit的逆操作,将多个数组合并成多通道的数组。

    merge(const Mat * mv, size_t count, OutputArray       dst )

    merge(InputArrayOfArrays mv, OutputArray dst )      

    //图像合并例子,方式1:
    Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic5.bmp");
    Mat channels[3];
    split(M, channels);
    
    imshow("pic1", M);
    imshow("B", channels[0]);
    imshow("G", channels[1]);
    imshow("R", channels[2]);
    
    Mat dst;
    merge(channels, 3, dst);
    imshow("merged", M);
    //方式2:
    Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic5.bmp");
    vector<Mat> channels;
    split(M, channels);
    
    imshow("pic1", M);
    imshow("B", channels.at(0));
    imshow("G", channels.at(1));
    imshow("R", channels.at(2));
    
    Mat dst;
    merge(channels, dst);
    imshow("merged", M);

    输出如下图。

    7、参考文献

    1、《OpenCV3 编程入门》,电子工业出版社,毛星雨著

    2、《学习OpenCV》,清华大学出版社,Gary Bradski Adrian kaehler

    3opencv常用api简单分析: split()merge()

     

    尊重原创技术文章,转载请注明。

     https://www.cnblogs.com/pingwen/p/12296617.html

  • 相关阅读:
    LeetCode 93. Restore IP Addresses
    LeetCode 92. Reverse Linked List II
    LeetCode 94. Binary Tree Inorder Traversal
    javaweb中重定向和请求转发(response.sendRedirect()和request.getRequestDispatcher(rul).forward(request,response)))的区别
    java关于jdbc的配置与使用步骤
    关于php中的include html文件的问题,为什么html可以在php中执行
    yii2 无法显示debug条的问题解决方法
    elasticsearch报错expected <block end>, but found BlockMappingStart解决方法
    sysctl -p 报错问题的解决方法
    yii2 Rbac使用yii命令一键建表
  • 原文地址:https://www.cnblogs.com/pingwen/p/12296617.html
Copyright © 2020-2023  润新知