【opencv/core module】(四)Operations with images

说在前面

Input&Output

  • imread
    读取图像,默认3通道(即BGR)

    Mat img = imread(filename);
    

    读取图像为灰度图

    Mat img = imread(filename, IMREAD_GRAYSCALE);
    

    查找资料貌似不能用这个读取gif
    在这里插入图片描述
    在这里插入图片描述

  • imwrite

    imwrite(filename, img);
    

    jpg格式保存为png格式
    在这里插入图片描述

Basic operations with images(图像基操)

  • Accessing pixel intensity values(访问像素值)

    要获取像素平均强度值,我们需要知道图像的通道数以及图像的类型

    首先我们考虑灰度图,其访问方式为:

    Scalar intensity = img.at<uchar>(y, x);
    
    //对于at<>中的取值
    //If matrix is of type CV_8U then use Mat.at<uchar>(y,x). 无符号char型
    //If matrix is of type CV_8S then use Mat.at<schar>(y,x). 有符号char型
    //If matrix is of type CV_16U then use Mat.at<ushort>(y,x). 无符号short型
    //If matrix is of type CV_16S then use Mat.at<short>(y,x).  有符号short型
    //If matrix is of type CV_32S then use Mat.at<int>(y,x).
    //If matrix is of type CV_32F then use Mat.at<float>(y,x).
    //If matrix is of type CV_64F then use Mat.at<double>(y,x).
    
    //若对(y,x)这种访问方式不习惯,opencv还提供了另一种方式
    //Scalar intensity = img.at<uchar>(Point(x, y));
    
    /*对于Scalar
    typedef struct Scalar
    {
    	double val[4];
    }Scalar;
    */
    

    对于为何使用(y,x)可以参考下图,坐标系如下左图,img.at (y, x)的函数原型为Mat::at(row, col)
    在这里插入图片描述
    然后我们考虑多通道的图像

    		Vec3b intensity = img.at<Vec3b>(y, x);
            uchar blue = intensity.val[0];
            uchar green = intensity.val[1];
            uchar red = intensity.val[2];
            
            //对于Vec3b
            //     typedef Vec<uchar, 3> cv::Vec3b
            //其他还有Vec3f,规则类似
            //     typedef Vec<float, 3> cv::Vec3f
    

    同样,我们可以通过这种方式更改其对应的值

    //单通道,这里也可以访问三通道的图像,但是访问的不是(y,x)那个像素
    img.at<uchar>(y, x) = 128;
    
    //三通道,CV_8UC3
    img.at<Vec3b>(y,x)[0] = 128;
    img.at<Vec3b>(y,x)[1] = 128;
    img.at<Vec3b>(y,x)[2] = 128;
    

    最后,opencv提供points array到matric的转换

    std::vector<Point2f> points;
    
    points.push_back(Point2f(0, 1));
    points.push_back(Point2f(1, 1));
    points.push_back(Point2f(2, 1));
    points.push_back(Point2f(5, 1));
    
    Mat pointsMat = Mat(points);
    

    输出结果为:
    在这里插入图片描述

  • Memory management and reference counting(内存管理&引用计数)

    由于Mat类维护的是图像/矩阵的信息以及一个指向数据的指针,可能会出现多个Mat的指针指向同一块数据,这样我们就需要考虑这块数据的释放问题(何时释放、被谁释放等)
    在这里插入图片描述

  • Primitive operations

    opencv提供了一系列基本的图像处理操作,这里举个栗子。

    Mat img, grey;
    
    //原图
    img = imread("test1.jpg");
    imshow("operations_before", img);
    
    //定义一个矩形(x,y,宽,高)原图的右半部分
    Rect r(img.cols / 2, 0, img.cols / 2, img.rows);
    
    //设置感兴趣区域,用的下面这种方法
    //可以知道smallImg中的数据指针指向的是img对应的数据部分
    //没有发生内存拷贝
    Mat smallImg = img(r);
    
    //这里同理,原图的左半部分
    Rect rC(0, 0, img.cols / 2, img.rows);
    Mat smallImgC = img(rC);
    
    //我们在这里克隆一份左半部分
    Mat src = smallImgC.clone();
    
    //将灰度图保存一下,src、grey指向不同的数据
    cvtColor(src, grey, COLOR_BGR2GRAY);
    
    //然后将src复制到smallImg,也就是原图的右半部分
    src.copyTo(smallImg, grey);
    
    imshow("operations",img);
    

    在这里插入图片描述在这里插入图片描述

  • Visualizing images(显示图像)

    • 使用namedWindow(“image”, WINDOW_AUTOSIZE)来创建窗口;
    • WINDOW_AUTOSIZE,窗口大小适合Mat大小,且不可更改
    • WINDOW_FREERATIO,在生成窗口后可以更改窗口大小(就像你调整浏览器窗口大小那样)
    • 注意,这里的Sobel等函数我们暂时先不管
    	Mat img = imread("image.jpg");
        Mat grey;
        cvtColor(img, grey, COLOR_BGR2GRAY);
        Mat sobelx;
        Sobel(grey, sobelx, CV_32F, 1, 0);
        double minVal, maxVal;
        minMaxLoc(sobelx, &minVal, &maxVal); //find minimum and maximum intensities
        Mat draw;
        sobelx.convertTo(draw, CV_8U, 255.0/(maxVal - minVal), 
        						-minVal * 255.0/(maxVal - minVal));
        namedWindow("image", WINDOW_AUTOSIZE);
        imshow("image", draw);
        waitKey();
    

    在这里插入图片描述
    在这里插入图片描述

  • 补充(imread PNG格式图片)

    • 我们知道png格式的图片有的地方是透明的,即没有像素,那么读取到Mat中是什么亚子的呢?
    • 我们使用一张png图片进行实验
      Mat img = imread("pikachu.png");
      Vec3b intensity = img.at<Vec3b>(0, 0);
      cout << intensity << endl;
      imshow("png", img);
      
    • 结果如下图,可以看到无像素的位置的intensity为[0,0,0]
      在这里插入图片描述
    • 然后测试其转换成灰度图后无像素的位置的值也是0;
    • 这样我们就知道copyTo()函数中mask的作用了,通过判断mask像素值是否为0来决定是否要将该位置的src像素复制到目标图像上,这样我们就可以只关注png图像中有像素的地方了。
    src.copyTo(smallImg, grey);
    /*
    void cv::Mat::copyTo 
    (
    OutputArray m, 
    InputArray mask 
    )const*/
    
    • 就像这样

    在这里插入图片描述

    • 最后还有一个问题要考虑,像素值为0其实还可以是纯黑色,如果图像原本就有一块纯黑的部分,那么是会当成无像素处理还是黑色来处理呢?(自己先思考下)

END-2019.6.27~2019.6.28

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值