OpenCV之图像处理(四) Mat对象

Mat对象OpenCV2.0之后引进的图像数据结构、自动分配内存、不存在内存泄漏的问题,是面向对象的数据结构。分了两个部分,头部与数据部分
IplImage是从2001年OpenCV发布之后就一直存在,是C语言风格的数据结构,需要开发者自己分配与管理内存,对大的程序使用它容易导致内存泄漏问题,不建议使用了

Mat对象构造函数:(部分)
    Mat();
    Mat(int rows, int cols, int type);
    Mat(Size size, int type);
    Mat(int rows, int cols, int type, const Scalar& s);
    Mat(Size size, int type, const Scalar& s);
    Mat(int ndims, const int* sizes, int type);
    Mat(int ndims, const int* sizes, int type, const Scalar& s);
常用方法:
    void copyTo(Mat mat)                    //完全复制一份
    void convertTo(Mat dst, int type)       //转换,比如8位的转换为float
    Mat clone()                             //完全复制一份
    int channels()                          //通道数
    int depth()                             //深度
    bool empty();                           //是否空
    uchar* ptr(i=0)                         //矩阵数据指针
Mat对象使用-四个要点:
    输出图像的内存是自动分配的
    使用OpenCV的C++接口,不需要考虑内存分配问题
    赋值操作和拷贝构造函数只会复制头部分
    使用clone与copyTo两个函数实现数据完全复制

创建多维数组cv::Mat::create
    int sz[3] = {2,2,2};     
    Mat  L(3,sz, CV_8UC1, Scalar::all(0)); //这里的3表示3维数组

vs代码

    #include <opencv2/opencv.hpp>
    #include <iostream>
    using namespace std;
    using namespace cv;
    void main(int argc, char** argv)
    {
        Mat src;
        double time, timeconsume;
        src = imread("D:/hankin/opencv/images/test1_3.png", IMREAD_COLOR);
        if (!src.data)
        {
            printf("could not load image..");
            return;
        }
        namedWindow("input image", CV_WINDOW_AUTOSIZE);
        imshow("input image", src);

        Mat dst = Mat(src.size(), src.type());
        dst = Scalar(127, 0, 255);//给矩阵所有的像素点设置颜色数据,绯红,这里的 = 号运算符重载了。。   Scalar参数顺序是 B G R
        //Mat dst = src.clone();//完全拷贝
        /*Mat dst;
        src.copyTo(dst);//完全拷贝*/
        //Mat dst = imread("...");//只是复制部分,Mat对象头部与数据的指针,不会复制数据
        //Mat dst(src);//只是复制部分,Mat对象头部与数据的指针,不会复制数据
        namedWindow("output image", CV_WINDOW_AUTOSIZE);
        imshow("output image", dst);

        cvtColor(src, dst, CV_BGR2GRAY);//dst对象输出图像的内存是自动分配的
        printf("rgb.channels=%d, gray.channels=%d,%d,%d\n", src.channels(), dst.channels(), src.type(), dst.type());//rgb通道数为3,gray通道数为1,16,0

        const uchar* firstRow = dst.ptr<uchar>(0);//图像第一行颜色数据
        printf("first pixel value : %d\n", *firstRow);
        printf("dst.cols=%d, dst.rows=%d\n", dst.cols, dst.rows);

        // CV_8UC1 8表示8位,UC表示unsigned char,1表示1个通道, Scalar表示向量长度,要与通道数目一致
        Mat m(3, 3, CV_8UC3, Scalar(0, 0, 255));//3*3个像素点,CV_8UC3表示像素点为三个通道颜色数据,CV_8UC1表示像素点为单通道,对应的传 Scalar(255) 
        cout << "m = " << endl << m << endl;//打印每个通道颜色数据
        /*  m =
                [  0,   0, 255,   0,   0, 255,   0,   0, 255;
                   0,   0, 255,   0,   0, 255,   0,   0, 255;
                   0,   0, 255,   0,   0, 255,   0,   0, 255]
        */
        imshow("scalar", m);

        Mat m1;
        m1.create(src.size(), src.type());//以create方式创建Mat
        m1 = Scalar(0, 0, 255);//Scalar参数顺序是 B G R
        imshow("create", m1);
        //Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); //定义小数组,以 << 运算符重载 创建Mat
        Mat zeros = Mat::zeros(2, 2, CV_8UC1);//初始值0
        cout << "zeros = " << endl << zeros << endl;
        /*
            zeros =
                [0,   0;
                 0,   0]
            eye =
                [1,   0;
                 0,   1;
                 0,   0]
        */
        Mat eye = Mat::eye(3, 2, CV_8UC1);//沿着主对角线的像素点(不是通道)的第一个通道的数据设置为1,其他都为0,对于CV_8UC1的方阵可以生成单一矩阵
        cout << "eye = " << endl << eye << endl;
        waitKey(0);
    }

效果图

这里写图片描述

android代码

@BindView(R.id.iv_opencv1_4_origin) ImageView mOriginIv;
@BindView(R.id.iv_opencv1_4_convert1) ImageView mConvert1Iv;
@BindView(R.id.iv_opencv1_4_convert2) ImageView mConvert2Iv;
private Bitmap mOriginBmp;
private Bitmap mConvert1Bmp;
private Bitmap mConvert2Bmp;
private Mat mOriginMat = new Mat();
private Mat mConvert1Mat;
private Mat mConvert2Mat = new Mat();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_cv1_4);
    mUnbinder = ButterKnife.bind(this);

    //origin
    mOriginBmp = CV310Utils.getBitmapFromAssets(this, "opencv/test1_3.png");//格式是Bitmap.Config.ARGB_8888
    mOriginIv.setImageBitmap(mOriginBmp);
    mConvert1Bmp = Bitmap.createBitmap(mOriginBmp.getWidth(), mOriginBmp.getHeight(), Bitmap.Config.RGB_565);
    mConvert2Bmp = Bitmap.createBitmap(mOriginBmp.getWidth(), mOriginBmp.getHeight(), Bitmap.Config.ARGB_8888);
    Utils.bitmapToMat(mOriginBmp, mOriginMat);//只支持RGB_565或ARGB_8888,Mat生成的是4通道的RGBA
    LogUtils.d("mydebug---", "origin.channels="+mOriginMat.channels()+",origin.type="+mOriginMat.type());//origin.channels=4,origin.type=24

    //convert1
    mConvert1Mat = new Mat(mOriginMat.size(), mOriginMat.type());
    Scalar scalar1 = new Scalar(255, 0, 127, 64);//c++中scalar参数是BGR排列顺序,java中是RGBA ,因为mConvert1Bmp是 RGB_565 所以 alpha 在Scalar不起作用
    mConvert1Mat.setTo(scalar1);//给矩阵所有的像素点设置颜色数据,绯红
    Utils.matToBitmap(mConvert1Mat, mConvert1Bmp);
    LogUtils.d("mydebug---", "rgb565.channels="+mOriginMat.channels()+",rgb565.type="+mOriginMat.type());//rgb565.channels=4,rgb565.type=24
    mConvert1Iv.setImageBitmap(mConvert1Bmp);

    //convert2
    mConvert2Mat.create(mOriginMat.size(), mOriginMat.type());//create方式创建Mat
    Scalar scalar2 = new Scalar(255, 0, 127, 64);//由于mConvert2Bmp是 ARGB_8888,所以 alpha 会在Scalar起作用
    mConvert2Mat.setTo(scalar2);
    Utils.matToBitmap(mConvert2Mat, mConvert2Bmp);
    LogUtils.d("mydebug---", "argb8888.channels="+mOriginMat.channels()+",argb8888.type="+mOriginMat.type());//argb8888.channels=4,argb8888.type=24
    mConvert2Iv.setImageBitmap(mConvert2Bmp);

    Mat gray = new Mat();
    Imgproc.cvtColor(mOriginMat, gray, Imgproc.COLOR_BGR2GRAY);
    LogUtils.d("mydebug---", "gray.channels="+gray.channels()+",gray.type="+gray.type());//gray.channels=1,gray.type=0

    // CV_8UC1 8表示8位,UC表示unsigned char,1表示1个通道, Scalar表示向量长度,要与通道数目一致
    Mat cv_8uc3 = new Mat(3, 3, CvType.CV_8UC3, new Scalar(255, 0, 0));//3*3个像素点,CV_8UC3表示像素点为三个通道颜色数据,CV_8UC1表示像素点为单通道,对应的传 Scalar(255)
    /*  cv_8uc3 =
            255,0,0,255,0,0,255,0,0,
            255,0,0,255,0,0,255,0,0,
            255,0,0,255,0,0,255,0,0,
    */
    LogUtils.d("mydebug---", "cv_8uc3="+CV310Utils.traverseMat(cv_8uc3));//打印每个通道颜色数据

    Mat zeros = Mat.zeros(2, 2, CvType.CV_8UC1);//初始值0
    /*  zeros =
            0,0,
            0,0,
    */
    LogUtils.d("mydebug---", "zeros="+CV310Utils.traverseMat(zeros));

    Mat eye = Mat.eye(3, 2, CvType.CV_8UC2);//沿着主对角线的像素点(不是通道)的第一个通道的数据设置为1,其他都为0,对于CV_8UC1的方阵可以生成单一矩阵
    /*  eye =
            1,0,0,0,
            0,0,1,0,
            0,0,0,0,
    */
    LogUtils.d("mydebug---", "eye="+CV310Utils.traverseMat(eye));
}

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/80866337