C/C++ 编程 —— OpenCV API 学习 笔记(更新中...)

41 篇文章 6 订阅
2 篇文章 0 订阅

文档声明:
以下资料均属于本人在学习过程中产出的学习笔记,如果错误或者遗漏之处,请多多指正。并且该文档在后期会随着学习的深入不断补充完善。感谢各位的参考查看。


笔记资料仅供学习交流使用,转载请标明出处,谢谢配合。
如果存在相关知识点的遗漏,可以在评论区留言,看到后将在第一时间更新。
作者:Aliven888

Opencv 开发资料

  在 OpenCV 中,可以用 C++ 语法的 cv::Mat 类来表示一张图像,也可以用 C 语法的 lpllmage 或 CvMat 结构体来表示一张图像。

opencv 库版本:opencv-4.5.3-vc14_vc15

单通道像素值

在这里插入图片描述

多通道像素值

  OpenCV默认颜色顺序为BGR。
在这里插入图片描述

头文件

#include <opencv2/opencv.hpp>

调用库

############################### CMakeLists.txt 调用 #######################################

# CMakeLists.txt 调用
find_package(OpenCV REQUIRED)  # 查找是否安装 opencv
include_directories(${OpenCV_INCLUDE_DIRS}) # 导入头文件
target_link_libraries(${OpenCV_LIBS}) # 导入 opencv 库



###############################  CMakefile 调用   #########################################

INCLIDE_DIR=./thirdparty/hikcamera/include
LIB_DIR=./thirdparty/hikcamera/lib/64
LIBS=-lMvCameraControl -lpthread -lopencv_imgcodecs -lopencv_dnn -lopencv_imgproc -lopencv_core 

Demo:hikDemo.cpp
	g++ -g -o hikCamera hikDemo.cpp -I$(INCLIDE_DIR) -Wl,-rpath=$(LIB_DIR) -L$(LIB_DIR) $(LIBS)

.PHONY : clean
clean:
	-rm -rf hikCamera

函数库介绍

cv::Mat Class

cv::Mat 类能够自动管理内存,由矩阵头和指向存储所有像素值的矩阵的指针构成。

cv::Mat 类表示一个n维的密集数值单通道或多通道数组,它可用于存储实数或复数值的向量和矩阵 灰度和彩色图像、体素、向量场、点云、张量、直方图等。

1、无数据拷贝的cv::Mat的定义和初始化

// 1、默认形式
cv::Mat m;

// 2、指定类型和大小(行列)的二维数组 type = CV_8UC1
cv::Mat m(int rows, int cols, int type);

// 3、有初始化值的指定类型和大小(行列)的二维数组
cv::Mat m(int rows, int cols, int type, const Scalar& s);

// 4、使用预先存在数据定义的指定类型和大小(行列)的二维数组
cv::Mat m(int rows, int cols, int type, void* data, size_t step = AUTO_STEP);

// 5、指定大小(size)和类型的二维数组
cv::Mat m(cv::Size sz, int type, const Scalar& s);

// 6、使用预先存在的数据定义的指定大小(size)和类型的二维数组
cv::Mat m(cv::Size sz, int type, void* data, size_t step = AUTO_STEP);

// 7、指定类型的多维数组
cv::Mat m(int ndims, const int* sizes, int type);

// 8、有初始化值的指定类型多维数组
cv::Mat m(int ndims, const int* sizes, int type, const Scalar& s);

// 9、使用预先存在的数据定义的指定类型的多维数组
cv::Mat m(int ndims, const int* sizes, int type, void* data, size_t step = AUTO_STEP);

2、成员函数详解

    /** @brief assignment operators

    These are available assignment operators. Since they all are very different, make sure to read the
    operator parameters description.
    @param m Assigned, right-hand-side matrix. Matrix assignment is an O(1) operation. This means that
    no data is copied but the data is shared and the reference counter, if any, is incremented. Before
    assigning new data, the old data is de-referenced via Mat::release .
     */
    Mat& operator = (const Mat& m);

    /** @overload
    @param expr Assigned matrix expression object. As opposite to the first form of the assignment
    operation, the second form can reuse already allocated matrix if it has the right size and type to
    fit the matrix expression result. It is automatically handled by the real function that the matrix
    expressions is expanded to. For example, C=A+B is expanded to add(A, B, C), and add takes care of
    automatic C reallocation.
    */
    Mat& operator = (const MatExpr& expr);

    //! retrieve UMat from Mat
    UMat getUMat(int accessFlags, UMatUsageFlags usageFlags = USAGE_DEFAULT) const;

    /** @brief Creates a matrix header for the specified matrix row.

    The method makes a new header for the specified matrix row and returns it. This is an O(1)
    operation, regardless of the matrix size. The underlying data of the new matrix is shared with the
    original matrix. Here is the example of one of the classical basic matrix processing operations,
    axpy, used by LU and many other algorithms:
    @code
        inline void matrix_axpy(Mat& A, int i, int j, double alpha)
        {
            A.row(i) += A.row(j)*alpha;
        }
    @endcode
    @note In the current implementation, the following code does not work as expected:
    @code
        Mat A;
        ...
        A.row(i) = A.row(j); // will not work
    @endcode
    This happens because A.row(i) forms a temporary header that is further assigned to another header.
    Remember that each of these operations is O(1), that is, no data is copied. Thus, the above
    assignment is not true if you may have expected the j-th row to be copied to the i-th row. To
    achieve that, you should either turn this simple assignment into an expression or use the
    Mat::copyTo method:
    @code
        Mat A;
        ...
        // works, but looks a bit obscure.
        A.row(i) = A.row(j) + 0;
        // this is a bit longer, but the recommended method.
        A.row(j).copyTo(A.row(i));
    @endcode
    @param y A 0-based row index.
     */
    Mat row(int y) const;

    /** @brief Creates a matrix header for the specified matrix column.

    The method makes a new header for the specified matrix column and returns it. This is an O(1)
    operation, regardless of the matrix size. The underlying data of the new matrix is shared with the
    original matrix. See also the Mat::row description.
    @param x A 0-based column index.
     */
    Mat col(int x) const;

    /** @brief Creates a matrix header for the specified row span.

    The method makes a new header for the specified row span of the matrix. Similarly to Mat::row and
    Mat::col , this is an O(1) operation.
    @param startrow An inclusive 0-based start index of the row span.
    @param endrow An exclusive 0-based ending index of the row span.
     */
    Mat rowRange(int startrow, int endrow) const;

    /** @overload
    @param r Range structure containing both the start and the end indices.
    */
    Mat rowRange(const Range& r) const;

    /** @brief Creates a matrix header for the specified column span.

    The method makes a new header for the specified column span of the matrix. Similarly to Mat::row and
    Mat::col , this is an O(1) operation.
    @param startcol An inclusive 0-based start index of the column span.
    @param endcol An exclusive 0-based ending index of the column span.
     */
    Mat colRange(int startcol, int endcol) const;

    /** @overload
    @param r Range structure containing both the start and the end indices.
    */
    Mat colRange(const Range& r) const;

    /** @brief Extracts a diagonal from a matrix

    The method makes a new header for the specified matrix diagonal. The new matrix is represented as a
    single-column matrix. Similarly to Mat::row and Mat::col, this is an O(1) operation.
    @param d index of the diagonal, with the following values:
    - `d=0` is the main diagonal.
    - `d<0` is a diagonal from the lower half. For example, d=-1 means the diagonal is set
      immediately below the main one.
    - `d>0` is a diagonal from the upper half. For example, d=1 means the diagonal is set
      immediately above the main one.
    For example:
    @code
        Mat m = (Mat_<int>(3,3) <<
                    1,2,3,
                    4,5,6,
                    7,8,9);
        Mat d0 = m.diag(0);
        Mat d1 = m.diag(1);
        Mat d_1 = m.diag(-1);
    @endcode
    The resulting matrices are
    @code
     d0 =
       [1;
        5;
        9]
     d1 =
       [2;
        6]
     d_1 =
       [4;
        8]
    @endcode
     */
    Mat diag(int d=0) const;

    /** @brief creates a diagonal matrix

    The method creates a square diagonal matrix from specified main diagonal.
    @param d One-dimensional matrix that represents the main diagonal.
     */
    static Mat diag(const Mat& d);

    /** @brief Creates a full copy of the array and the underlying data.

    The method creates a full copy of the array. The original step[] is not taken into account. So, the
    array copy is a continuous array occupying total()*elemSize() bytes.
     */
    Mat clone() const;

    /** @brief Copies the matrix to another one.

    The method copies the matrix data to another matrix. Before copying the data, the method invokes :
    @code
        m.create(this->size(), this->type());
    @endcode
    so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the
    function does not handle the case of a partial overlap between the source and the destination
    matrices.

    When the operation mask is specified, if the Mat::create call shown above reallocates the matrix,
    the newly allocated matrix is initialized with all zeros before copying the data.
    @param m Destination matrix. If it does not have a proper size or type before the operation, it is
    reallocated.
     */
    void copyTo( OutputArray m ) const;

    /** @overload
    @param m Destination matrix. If it does not have a proper size or type before the operation, it is
    reallocated.
    @param mask Operation mask of the same size as \*this. Its non-zero elements indicate which matrix
    elements need to be copied. The mask has to be of type CV_8U and can have 1 or multiple channels.
    */
    void copyTo( OutputArray m, InputArray mask ) const;

    /** @brief Converts an array to another data type with optional scaling.

    The method converts source pixel values to the target data type. saturate_cast\<\> is applied at
    the end to avoid possible overflows:

    \f[m(x,y) = saturate \_ cast<rType>( \alpha (*this)(x,y) +  \beta )\f]
    @param m output matrix; if it does not have a proper size or type before the operation, it is
    reallocated.
    @param rtype desired output matrix type or, rather, the depth since the number of channels are the
    same as the input has; if rtype is negative, the output matrix will have the same type as the input.
    @param alpha optional scale factor.
    @param beta optional delta added to the scaled values.
     */
    void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;

    /** @brief Provides a functional form of convertTo.

    This is an internally used method called by the @ref MatrixExpressions engine.
    @param m Destination array.
    @param type Desired destination array depth (or -1 if it should be the same as the source type).
     */
    void assignTo( Mat& m, int type=-1 ) const;

    /** @brief Sets all or some of the array elements to the specified value.
    @param s Assigned scalar converted to the actual array type.
    */
    Mat& operator = (const Scalar& s);

    /** @brief Sets all or some of the array elements to the specified value.

    This is an advanced variant of the Mat::operator=(const Scalar& s) operator.
    @param value Assigned scalar converted to the actual array type.
    @param mask Operation mask of the same size as \*this. Its non-zero elements indicate which matrix
    elements need to be copied. The mask has to be of type CV_8U and can have 1 or multiple channels
     */
    Mat& setTo(InputArray value, InputArray mask=noArray());

    /** @brief Changes the shape and/or the number of channels of a 2D matrix without copying the data.

    The method makes a new matrix header for \*this elements. The new matrix may have a different size
    and/or different number of channels. Any combination is possible if:
    -   No extra elements are included into the new matrix and no elements are excluded. Consequently,
        the product rows\*cols\*channels() must stay the same after the transformation.
    -   No data is copied. That is, this is an O(1) operation. Consequently, if you change the number of
        rows, or the operation changes the indices of elements row in some other way, the matrix must be
        continuous. See Mat::isContinuous .

    For example, if there is a set of 3D points stored as an STL vector, and you want to represent the
    points as a 3xN matrix, do the following:
    @code
        std::vector<Point3f> vec;
        ...
        Mat pointMat = Mat(vec). // convert vector to Mat, O(1) operation
                          reshape(1). // make Nx3 1-channel matrix out of Nx1 3-channel.
                                      // Also, an O(1) operation
                             t(); // finally, transpose the Nx3 matrix.
                                  // This involves copying all the elements
    @endcode
    @param cn New number of channels. If the parameter is 0, the number of channels remains the same.
    @param rows New number of rows. If the parameter is 0, the number of rows remains the same.
     */
    Mat reshape(int cn, int rows=0) const;

    /** @overload */
    Mat reshape(int cn, int newndims, const int* newsz) const;

    /** @overload */
    Mat reshape(int cn, const std::vector<int>& newshape) const;

    /** @brief Transposes a matrix.

    The method performs matrix transposition by means of matrix expressions. It does not perform the
    actual transposition but returns a temporary matrix transposition object that can be further used as
    a part of more complex matrix expressions or can be assigned to a matrix:
    @code
        Mat A1 = A + Mat::eye(A.size(), A.type())*lambda;
        Mat C = A1.t()*A1; // compute (A + lambda*I)^t * (A + lamda*I)
    @endcode
     */
    MatExpr t() const;

    /** @brief Inverses a matrix.

    The method performs a matrix inversion by means of matrix expressions. This means that a temporary
    matrix inversion object is returned by the method and can be used further as a part of more complex
    matrix expressions or can be assigned to a matrix.
    @param method Matrix inversion method. One of cv::DecompTypes
     */
    MatExpr inv(int method=DECOMP_LU) const;

    /** @brief Performs an element-wise multiplication or division of the two matrices.

    The method returns a temporary object encoding per-element array multiplication, with optional
    scale. Note that this is not a matrix multiplication that corresponds to a simpler "\*" operator.

    Example:
    @code
        Mat C = A.mul(5/B); // equivalent to divide(A, B, C, 5)
    @endcode
    @param m Another array of the same type and the same size as \*this, or a matrix expression.
    @param scale Optional scale factor.
     */
    MatExpr mul(InputArray m, double scale=1) const;

    /** @brief Computes a cross-product of two 3-element vectors.

    The method computes a cross-product of two 3-element vectors. The vectors must be 3-element
    floating-point vectors of the same shape and size. The result is another 3-element vector of the
    same shape and type as operands.
    @param m Another cross-product operand.
     */
    Mat cross(InputArray m) const;

    /** @brief Computes a dot-product of two vectors.

    The method computes a dot-product of two matrices. If the matrices are not single-column or
    single-row vectors, the top-to-bottom left-to-right scan ordering is used to treat them as 1D
    vectors. The vectors must have the same size and type. If the matrices have more than one channel,
    the dot products from all the channels are summed together.
    @param m another dot-product operand.
     */
    double dot(InputArray m) const;

    /** @brief Returns a zero array of the specified size and type.

    The method returns a Matlab-style zero array initializer. It can be used to quickly form a constant
    array as a function parameter, part of a matrix expression, or as a matrix initializer. :
    @code
        Mat A;
        A = Mat::zeros(3, 3, CV_32F);
    @endcode
    In the example above, a new matrix is allocated only if A is not a 3x3 floating-point matrix.
    Otherwise, the existing matrix A is filled with zeros.
    @param rows Number of rows.
    @param cols Number of columns.
    @param type Created matrix type.
     */
    static MatExpr zeros(int rows, int cols, int type);

    /** @overload
    @param size Alternative to the matrix size specification Size(cols, rows) .
    @param type Created matrix type.
    */
    static MatExpr zeros(Size size, int type);

    /** @overload
    @param ndims Array dimensionality.
    @param sz Array of integers specifying the array shape.
    @param type Created matrix type.
    */
    static MatExpr zeros(int ndims, const int* sz, int type);

    /** @brief Returns an array of all 1's of the specified size and type.

    The method returns a Matlab-style 1's array initializer, similarly to Mat::zeros. Note that using
    this method you can initialize an array with an arbitrary value, using the following Matlab idiom:
    @code
        Mat A = Mat::ones(100, 100, CV_8U)*3; // make 100x100 matrix filled with 3.
    @endcode
    The above operation does not form a 100x100 matrix of 1's and then multiply it by 3. Instead, it
    just remembers the scale factor (3 in this case) and use it when actually invoking the matrix
    initializer.
    @param rows Number of rows.
    @param cols Number of columns.
    @param type Created matrix type.
     */
    static MatExpr ones(int rows, int cols, int type);

    /** @overload
    @param size Alternative to the matrix size specification Size(cols, rows) .
    @param type Created matrix type.
    */
    static MatExpr ones(Size size, int type);

    /** @overload
    @param ndims Array dimensionality.
    @param sz Array of integers specifying the array shape.
    @param type Created matrix type.
    */
    static MatExpr ones(int ndims, const int* sz, int type);

    /** @brief Returns an identity matrix of the specified size and type.

    The method returns a Matlab-style identity matrix initializer, similarly to Mat::zeros. Similarly to
    Mat::ones, you can use a scale operation to create a scaled identity matrix efficiently:
    @code
        // make a 4x4 diagonal matrix with 0.1's on the diagonal.
        Mat A = Mat::eye(4, 4, CV_32F)*0.1;
    @endcode
    @param rows Number of rows.
    @param cols Number of columns.
    @param type Created matrix type.
     */
    static MatExpr eye(int rows, int cols, int type);

    /** @overload
    @param size Alternative matrix size specification as Size(cols, rows) .
    @param type Created matrix type.
    */
    static MatExpr eye(Size size, int type);

    /** @brief Allocates new array data if needed.

    This is one of the key Mat methods. Most new-style OpenCV functions and methods that produce arrays
    call this method for each output array. The method uses the following algorithm:

    -# If the current array shape and the type match the new ones, return immediately. Otherwise,
       de-reference the previous data by calling Mat::release.
    -# Initialize the new header.
    -# Allocate the new data of total()\*elemSize() bytes.
    -# Allocate the new, associated with the data, reference counter and set it to 1.

    Such a scheme makes the memory management robust and efficient at the same time and helps avoid
    extra typing for you. This means that usually there is no need to explicitly allocate output arrays.
    That is, instead of writing:
    @code
        Mat color;
        ...
        Mat gray(color.rows, color.cols, color.depth());
        cvtColor(color, gray, COLOR_BGR2GRAY);
    @endcode
    you can simply write:
    @code
        Mat color;
        ...
        Mat gray;
        cvtColor(color, gray, COLOR_BGR2GRAY);
    @endcode
    because cvtColor, as well as the most of OpenCV functions, calls Mat::create() for the output array
    internally.
    @param rows New number of rows.
    @param cols New number of columns.
    @param type New matrix type.
     */
    void create(int rows, int cols, int type);

    /** @overload
    @param size Alternative new matrix size specification: Size(cols, rows)
    @param type New matrix type.
    */
    void create(Size size, int type);

    /** @overload
    @param ndims New array dimensionality.
    @param sizes Array of integers specifying a new array shape.
    @param type New matrix type.
    */
    void create(int ndims, const int* sizes, int type);

    /** @overload
    @param sizes Array of integers specifying a new array shape.
    @param type New matrix type.
    */
    void create(const std::vector<int>& sizes, int type);

    /** @brief Increments the reference counter.

    The method increments the reference counter associated with the matrix data. If the matrix header
    points to an external data set (see Mat::Mat ), the reference counter is NULL, and the method has no
    effect in this case. Normally, to avoid memory leaks, the method should not be called explicitly. It
    is called implicitly by the matrix assignment operator. The reference counter increment is an atomic
    operation on the platforms that support it. Thus, it is safe to operate on the same matrices
    asynchronously in different threads.
     */
    void addref();

    /** @brief Decrements the reference counter and deallocates the matrix if needed.

    The method decrements the reference counter associated with the matrix data. When the reference
    counter reaches 0, the matrix data is deallocated and the data and the reference counter pointers
    are set to NULL's. If the matrix header points to an external data set (see Mat::Mat ), the
    reference counter is NULL, and the method has no effect in this case.

    This method can be called manually to force the matrix data deallocation. But since this method is
    automatically called in the destructor, or by any other method that changes the data pointer, it is
    usually not needed. The reference counter decrement and check for 0 is an atomic operation on the
    platforms that support it. Thus, it is safe to operate on the same matrices asynchronously in
    different threads.
     */
    void release();

    //! internal use function, consider to use 'release' method instead; deallocates the matrix data
    void deallocate();
    //! internal use function; properly re-allocates _size, _step arrays
    void copySize(const Mat& m);

    /** @brief Reserves space for the certain number of rows.

    The method reserves space for sz rows. If the matrix already has enough space to store sz rows,
    nothing happens. If the matrix is reallocated, the first Mat::rows rows are preserved. The method
    emulates the corresponding method of the STL vector class.
    @param sz Number of rows.
     */
    void reserve(size_t sz);

    /** @brief Reserves space for the certain number of bytes.

    The method reserves space for sz bytes. If the matrix already has enough space to store sz bytes,
    nothing happens. If matrix has to be reallocated its previous content could be lost.
    @param sz Number of bytes.
    */
    void reserveBuffer(size_t sz);

    /** @brief Changes the number of matrix rows.

    The methods change the number of matrix rows. If the matrix is reallocated, the first
    min(Mat::rows, sz) rows are preserved. The methods emulate the corresponding methods of the STL
    vector class.
    @param sz New number of rows.
     */
    void resize(size_t sz);

    /** @overload
    @param sz New number of rows.
    @param s Value assigned to the newly added elements.
     */
    void resize(size_t sz, const Scalar& s);

    //! internal function
    void push_back_(const void* elem);

    /** @brief Adds elements to the bottom of the matrix.

    The methods add one or more elements to the bottom of the matrix. They emulate the corresponding
    method of the STL vector class. When elem is Mat , its type and the number of columns must be the
    same as in the container matrix.
    @param elem Added element(s).
     */
    template<typename _Tp> void push_back(const _Tp& elem);

    /** @overload
    @param elem Added element(s).
    */
    template<typename _Tp> void push_back(const Mat_<_Tp>& elem);

    /** @overload
    @param elem Added element(s).
    */
    template<typename _Tp> void push_back(const std::vector<_Tp>& elem);

    /** @overload
    @param m Added line(s).
    */
    void push_back(const Mat& m);

    /** @brief Removes elements from the bottom of the matrix.

    The method removes one or more rows from the bottom of the matrix.
    @param nelems Number of removed rows. If it is greater than the total number of rows, an exception
    is thrown.
     */
    void pop_back(size_t nelems=1);

    /** @brief Locates the matrix header within a parent matrix.

    After you extracted a submatrix from a matrix using Mat::row, Mat::col, Mat::rowRange,
    Mat::colRange, and others, the resultant submatrix points just to the part of the original big
    matrix. However, each submatrix contains information (represented by datastart and dataend
    fields) that helps reconstruct the original matrix size and the position of the extracted
    submatrix within the original matrix. The method locateROI does exactly that.
    @param wholeSize Output parameter that contains the size of the whole matrix containing *this*
    as a part.
    @param ofs Output parameter that contains an offset of *this* inside the whole matrix.
     */
    void locateROI( Size& wholeSize, Point& ofs ) const;

    /** @brief Adjusts a submatrix size and position within the parent matrix.

    The method is complimentary to Mat::locateROI . The typical use of these functions is to determine
    the submatrix position within the parent matrix and then shift the position somehow. Typically, it
    can be required for filtering operations when pixels outside of the ROI should be taken into
    account. When all the method parameters are positive, the ROI needs to grow in all directions by the
    specified amount, for example:
    @code
        A.adjustROI(2, 2, 2, 2);
    @endcode
    In this example, the matrix size is increased by 4 elements in each direction. The matrix is shifted
    by 2 elements to the left and 2 elements up, which brings in all the necessary pixels for the
    filtering with the 5x5 kernel.

    adjustROI forces the adjusted ROI to be inside of the parent matrix that is boundaries of the
    adjusted ROI are constrained by boundaries of the parent matrix. For example, if the submatrix A is
    located in the first row of a parent matrix and you called A.adjustROI(2, 2, 2, 2) then A will not
    be increased in the upward direction.

    The function is used internally by the OpenCV filtering functions, like filter2D , morphological
    operations, and so on.
    @param dtop Shift of the top submatrix boundary upwards.
    @param dbottom Shift of the bottom submatrix boundary downwards.
    @param dleft Shift of the left submatrix boundary to the left.
    @param dright Shift of the right submatrix boundary to the right.
    @sa copyMakeBorder
     */
    Mat& adjustROI( int dtop, int dbottom, int dleft, int dright );

    /** @brief Extracts a rectangular submatrix.

    The operators make a new header for the specified sub-array of \*this . They are the most
    generalized forms of Mat::row, Mat::col, Mat::rowRange, and Mat::colRange . For example,
    `A(Range(0, 10), Range::all())` is equivalent to `A.rowRange(0, 10)`. Similarly to all of the above,
    the operators are O(1) operations, that is, no matrix data is copied.
    @param rowRange Start and end row of the extracted submatrix. The upper boundary is not included. To
    select all the rows, use Range::all().
    @param colRange Start and end column of the extracted submatrix. The upper boundary is not included.
    To select all the columns, use Range::all().
     */
    Mat operator()( Range rowRange, Range colRange ) const;

    /** @overload
    @param roi Extracted submatrix specified as a rectangle.
    */
    Mat operator()( const Rect& roi ) const;

    /** @overload
    @param ranges Array of selected ranges along each array dimension.
    */
    Mat operator()( const Range* ranges ) const;

    /** @overload
    @param ranges Array of selected ranges along each array dimension.
    */
    Mat operator()(const std::vector<Range>& ranges) const;

    // //! converts header to CvMat; no data is copied
    // operator CvMat() const;
    // //! converts header to CvMatND; no data is copied
    // operator CvMatND() const;
    // //! converts header to IplImage; no data is copied
    // operator IplImage() const;

    template<typename _Tp> operator std::vector<_Tp>() const;
    template<typename _Tp, int n> operator Vec<_Tp, n>() const;
    template<typename _Tp, int m, int n> operator Matx<_Tp, m, n>() const;

#ifdef CV_CXX_STD_ARRAY
    template<typename _Tp, std::size_t _Nm> operator std::array<_Tp, _Nm>() const;
#endif

    /** @brief Reports whether the matrix is continuous or not.

    The method returns true if the matrix elements are stored continuously without gaps at the end of
    each row. Otherwise, it returns false. Obviously, 1x1 or 1xN matrices are always continuous.
    Matrices created with Mat::create are always continuous. But if you extract a part of the matrix
    using Mat::col, Mat::diag, and so on, or constructed a matrix header for externally allocated data,
    such matrices may no longer have this property.

    The continuity flag is stored as a bit in the Mat::flags field and is computed automatically when
    you construct a matrix header. Thus, the continuity check is a very fast operation, though
    theoretically it could be done as follows:
    @code
        // alternative implementation of Mat::isContinuous()
        bool myCheckMatContinuity(const Mat& m)
        {
            //return (m.flags & Mat::CONTINUOUS_FLAG) != 0;
            return m.rows == 1 || m.step == m.cols*m.elemSize();
        }
    @endcode
    The method is used in quite a few of OpenCV functions. The point is that element-wise operations
    (such as arithmetic and logical operations, math functions, alpha blending, color space
    transformations, and others) do not depend on the image geometry. Thus, if all the input and output
    arrays are continuous, the functions can process them as very long single-row vectors. The example
    below illustrates how an alpha-blending function can be implemented:
    @code
        template<typename T>
        void alphaBlendRGBA(const Mat& src1, const Mat& src2, Mat& dst)
        {
            const float alpha_scale = (float)std::numeric_limits<T>::max(),
                        inv_scale = 1.f/alpha_scale;

            CV_Assert( src1.type() == src2.type() &&
                       src1.type() == CV_MAKETYPE(traits::Depth<T>::value, 4) &&
                       src1.size() == src2.size());
            Size size = src1.size();
            dst.create(size, src1.type());

            // here is the idiom: check the arrays for continuity and,
            // if this is the case,
            // treat the arrays as 1D vectors
            if( src1.isContinuous() && src2.isContinuous() && dst.isContinuous() )
            {
                size.width *= size.height;
                size.height = 1;
            }
            size.width *= 4;

            for( int i = 0; i < size.height; i++ )
            {
                // when the arrays are continuous,
                // the outer loop is executed only once
                const T* ptr1 = src1.ptr<T>(i);
                const T* ptr2 = src2.ptr<T>(i);
                T* dptr = dst.ptr<T>(i);

                for( int j = 0; j < size.width; j += 4 )
                {
                    float alpha = ptr1[j+3]*inv_scale, beta = ptr2[j+3]*inv_scale;
                    dptr[j] = saturate_cast<T>(ptr1[j]*alpha + ptr2[j]*beta);
                    dptr[j+1] = saturate_cast<T>(ptr1[j+1]*alpha + ptr2[j+1]*beta);
                    dptr[j+2] = saturate_cast<T>(ptr1[j+2]*alpha + ptr2[j+2]*beta);
                    dptr[j+3] = saturate_cast<T>((1 - (1-alpha)*(1-beta))*alpha_scale);
                }
            }
        }
    @endcode
    This approach, while being very simple, can boost the performance of a simple element-operation by
    10-20 percents, especially if the image is rather small and the operation is quite simple.

    Another OpenCV idiom in this function, a call of Mat::create for the destination array, that
    allocates the destination array unless it already has the proper size and type. And while the newly
    allocated arrays are always continuous, you still need to check the destination array because
    Mat::create does not always allocate a new matrix.
     */
    bool isContinuous() const;

    //! returns true if the matrix is a submatrix of another matrix
    bool isSubmatrix() const;

    /** @brief Returns the matrix element size in bytes.

    The method returns the matrix element size in bytes. For example, if the matrix type is CV_16SC3 ,
    the method returns 3\*sizeof(short) or 6.
     */
    size_t elemSize() const;

    /** @brief Returns the size of each matrix element channel in bytes.

    The method returns the matrix element channel size in bytes, that is, it ignores the number of
    channels. For example, if the matrix type is CV_16SC3 , the method returns sizeof(short) or 2.
     */
    size_t elemSize1() const;

    /** @brief Returns the type of a matrix element.

    The method returns a matrix element type. This is an identifier compatible with the CvMat type
    system, like CV_16SC3 or 16-bit signed 3-channel array, and so on.
     */
    int type() const;

    /** @brief Returns the depth of a matrix element.

    The method returns the identifier of the matrix element depth (the type of each individual channel).
    For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of
    matrix types contains the following values:
    -   CV_8U - 8-bit unsigned integers ( 0..255 )
    -   CV_8S - 8-bit signed integers ( -128..127 )
    -   CV_16U - 16-bit unsigned integers ( 0..65535 )
    -   CV_16S - 16-bit signed integers ( -32768..32767 )
    -   CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
    -   CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
    -   CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
     */
    int depth() const;

    /** @brief Returns the number of matrix channels.

    The method returns the number of matrix channels.
     */
    int channels() const;

    /** @brief Returns a normalized step.

    The method returns a matrix step divided by Mat::elemSize1() . It can be useful to quickly access an
    arbitrary matrix element.
     */
    size_t step1(int i=0) const;

    /** @brief Returns true if the array has no elements.

    The method returns true if Mat::total() is 0 or if Mat::data is NULL. Because of pop_back() and
    resize() methods `M.total() == 0` does not imply that `M.data == NULL`.
     */
    bool empty() const;

    /** @brief Returns the total number of array elements.

    The method returns the number of array elements (a number of pixels if the array represents an
    image).
     */
    size_t total() const;

    /** @brief Returns the total number of array elements.

     The method returns the number of elements within a certain sub-array slice with startDim <= dim < endDim
     */
    size_t total(int startDim, int endDim=INT_MAX) const;

    /**
     * @param elemChannels Number of channels or number of columns the matrix should have.
     *                     For a 2-D matrix, when the matrix has only 1 column, then it should have
     *                     elemChannels channels; When the matrix has only 1 channel,
     *                     then it should have elemChannels columns.
     *                     For a 3-D matrix, it should have only one channel. Furthermore,
     *                     if the number of planes is not one, then the number of rows
     *                     within every plane has to be 1; if the number of rows within
     *                     every plane is not 1, then the number of planes has to be 1.
     * @param depth The depth the matrix should have. Set it to -1 when any depth is fine.
     * @param requireContinuous Set it to true to require the matrix to be continuous
     * @return -1 if the requirement is not satisfied.
     *         Otherwise, it returns the number of elements in the matrix. Note
     *         that an element may have multiple channels.
     *
     * The following code demonstrates its usage for a 2-d matrix:
     * @snippet snippets/core_mat_checkVector.cpp example-2d
     *
     * The following code demonstrates its usage for a 3-d matrix:
     * @snippet snippets/core_mat_checkVector.cpp example-3d
     */
    int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const;

    /** @brief Returns a pointer to the specified matrix row.

    The methods return `uchar*` or typed pointer to the specified matrix row. See the sample in
    Mat::isContinuous to know how to use these methods.
    @param i0 A 0-based row index.
     */
    uchar* ptr(int i0=0);
    /** @overload */
    const uchar* ptr(int i0=0) const;

    /** @overload
    @param row Index along the dimension 0
    @param col Index along the dimension 1
    */
    uchar* ptr(int row, int col);
    /** @overload
    @param row Index along the dimension 0
    @param col Index along the dimension 1
    */
    const uchar* ptr(int row, int col) const;

    /** @overload */
    uchar* ptr(int i0, int i1, int i2);
    /** @overload */
    const uchar* ptr(int i0, int i1, int i2) const;

    /** @overload */
    uchar* ptr(const int* idx);
    /** @overload */
    const uchar* ptr(const int* idx) const;
    /** @overload */
    template<int n> uchar* ptr(const Vec<int, n>& idx);
    /** @overload */
    template<int n> const uchar* ptr(const Vec<int, n>& idx) const;

    /** @overload */
    template<typename _Tp> _Tp* ptr(int i0=0);
    /** @overload */
    template<typename _Tp> const _Tp* ptr(int i0=0) const;
    /** @overload
    @param row Index along the dimension 0
    @param col Index along the dimension 1
    */
    template<typename _Tp> _Tp* ptr(int row, int col);
    /** @overload
    @param row Index along the dimension 0
    @param col Index along the dimension 1
    */
    template<typename _Tp> const _Tp* ptr(int row, int col) const;
    /** @overload */
    template<typename _Tp> _Tp* ptr(int i0, int i1, int i2);
    /** @overload */
    template<typename _Tp> const _Tp* ptr(int i0, int i1, int i2) const;
    /** @overload */
    template<typename _Tp> _Tp* ptr(const int* idx);
    /** @overload */
    template<typename _Tp> const _Tp* ptr(const int* idx) const;
    /** @overload */
    template<typename _Tp, int n> _Tp* ptr(const Vec<int, n>& idx);
    /** @overload */
    template<typename _Tp, int n> const _Tp* ptr(const Vec<int, n>& idx) const;

    /** @brief Returns a reference to the specified array element.

    The template methods return a reference to the specified array element. For the sake of higher
    performance, the index range checks are only performed in the Debug configuration.

    Note that the variants with a single index (i) can be used to access elements of single-row or
    single-column 2-dimensional arrays. That is, if, for example, A is a 1 x N floating-point matrix and
    B is an M x 1 integer matrix, you can simply write `A.at<float>(k+4)` and `B.at<int>(2*i+1)`
    instead of `A.at<float>(0,k+4)` and `B.at<int>(2*i+1,0)`, respectively.

    The example below initializes a Hilbert matrix:
    @code
        Mat H(100, 100, CV_64F);
        for(int i = 0; i < H.rows; i++)
            for(int j = 0; j < H.cols; j++)
                H.at<double>(i,j)=1./(i+j+1);
    @endcode

    Keep in mind that the size identifier used in the at operator cannot be chosen at random. It depends
    on the image from which you are trying to retrieve the data. The table below gives a better insight in this:
     - If matrix is of type `CV_8U` then use `Mat.at<uchar>(y,x)`.
     - If matrix is of type `CV_8S` then use `Mat.at<schar>(y,x)`.
     - If matrix is of type `CV_16U` then use `Mat.at<ushort>(y,x)`.
     - If matrix is of type `CV_16S` then use `Mat.at<short>(y,x)`.
     - 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)`.

    @param i0 Index along the dimension 0
     */
    template<typename _Tp> _Tp& at(int i0=0);
    /** @overload
    @param i0 Index along the dimension 0
    */
    template<typename _Tp> const _Tp& at(int i0=0) const;
    /** @overload
    @param row Index along the dimension 0
    @param col Index along the dimension 1
    */
    template<typename _Tp> _Tp& at(int row, int col);
    /** @overload
    @param row Index along the dimension 0
    @param col Index along the dimension 1
    */
    template<typename _Tp> const _Tp& at(int row, int col) const;

    /** @overload
    @param i0 Index along the dimension 0
    @param i1 Index along the dimension 1
    @param i2 Index along the dimension 2
    */
    template<typename _Tp> _Tp& at(int i0, int i1, int i2);
    /** @overload
    @param i0 Index along the dimension 0
    @param i1 Index along the dimension 1
    @param i2 Index along the dimension 2
    */
    template<typename _Tp> const _Tp& at(int i0, int i1, int i2) const;

    /** @overload
    @param idx Array of Mat::dims indices.
    */
    template<typename _Tp> _Tp& at(const int* idx);
    /** @overload
    @param idx Array of Mat::dims indices.
    */
    template<typename _Tp> const _Tp& at(const int* idx) const;

    /** @overload */
    template<typename _Tp, int n> _Tp& at(const Vec<int, n>& idx);
    /** @overload */
    template<typename _Tp, int n> const _Tp& at(const Vec<int, n>& idx) const;

    /** @overload
    special versions for 2D arrays (especially convenient for referencing image pixels)
    @param pt Element position specified as Point(j,i) .
    */
    template<typename _Tp> _Tp& at(Point pt);
    /** @overload
    special versions for 2D arrays (especially convenient for referencing image pixels)
    @param pt Element position specified as Point(j,i) .
    */
    template<typename _Tp> const _Tp& at(Point pt) const;

    /** @brief Returns the matrix iterator and sets it to the first matrix element.

    The methods return the matrix read-only or read-write iterators. The use of matrix iterators is very
    similar to the use of bi-directional STL iterators. In the example below, the alpha blending
    function is rewritten using the matrix iterators:
    @code
        template<typename T>
        void alphaBlendRGBA(const Mat& src1, const Mat& src2, Mat& dst)
        {
            typedef Vec<T, 4> VT;

            const float alpha_scale = (float)std::numeric_limits<T>::max(),
                        inv_scale = 1.f/alpha_scale;

            CV_Assert( src1.type() == src2.type() &&
                       src1.type() == traits::Type<VT>::value &&
                       src1.size() == src2.size());
            Size size = src1.size();
            dst.create(size, src1.type());

            MatConstIterator_<VT> it1 = src1.begin<VT>(), it1_end = src1.end<VT>();
            MatConstIterator_<VT> it2 = src2.begin<VT>();
            MatIterator_<VT> dst_it = dst.begin<VT>();

            for( ; it1 != it1_end; ++it1, ++it2, ++dst_it )
            {
                VT pix1 = *it1, pix2 = *it2;
                float alpha = pix1[3]*inv_scale, beta = pix2[3]*inv_scale;
                *dst_it = VT(saturate_cast<T>(pix1[0]*alpha + pix2[0]*beta),
                             saturate_cast<T>(pix1[1]*alpha + pix2[1]*beta),
                             saturate_cast<T>(pix1[2]*alpha + pix2[2]*beta),
                             saturate_cast<T>((1 - (1-alpha)*(1-beta))*alpha_scale));
            }
        }
    @endcode
     */
    template<typename _Tp> MatIterator_<_Tp> begin();
    template<typename _Tp> MatConstIterator_<_Tp> begin() const;

    /** @brief Returns the matrix iterator and sets it to the after-last matrix element.

    The methods return the matrix read-only or read-write iterators, set to the point following the last
    matrix element.
     */
    template<typename _Tp> MatIterator_<_Tp> end();
    template<typename _Tp> MatConstIterator_<_Tp> end() const;

    /** @brief Runs the given functor over all matrix elements in parallel.

    The operation passed as argument has to be a function pointer, a function object or a lambda(C++11).

    Example 1. All of the operations below put 0xFF the first channel of all matrix elements:
    @code
        Mat image(1920, 1080, CV_8UC3);
        typedef cv::Point3_<uint8_t> Pixel;

        // first. raw pointer access.
        for (int r = 0; r < image.rows; ++r) {
            Pixel* ptr = image.ptr<Pixel>(r, 0);
            const Pixel* ptr_end = ptr + image.cols;
            for (; ptr != ptr_end; ++ptr) {
                ptr->x = 255;
            }
        }

        // Using MatIterator. (Simple but there are a Iterator's overhead)
        for (Pixel &p : cv::Mat_<Pixel>(image)) {
            p.x = 255;
        }

        // Parallel execution with function object.
        struct Operator {
            void operator ()(Pixel &pixel, const int * position) {
                pixel.x = 255;
            }
        };
        image.forEach<Pixel>(Operator());

        // Parallel execution using C++11 lambda.
        image.forEach<Pixel>([](Pixel &p, const int * position) -> void {
            p.x = 255;
        });
    @endcode
    Example 2. Using the pixel's position:
    @code
        // Creating 3D matrix (255 x 255 x 255) typed uint8_t
        // and initialize all elements by the value which equals elements position.
        // i.e. pixels (x,y,z) = (1,2,3) is (b,g,r) = (1,2,3).

        int sizes[] = { 255, 255, 255 };
        typedef cv::Point3_<uint8_t> Pixel;

        Mat_<Pixel> image = Mat::zeros(3, sizes, CV_8UC3);

        image.forEach<Pixel>([&](Pixel& pixel, const int position[]) -> void {
            pixel.x = position[0];
            pixel.y = position[1];
            pixel.z = position[2];
        });
    @endcode
     */
    template<typename _Tp, typename Functor> void forEach(const Functor& operation);
    /** @overload */
    template<typename _Tp, typename Functor> void forEach(const Functor& operation) const;

#ifdef CV_CXX_MOVE_SEMANTICS
    Mat(Mat&& m);
    Mat& operator = (Mat&& m);
#endif

    enum { MAGIC_VAL  = 0x42FF0000, AUTO_STEP = 0, CONTINUOUS_FLAG = CV_MAT_CONT_FLAG, SUBMATRIX_FLAG = CV_SUBMAT_FLAG };
    enum { MAGIC_MASK = 0xFFFF0000, TYPE_MASK = 0x00000FFF, DEPTH_MASK = 7 };

    /*! includes several bit-fields:
         - the magic signature
         - continuity flag
         - depth
         - number of channels
     */
    int flags;
    //! the matrix dimensionality, >= 2
    int dims;
    //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
    int rows, cols;
    //! pointer to the data
    uchar* data;

    //! helper fields used in locateROI and adjustROI
    const uchar* datastart;
    const uchar* dataend;
    const uchar* datalimit;

    //! custom allocator
    MatAllocator* allocator;
    //! and the standard allocator
    static MatAllocator* getStdAllocator();
    static MatAllocator* getDefaultAllocator();
    static void setDefaultAllocator(MatAllocator* allocator);

    //! interaction with UMat
    UMatData* u;

    MatSize size;
    MatStep step;

protected:
    template<typename _Tp, typename Functor> void forEach_impl(const Functor& operation);

3、从其他cv::Mat进行数据拷贝的定义和初始化

// 1、拷贝构造形式
cv::Mat m(const cv::Mat& mat);

// 2、指定行列范围的拷贝构造
cv::Mat m(const cv::Mat& mat, const cv::Range& rows, const cv::Range& cols);

// 3、指定ROI的拷贝构造
cv::Mat m(const cv::Mat& mat, const cv::Rect& roi);

// 4、使用多维数组中指定范围内的数据的拷贝构造
cv::Mat(const cv::Mat& mat, const cv::Range* ranges);

4、使用OpenCV中的模板进行定义和初始化

// 1、使用cv::Vec定义相同类型、大小为n的一维数组
cv::Mat m(const cv::Vec<T, n>& vec, bool = copyData = true);

// 2、使用cv::Matx定义相同类型、大小为mxn的二维数组
cv::Mat(const cv::Matx<T, m, n>& vec, bool copyData = true);

// 3、使用STL vector定义相同类型的一维数组
cv::Mat(const std::vector<T>& vec, bool copyData = true);

5、直接使用静态函数创建cv::Mat

// 1、使用zeros()函数定义指定大小和类型的cv::Mat(全为0)
cv::Mat m = cv::Mat::zeros(int rows, int cols, int type);

// 2、使用ones()函数定义指定大小和类型的cv::Mat(全为0)
cv::Mat m = cv::Mat::ones(int rows, int cols, int type);

// 3、使用eye()函数定义指定大小和类型的cv::Mat(恒等矩阵)
cv::Mat m = cv::Mat::eye(int rows, int cols, int type);

6、IplImage与CV::Mat之间的转换

// A. 将IplImage-----> Mat类型
Mat::Mat(const IplImage* img, bool copyData=false);

// 默认情况下,新的Mat类型与原来的IplImage类型共享图像数据,转换只是创建一个Mat矩阵头。
// 当将参数copyData设为true后,就会复制整个图像数据。

// eg:
IplImage*iplImg = cvLoadImage("greatwave.jpg", 1);
Matmtx(iplImg); // IplImage* ->Mat 共享数据
// or : Mat mtx = iplImg;或者是:Mat mtx(iplImg,0); // 0是不复制影像,也就是iplImg的data共用同个记意位置,header各自有

// B. 将Mat类型转换-----> IplImage类型
// 同样只是创建图像头,而没有复制数据。

IplImage ipl_img = img; // Mat -> IplImage
IplImage*-> BYTE*
BYTE* data= img->imageData;

7、CvMat 与IPlimage类图片之间的相互转化

// A.CvMat-> IplImage
IplImage* img = cvCreateImage(cvGetSize(mat),8,1);
cvGetImage(matI,img);
cvSaveImage("rice1.bmp",img);


// B.IplImage -> CvMat
IplImage* img = cvLoadimage("leda.jpg",1);
//法1:
CvMat *mat = cvCreateMat( img->height, img->width, CV_64FC3 );
cvConvert( img, mat );
//法2:
CvMat mathdr;
CvMat *mat = cvGetMat( img, &mathdr );

cv::namedWindow 创建窗口

/*
函数 namedWindow 创建一个窗口,该窗口可用作图像的占位符和轨迹栏。创建的窗口以其名称引用。

如果已存在同名窗口,则该函数不执行任何操作。

您可以调用 cv::destroyWindow 或 cv::destroyAllWindows 来关闭窗口并取消分配任何关联的内存使用情况。对于一个简单的程序,您实际上不必调用这些函数,因为所有的应用程序的资源和窗口在退出时由操作系统自动关闭。

@笔记

Qt 后端支持额外的标志:
 - **WINDOW_NORMAL 或 WINDOW_AUTOSIZE:** WINDOW_NORMAL 使您能够调整窗口,而 WINDOW_AUTOSIZE 自动调整窗口大小以适应显示的图像(请参阅 imshow ),并且您无法手动更改窗口大小。
 - **WINDOW_FREERATIO 或 WINDOW_KEEPRATIO:** WINDOW_FREERATIO 调整图像与它的比例无关,而 WINDOW_KEEPRATIO 保持图像比例。
 - **WINDOW_GUI_NORMAL 或 WINDOW_GUI_EXPANDED:** WINDOW_GUI_NORMAL 是绘制窗口的旧方法没有状态栏和工具栏,而 WINDOW_GUI_EXPANDED 是一个新的增强型 GUI。

默认情况下,标志 == WINDOW_AUTOSIZE | WINDOW_KEEPRATIO | WINDOW_GUI_EXPANDED

@param winname 窗口标题中可用作窗口标识符的窗口名称。
@param flags 窗口的标志。支持的标志是: (cv::WindowFlags)
 */
CV_EXPORTS_W void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE); 

cv::resizeWindow 重置窗口大小

/*
调整窗口到指定大小

- 指定的窗口大小用于图像区域。 工具栏不计算在内。
- 只能调整没有 cv::WINDOW_AUTOSIZE 标志创建的窗口的大小。

@param winname 窗口名称。
@param width 新的窗口宽度。
@param height 新的窗口高度。
*/

CV_EXPORTS_W void resizeWindow(const String& winname, int width, int height);

/* @重载
@param winname 窗口名称。
@param size 新的窗口大小。
*/
CV_EXPORTS_W void resizeWindow(const String& winname, const cv::Size& size);

cv::moveWindow 移动窗口

/* 
将窗口移动到指定位置。

@param winname 窗口的名称。
@param x 窗口的新 x 坐标。
@param y 窗口的新 y 坐标。
*/
CV_EXPORTS_W void moveWindow(const String& winname, int x, int y);

cv::destroyWindow 销毁指定窗口

/**
销毁指定的窗口。函数 destroyWindow 销毁具有给定名称的窗口。

@param winname 要销毁的窗口的名称。
*/
CV_EXPORTS_W void destroyWindow(const String& winname);

cv::destroyAllWindows 销毁全部窗口

/*
函数 destroyAllWindows 销毁所有打开的 HighGUI 窗口。
*/
CV_EXPORTS_W void destroyAllWindows();

cv::Scalar 编辑通道像素

定义:

  首先单词 Scalar 的意思是 标量,可以用来存放4个double数值的数组,一般用来存放像素值(不一定是灰度值哦)的,最多可以存放4个通道的(可初始化 0 - 4 个通道)。

//opencv-4.5.3-vc14_vc15

//定义成了一个模板
template<typename _Tp> inline
Scalar_<_Tp>::Scalar_()
{
    this->val[0] = this->val[1] = this->val[2] = this->val[3] = 0;  // 默认值都是 0
}

template<typename _Tp> inline
Scalar_<_Tp>::Scalar_(_Tp v0, _Tp v1, _Tp v2, _Tp v3)
{
    this->val[0] = v0;
    this->val[1] = v1;
    this->val[2] = v2;
    this->val[3] = v3;
}

template<typename _Tp> inline
Scalar_<_Tp>::Scalar_(const Scalar_<_Tp>& s) : Vec<_Tp, 4>(s) {
}

  可以看到,Scalar 是一个由长度为 4 的数组作为元素构成的结构体,Scalar 最多可以存储四个值,没有提供的值默认是 0

使用场景:

//下面的代码表示:
//创建一个2通道,且每个通道的值都为(1,2,3)深度为32,7行7列的图像矩阵。
//CV_32F表示每个元素的值的类型为32位浮点数,C2表示通道数为2,
//Scalar(1,2,3)表示对矩阵每个元素都赋值为(1,2,3),
//第一个通道中的值都是1,第二个通道中的值都是2,第三个通道中的值都是3,第四个通道中的值默认为0。

//a) 存放单通道图像中像素:cvScalar(255);
//b) 存放三通道图像中像素:cvScalar(255,255,255);

cv::Mat M(9,9,CV_32FC2,Scalar(1,2,3));

cv::imread 加载图像文件

//官方介绍
/*
函数 imread 从指定文件加载图像并返回它的图像矩阵 cv::Mat。
如果图像不能读取(由于文件丢失、权限不当、格式不支持或无效),函数返回一个空矩阵( Mat::data==NULL )。

目前,支持以下文件格式:

- Windows 位图 - \*.bmp, \*.dib(始终支持)
- JPEG 文件 - \*.jpeg、\*.jpg、\*.jpe(请参阅 *注意* 部分)
- JPEG 2000 文件 - \*.jp2(请参阅 *注意* 部分)
- 便携式网络图形 - \*.png(请参阅 *注意* 部分)
- WebP - \*.webp(见*注意*部分)
- 便携式图像格式 - \*.pbm、\*.pgm、\*.ppm \*.pxm、\*.pnm(始终支持)
- PFM 文件 - \*.pfm(请参阅 *Note* 部分)
- 太阳光栅 - \*.sr、\*.ras(始终支持)
- TIFF 文件 - \*.tiff, \*.tif(请参阅 *注意* 部分)
- OpenEXR 图像文件 - \*.exr(请参阅 *注意* 部分)
- Radiance HDR - \*.hdr, \*.pic(始终支持)
- GDAL 支持的栅格和矢量地理空间数据(请参阅 *注意* 部分)


参数介绍:
@param filename :要加载的文件名
@param flags = IMREAD_COLOR : 可以采用 cv::ImreadModes 值的标志
*/

//! Imread flags
enum ImreadModes {
IMREAD_UNCHANGED = -1, //!< 如果设置,则按原样返回加载的图像(使用 alpha 通道,否则将被裁剪)。忽略 EXIF 方向。
       IMREAD_GRAYSCALE = 0, //!< 如果设置,始终将图像转换为单通道灰度图像(编解码器内部转换)。
       IMREAD_COLOR = 1, //!< 如果设置,始终将图像转换为 3 通道 BGR 彩色图像。
       IMREAD_ANYDEPTH = 2, //!< 如果设置,当输入有对应深度时返回16位/32位图像,否则转换为8位。
       IMREAD_ANYCOLOR = 4, //!< 如果设置,则以任何可能的颜色格式读取图像。
       IMREAD_LOAD_GDAL = 8, //!< 如果设置,则使用 gdal 驱动程序加载图像。
       IMREAD_REDUCED_GRAYSCALE_2 = 16, //!< 如果设置,则始终将图像转换为单通道灰度图像,图像尺寸缩小 1/2。
       IMREAD_REDUCED_COLOR_2 = 17, //!< 如果设置,则始终将图像转换为 3 通道 BGR 彩色图像,并且图像尺寸减小 1/2。
       IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< 如果设置,则始终将图像转换为单通道灰度图像,图像尺寸缩小 1/4。
       IMREAD_REDUCED_COLOR_4 = 33, //!< 如果设置,则始终将图像转换为 3 通道 BGR 彩色图像,并且图像尺寸减小 1/4。
       IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< 如果设置,则始终将图像转换为单通道灰度图像,图像尺寸缩小 1/8。
       IMREAD_REDUCED_COLOR_8 = 65, //!< 如果设置,则始终将图像转换为 3 通道 BGR 彩色图像,并且图像尺寸减小 1/8。
       IMREAD_IGNORE_ORIENTATION = 128 //!< 如果设置,则不根据 EXIF 的方向标志旋转图像。
     };

CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR );

cv::imwrite 存储写入文件

/*
函数 imwrite 将图像保存到指定的文件中。图像格式选择基于文件扩展名(有关扩展名列表,请参阅 cv::imread)。
一般只有8位单通道或 3 通道(带有“BGR”通道顺序)图像可以使用此功能保存,但以下情况除外:

- 16 位无符号 (CV_16U) 图像可以保存为 PNG、JPEG 2000 和 TIFF 格式
- 32 位浮点 (CV_32F) 图像可以保存为 PFM、TIFF、OpenEXR 和 Radiance HDR 格式;将使用 LogLuv 高动态范围编码保存 3 通道 (CV_32FC3) TIFF 图像(每像素 4 个字节)
- 可以使用此功能保存带有 Alpha 通道的 PNG 图像。为此,请创建 8 位(或 16 位)4 通道图像 BGRA,其中 Alpha 通道在最后。全透明像素应该将 alpha 设置为 0,完全不透明的像素应该将 alpha 设置为 255/65535(请参阅下面的代码示例)。
- 可以以 TIFF 格式保存多个图像(Mat 的矢量)(请参阅下面的代码示例)。

如果不支持图像格式,图像将被转换为 8 位无符号 (CV_8U) 并以这种方式保存。

如果格式、深度或通道顺序不同,请使用
cv::Mat::convertTo 和 cv::cvtColor 在保存之前进行转换。或者,使用通用FileStorage I/O 函数将图像保存为 XML 或 YAML 格式。

@param filename 文件名。
@param img(cv::Mat 或 cv::Mat 向量)要保存的图像或图像。
@param params 格式特定的参数被编码成对 (paramId_1, paramValue_1, paramId_2, paramValue_2, ... .) 见 cv::ImwriteFlags
*/

//! Imwrite flags
enum ImwriteFlags {
       IMWRITE_JPEG_QUALITY = 1, //!< 对于JPEG,可以是0到100的质量(越高越好)。默认值为 95。
       IMWRITE_JPEG_PROGRESSIVE = 2, //!< 启用 JPEG 功能,0 或 1,默认为 False。
       IMWRITE_JPEG_OPTIMIZE = 3, //!< 启用 JPEG 功能,0 或 1,默认为 False。
       IMWRITE_JPEG_RST_INTERVAL = 4, //!< JPEG 重启间隔,0 - 65535,默认为 0 - 不重启。
       IMWRITE_JPEG_LUMA_QUALITY = 5, //!< 单独的亮度质量级别,0 - 100,默认为 0 - 不要使用。
       IMWRITE_JPEG_CHROMA_QUALITY = 6, //!< 单独的色度质量级别,0 - 100,默认为 0 - 不要使用。
       IMWRITE_PNG_COMPRESSION = 16, //!< 对于 PNG,可以是 0 到 9 的压缩级别。值越大,表示尺寸越小,压缩时间越长。如果指定,则策略更改为 IMWRITE_PNG_STRATEGY_DEFAULT (Z_DEFAULT_STRATEGY)。默认值为 1(最佳速度设置)。
       IMWRITE_PNG_STRATEGY = 17, //!< cv::ImwritePNGFlags 之一,默认为 IMWRITE_PNG_STRATEGY_RLE。
       IMWRITE_PNG_BILEVEL = 18, //!< 二进制级别 PNG,0 或 1,默认为 0。
       IMWRITE_PXM_BINARY = 32, //!< 对于 PPM、PGM 或 PBM,可以是二进制格式标志,0 或 1。默认值为 1。
       IMWRITE_EXR_TYPE = (3 << 4) + 0, /* 48 */ //!< 覆盖 EXR 存储类型(默认为 FLOAT (FP32))
       IMWRITE_EXR_COMPRESSION = (3 << 4) + 1, /* 49 */ //!< 覆盖 EXR 压缩类型(ZIP_COMPRESSION = 3 是默认值)
       IMWRITE_WEBP_QUALITY = 64, //!< 对于WEBP,可以是1到100的质量(越高越好)。默认情况下(没有任何参数)和质量高于 100 使用无损压缩。
       IMWRITE_PAM_TUPLETYPE = 128,//!< 对于 PAM,将 TUPLETYPE 字段设置为为格式定义的相应字符串值
       IMWRITE_TIFF_RESUNIT = 256,//!< 对于TIFF,用于指定设置哪个DPI分辨率单位;有关有效值,请参阅 libtiff 文档
       IMWRITE_TIFF_XDPI = 257,//!< 对于TIFF,用于指定X方向的DPI
       IMWRITE_TIFF_YDPI = 258, //!< 对于TIFF,用于指定Y方向的DPI
       IMWRITE_TIFF_COMPRESSION = 259, //!< 对于TIFF,用于指定图像压缩方案。有关与压缩格式对应的整数常量,请参阅 libtiff。注意,对于深度为 CV_32F 的图像,仅使用 libtiff 的 SGILOG 压缩方案。对于其他支持的深度,可以通过该标志指定压缩方案; LZW 压缩是默认的。
       IMWRITE_JPEG2000_COMPRESSION_X1000 = 272 //!< 对于JPEG2000,用于指定目标压缩率(乘以1000)。该值可以从 0 到 1000。默认值为 1000。
     };

CV_EXPORTS_W bool imwrite( const String& filename, InputArray img,
              const std::vector<int>& params = std::vector<int>());

cv:: imshow 显示图像文件

/*
函数 imshow 在指定窗口中显示图像。如果窗口是用cv::WINDOW_AUTOSIZE 标志,图像以其原始大小显示,但仍受屏幕分辨率的限制。
否则,将缩放图像以适合窗口。该函数可以缩放图像,具体取决于其深度:

- 如果图像是 8 位无符号,则按原样显示。
- 如果图像是 16 位无符号或 32 位整数,则像素除以 256。即值范围 [0,255\*256] 映射到 [0,255]。
- 如果图像是 32 位或 64 位浮点,则像素值乘以 255。即值范围 [0,1] 映射到 [0,255]。

如果窗口是使用 OpenGL 支持创建的,则 cv::imshow 还支持 ogl::Buffer 、 ogl::Texture2D 和cuda::GpuMat 作为输入。

如果该窗口不是在此函数之前创建的,则假定使用 cv::WINDOW_AUTOSIZE 创建一个窗口。

如果需要显示大于屏幕分辨率的图像,则需要在 imshow 之前调用 namedWindow("", WINDOW_NORMAL)。

@note 此函数后应调用 cv::waitKey 或 cv::pollKey 以执行 GUI 实际显示给定图像并使窗口响应所需的内务管理任务鼠标和键盘事件。
否则,它不会显示图像并且窗口可能会锁定。
例如,waitKey(0) 将无限显示窗口,直到任何按键(适合用于图像显示)。    
      waitKey(25) 将显示一帧并等待大约 25 毫秒的键
      按下(适合逐帧显示视频)。要移除窗口,请使用 cv::destroyWindow。

@param winname 窗口的名称。
@param mat 要显示的图像, 是一个 cv::Mat 对象。

*/


CV_EXPORTS_W void imshow(const String& winname, InputArray mat);

cv::waitKey 等待延时 / 按键事件

/*
函数 waitKey(n) 无限等待按键事件或延迟毫秒。

@按键事件:如果有按键按下,则返回对应按键的 ASCII 码值,如果等待的时间内没有按键操作,则返回 -1 。
@延时等待:延时等待 n ms, 阻塞型的。

@note 函数 #waitKey 和 #pollKey 是 HighGUI 中唯一可以获取和处理的方法 GUI  事件,因此需要定期调用其中之一以进行正常的事件处理,除非 HighGUI 在负责事件处理的环境中使用。

@note 该功能仅在创建了至少一个 HighGUI 窗口并且该窗口为积极的。如果有多个 HighGUI 窗口,它们中的任何一个都可以处于活动状态。

@param delay 以毫秒为单位的延迟。 0 是表示“永远”的特殊值。
*/
CV_EXPORTS_W int waitKey(int delay = 0);

cv::pollKey 按键事件

/** @brief 对按下的键进行轮询。

函数 #pollKey 无需等待即可轮询按键事件。 它返回按下的键的 ASCII 码值,如果自上次调用以来没有按下任何键,则为 -1。 

如果要等到某个键被按下,请使 #waitKey。

@note 函数 #waitKey 和 #pollKey 是 HighGUI 中唯一可以获取和处理的方法 GUI 事件,因此需要定期调用其中之一以进行正常的事件处理,除非 HighGUI 在负责事件处理的环境中使用。

@note 该功能仅在创建了至少一个 HighGUI 窗口并且该窗口为积极的。 如果有多个 HighGUI 窗口,它们中的任何一个都可以处于活动状态。
  */
CV_EXPORTS_W int pollKey();


cv::cvtColor 颜色空间转换

/*
将图像从一种颜色空间转换为另一种颜色空间。

该函数将输入图像从一种颜色空间转换为另一种颜色空间。转型的情况下to-from RGB 颜色空间,通道的顺序应该明确指定(RGB 或 BGR)。

笔记: 
OpenCV 中的默认颜色格式通常被称为 RGB ,但它实际上是 BGR(字节颠倒)。因此,标准(24 位)彩色图像中的第一个字节将是 8 位蓝色组件,第二个字节为绿色,第三个字节为红色。第四、第五和第六个字节将是第二个像素(蓝色,然后是绿色,然后是红色),依此类推。

R、G 和 B 通道值的常规范围是:
- CV_8U 图像为 0 到 255
- CV_16U 图像为 0 到 65535
- CV_32F 图像为 0 到 1

@param dst 输出与 src 大小和深度相同的图像。
@param code 颜色空间转换代码(参见#ColorConversionCodes)。
@param dstCn 目标图像中的通道数;如果参数为 0,则为通道是从 src 和代码自动派生的。
 */

//颜色空间转换码
enum ColorConversionCodes {
    COLOR_BGR2BGRA     = 0, //!< add alpha channel to RGB or BGR image
    COLOR_RGB2RGBA     = COLOR_BGR2BGRA,

    COLOR_BGRA2BGR     = 1, //!< remove alpha channel from RGB or BGR image
    COLOR_RGBA2RGB     = COLOR_BGRA2BGR,

    COLOR_BGR2RGBA     = 2, //!< convert between RGB and BGR color spaces (with or without alpha channel)
    COLOR_RGB2BGRA     = COLOR_BGR2RGBA,

    COLOR_RGBA2BGR     = 3,
    COLOR_BGRA2RGB     = COLOR_RGBA2BGR,

    COLOR_BGR2RGB      = 4,
    COLOR_RGB2BGR      = COLOR_BGR2RGB,

    COLOR_BGRA2RGBA    = 5,
    COLOR_RGBA2BGRA    = COLOR_BGRA2RGBA,

    COLOR_BGR2GRAY     = 6, //!< convert between RGB/BGR and grayscale, @ref color_convert_rgb_gray "color conversions"
    COLOR_RGB2GRAY     = 7,
    COLOR_GRAY2BGR     = 8,
    COLOR_GRAY2RGB     = COLOR_GRAY2BGR,
    COLOR_GRAY2BGRA    = 9,
    COLOR_GRAY2RGBA    = COLOR_GRAY2BGRA,
    COLOR_BGRA2GRAY    = 10,
    COLOR_RGBA2GRAY    = 11,

    COLOR_BGR2BGR565   = 12, //!< convert between RGB/BGR and BGR565 (16-bit images)
    COLOR_RGB2BGR565   = 13,
    COLOR_BGR5652BGR   = 14,
    COLOR_BGR5652RGB   = 15,
    COLOR_BGRA2BGR565  = 16,
    COLOR_RGBA2BGR565  = 17,
    COLOR_BGR5652BGRA  = 18,
    COLOR_BGR5652RGBA  = 19,

    COLOR_GRAY2BGR565  = 20, //!< convert between grayscale to BGR565 (16-bit images)
    COLOR_BGR5652GRAY  = 21,

    COLOR_BGR2BGR555   = 22,  //!< convert between RGB/BGR and BGR555 (16-bit images)
    COLOR_RGB2BGR555   = 23,
    COLOR_BGR5552BGR   = 24,
    COLOR_BGR5552RGB   = 25,
    COLOR_BGRA2BGR555  = 26,
    COLOR_RGBA2BGR555  = 27,
    COLOR_BGR5552BGRA  = 28,
    COLOR_BGR5552RGBA  = 29,

    COLOR_GRAY2BGR555  = 30, //!< convert between grayscale and BGR555 (16-bit images)
    COLOR_BGR5552GRAY  = 31,

    COLOR_BGR2XYZ      = 32, //!< convert RGB/BGR to CIE XYZ, @ref color_convert_rgb_xyz "color conversions"
    COLOR_RGB2XYZ      = 33,
    COLOR_XYZ2BGR      = 34,
    COLOR_XYZ2RGB      = 35,

    COLOR_BGR2YCrCb    = 36, //!< convert RGB/BGR to luma-chroma (aka YCC), @ref color_convert_rgb_ycrcb "color conversions"
    COLOR_RGB2YCrCb    = 37,
    COLOR_YCrCb2BGR    = 38,
    COLOR_YCrCb2RGB    = 39,

    COLOR_BGR2HSV      = 40, //!< convert RGB/BGR to HSV (hue saturation value) with H range 0..180 if 8 bit image, @ref color_convert_rgb_hsv "color conversions"
    COLOR_RGB2HSV      = 41,

    COLOR_BGR2Lab      = 44, //!< convert RGB/BGR to CIE Lab, @ref color_convert_rgb_lab "color conversions"
    COLOR_RGB2Lab      = 45,

    COLOR_BGR2Luv      = 50, //!< convert RGB/BGR to CIE Luv, @ref color_convert_rgb_luv "color conversions"
    COLOR_RGB2Luv      = 51,
    COLOR_BGR2HLS      = 52, //!< convert RGB/BGR to HLS (hue lightness saturation) with H range 0..180 if 8 bit image, @ref color_convert_rgb_hls "color conversions"
    COLOR_RGB2HLS      = 53,

    COLOR_HSV2BGR      = 54, //!< backward conversions HSV to RGB/BGR with H range 0..180 if 8 bit image
    COLOR_HSV2RGB      = 55,

    COLOR_Lab2BGR      = 56,
    COLOR_Lab2RGB      = 57,
    COLOR_Luv2BGR      = 58,
    COLOR_Luv2RGB      = 59,
    COLOR_HLS2BGR      = 60, //!< backward conversions HLS to RGB/BGR with H range 0..180 if 8 bit image
    COLOR_HLS2RGB      = 61,

    COLOR_BGR2HSV_FULL = 66, //!< convert RGB/BGR to HSV (hue saturation value) with H range 0..255 if 8 bit image, @ref color_convert_rgb_hsv "color conversions"
    COLOR_RGB2HSV_FULL = 67,
    COLOR_BGR2HLS_FULL = 68, //!< convert RGB/BGR to HLS (hue lightness saturation) with H range 0..255 if 8 bit image, @ref color_convert_rgb_hls "color conversions"
    COLOR_RGB2HLS_FULL = 69,

    COLOR_HSV2BGR_FULL = 70, //!< backward conversions HSV to RGB/BGR with H range 0..255 if 8 bit image
    COLOR_HSV2RGB_FULL = 71,
    COLOR_HLS2BGR_FULL = 72, //!< backward conversions HLS to RGB/BGR with H range 0..255 if 8 bit image
    COLOR_HLS2RGB_FULL = 73,

    COLOR_LBGR2Lab     = 74,
    COLOR_LRGB2Lab     = 75,
    COLOR_LBGR2Luv     = 76,
    COLOR_LRGB2Luv     = 77,

    COLOR_Lab2LBGR     = 78,
    COLOR_Lab2LRGB     = 79,
    COLOR_Luv2LBGR     = 80,
    COLOR_Luv2LRGB     = 81,

    COLOR_BGR2YUV      = 82, //!< convert between RGB/BGR and YUV
    COLOR_RGB2YUV      = 83,
    COLOR_YUV2BGR      = 84,
    COLOR_YUV2RGB      = 85,

    //! YUV 4:2:0 family to RGB
    COLOR_YUV2RGB_NV12  = 90,
    COLOR_YUV2BGR_NV12  = 91,
    COLOR_YUV2RGB_NV21  = 92,
    COLOR_YUV2BGR_NV21  = 93,
    COLOR_YUV420sp2RGB  = COLOR_YUV2RGB_NV21,
    COLOR_YUV420sp2BGR  = COLOR_YUV2BGR_NV21,

    COLOR_YUV2RGBA_NV12 = 94,
    COLOR_YUV2BGRA_NV12 = 95,
    COLOR_YUV2RGBA_NV21 = 96,
    COLOR_YUV2BGRA_NV21 = 97,
    COLOR_YUV420sp2RGBA = COLOR_YUV2RGBA_NV21,
    COLOR_YUV420sp2BGRA = COLOR_YUV2BGRA_NV21,

    COLOR_YUV2RGB_YV12  = 98,
    COLOR_YUV2BGR_YV12  = 99,
    COLOR_YUV2RGB_IYUV  = 100,
    COLOR_YUV2BGR_IYUV  = 101,
    COLOR_YUV2RGB_I420  = COLOR_YUV2RGB_IYUV,
    COLOR_YUV2BGR_I420  = COLOR_YUV2BGR_IYUV,
    COLOR_YUV420p2RGB   = COLOR_YUV2RGB_YV12,
    COLOR_YUV420p2BGR   = COLOR_YUV2BGR_YV12,

    COLOR_YUV2RGBA_YV12 = 102,
    COLOR_YUV2BGRA_YV12 = 103,
    COLOR_YUV2RGBA_IYUV = 104,
    COLOR_YUV2BGRA_IYUV = 105,
    COLOR_YUV2RGBA_I420 = COLOR_YUV2RGBA_IYUV,
    COLOR_YUV2BGRA_I420 = COLOR_YUV2BGRA_IYUV,
    COLOR_YUV420p2RGBA  = COLOR_YUV2RGBA_YV12,
    COLOR_YUV420p2BGRA  = COLOR_YUV2BGRA_YV12,

    COLOR_YUV2GRAY_420  = 106,
    COLOR_YUV2GRAY_NV21 = COLOR_YUV2GRAY_420,
    COLOR_YUV2GRAY_NV12 = COLOR_YUV2GRAY_420,
    COLOR_YUV2GRAY_YV12 = COLOR_YUV2GRAY_420,
    COLOR_YUV2GRAY_IYUV = COLOR_YUV2GRAY_420,
    COLOR_YUV2GRAY_I420 = COLOR_YUV2GRAY_420,
    COLOR_YUV420sp2GRAY = COLOR_YUV2GRAY_420,
    COLOR_YUV420p2GRAY  = COLOR_YUV2GRAY_420,

    //! YUV 4:2:2 family to RGB
    COLOR_YUV2RGB_UYVY = 107,
    COLOR_YUV2BGR_UYVY = 108,
    //COLOR_YUV2RGB_VYUY = 109,
    //COLOR_YUV2BGR_VYUY = 110,
    COLOR_YUV2RGB_Y422 = COLOR_YUV2RGB_UYVY,
    COLOR_YUV2BGR_Y422 = COLOR_YUV2BGR_UYVY,
    COLOR_YUV2RGB_UYNV = COLOR_YUV2RGB_UYVY,
    COLOR_YUV2BGR_UYNV = COLOR_YUV2BGR_UYVY,

    COLOR_YUV2RGBA_UYVY = 111,
    COLOR_YUV2BGRA_UYVY = 112,
    //COLOR_YUV2RGBA_VYUY = 113,
    //COLOR_YUV2BGRA_VYUY = 114,
    COLOR_YUV2RGBA_Y422 = COLOR_YUV2RGBA_UYVY,
    COLOR_YUV2BGRA_Y422 = COLOR_YUV2BGRA_UYVY,
    COLOR_YUV2RGBA_UYNV = COLOR_YUV2RGBA_UYVY,
    COLOR_YUV2BGRA_UYNV = COLOR_YUV2BGRA_UYVY,

    COLOR_YUV2RGB_YUY2 = 115,
    COLOR_YUV2BGR_YUY2 = 116,
    COLOR_YUV2RGB_YVYU = 117,
    COLOR_YUV2BGR_YVYU = 118,
    COLOR_YUV2RGB_YUYV = COLOR_YUV2RGB_YUY2,
    COLOR_YUV2BGR_YUYV = COLOR_YUV2BGR_YUY2,
    COLOR_YUV2RGB_YUNV = COLOR_YUV2RGB_YUY2,
    COLOR_YUV2BGR_YUNV = COLOR_YUV2BGR_YUY2,

    COLOR_YUV2RGBA_YUY2 = 119,
    COLOR_YUV2BGRA_YUY2 = 120,
    COLOR_YUV2RGBA_YVYU = 121,
    COLOR_YUV2BGRA_YVYU = 122,
    COLOR_YUV2RGBA_YUYV = COLOR_YUV2RGBA_YUY2,
    COLOR_YUV2BGRA_YUYV = COLOR_YUV2BGRA_YUY2,
    COLOR_YUV2RGBA_YUNV = COLOR_YUV2RGBA_YUY2,
    COLOR_YUV2BGRA_YUNV = COLOR_YUV2BGRA_YUY2,

    COLOR_YUV2GRAY_UYVY = 123,
    COLOR_YUV2GRAY_YUY2 = 124,
    //CV_YUV2GRAY_VYUY    = CV_YUV2GRAY_UYVY,
    COLOR_YUV2GRAY_Y422 = COLOR_YUV2GRAY_UYVY,
    COLOR_YUV2GRAY_UYNV = COLOR_YUV2GRAY_UYVY,
    COLOR_YUV2GRAY_YVYU = COLOR_YUV2GRAY_YUY2,
    COLOR_YUV2GRAY_YUYV = COLOR_YUV2GRAY_YUY2,
    COLOR_YUV2GRAY_YUNV = COLOR_YUV2GRAY_YUY2,

    //! alpha premultiplication
    COLOR_RGBA2mRGBA    = 125,
    COLOR_mRGBA2RGBA    = 126,

    //! RGB to YUV 4:2:0 family
    COLOR_RGB2YUV_I420  = 127,
    COLOR_BGR2YUV_I420  = 128,
    COLOR_RGB2YUV_IYUV  = COLOR_RGB2YUV_I420,
    COLOR_BGR2YUV_IYUV  = COLOR_BGR2YUV_I420,

    COLOR_RGBA2YUV_I420 = 129,
    COLOR_BGRA2YUV_I420 = 130,
    COLOR_RGBA2YUV_IYUV = COLOR_RGBA2YUV_I420,
    COLOR_BGRA2YUV_IYUV = COLOR_BGRA2YUV_I420,
    COLOR_RGB2YUV_YV12  = 131,
    COLOR_BGR2YUV_YV12  = 132,
    COLOR_RGBA2YUV_YV12 = 133,
    COLOR_BGRA2YUV_YV12 = 134,

    //! Demosaicing
    COLOR_BayerBG2BGR = 46,
    COLOR_BayerGB2BGR = 47,
    COLOR_BayerRG2BGR = 48,
    COLOR_BayerGR2BGR = 49,

    COLOR_BayerBG2RGB = COLOR_BayerRG2BGR,
    COLOR_BayerGB2RGB = COLOR_BayerGR2BGR,
    COLOR_BayerRG2RGB = COLOR_BayerBG2BGR,
    COLOR_BayerGR2RGB = COLOR_BayerGB2BGR,

    COLOR_BayerBG2GRAY = 86,
    COLOR_BayerGB2GRAY = 87,
    COLOR_BayerRG2GRAY = 88,
    COLOR_BayerGR2GRAY = 89,

    //! Demosaicing using Variable Number of Gradients
    COLOR_BayerBG2BGR_VNG = 62,
    COLOR_BayerGB2BGR_VNG = 63,
    COLOR_BayerRG2BGR_VNG = 64,
    COLOR_BayerGR2BGR_VNG = 65,

    COLOR_BayerBG2RGB_VNG = COLOR_BayerRG2BGR_VNG,
    COLOR_BayerGB2RGB_VNG = COLOR_BayerGR2BGR_VNG,
    COLOR_BayerRG2RGB_VNG = COLOR_BayerBG2BGR_VNG,
    COLOR_BayerGR2RGB_VNG = COLOR_BayerGB2BGR_VNG,

    //! Edge-Aware Demosaicing
    COLOR_BayerBG2BGR_EA  = 135,
    COLOR_BayerGB2BGR_EA  = 136,
    COLOR_BayerRG2BGR_EA  = 137,
    COLOR_BayerGR2BGR_EA  = 138,

    COLOR_BayerBG2RGB_EA  = COLOR_BayerRG2BGR_EA,
    COLOR_BayerGB2RGB_EA  = COLOR_BayerGR2BGR_EA,
    COLOR_BayerRG2RGB_EA  = COLOR_BayerBG2BGR_EA,
    COLOR_BayerGR2RGB_EA  = COLOR_BayerGB2BGR_EA,

    //! Demosaicing with alpha channel
    COLOR_BayerBG2BGRA = 139,
    COLOR_BayerGB2BGRA = 140,
    COLOR_BayerRG2BGRA = 141,
    COLOR_BayerGR2BGRA = 142,

    COLOR_BayerBG2RGBA = COLOR_BayerRG2BGRA,
    COLOR_BayerGB2RGBA = COLOR_BayerGR2BGRA,
    COLOR_BayerRG2RGBA = COLOR_BayerBG2BGRA,
    COLOR_BayerGR2RGBA = COLOR_BayerGB2BGRA,

    COLOR_COLORCVT_MAX  = 143
};

CV_EXPORTS_W void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );

eg:
cv::cvtColor(src_img, src_bgr, CV_YUV2RGB_NV12);

cv::resize 重置图片大小

函数原型如下:

void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR );

先解释一下各个参数的意思:

  • src:输入,原图像,即待改变大小的图像;

  • dst:输出,改变大小以后的图像,这个图像和原图像具备相同的内容,只是大小和原图像不同而已;

  • dsize:输出图像的大小。若是这个参数不为0,那么就表明将原图像缩放到这个Size(width,height)指定的大小;若是这个参数为0,那么原图像缩放以后的大小就要经过下面的公式来计算:dsize = Size(round(fxsrc.cols), round(fysrc.rows)) 原型;

  • fx:width方向的缩放比例,若是它是0,那么它就会按照(double)dsize.width/src.cols来计算;

  • fy:height方向的缩放比例,若是它是0,那么它就会按照(double)dsize.height/src.rows来计算;

  • interpolation:这个是指定插值的方式,图像缩放以后,确定像素要进行从新计算的,就靠这个参数来指定从新计算像素的方式,有如下几种:

      INTER_NEAREST - 最邻近插值
      INTER_LINEAR - 双线性插值,若是最后一个参数你不指定,默认使用这种方法
      INTER_AREA - resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.
      INTER_CUBIC - 4x4像素邻域内的双立方插值
      INTER_LANCZOS4 - 8x8像素邻域内的Lanczos插值
    

使用注意事项:

  1. dsize和fx/fy不能同时为0,要么你就指定好dsize的值,让fx和fy空置直接使用默认值,就像
    resize(img, imgDst, Size(30,30));要么你就让dsize为0,指定好fx和fy的值,好比fx=fy=0.5,那么就至关于把原图两个方向缩小一倍!

  2. 至于最后的插值方法,正常状况下使用默认的双线性插值就够用了。几种经常使用方法的效率是:最邻近插值>双线性插值>双立方插值>Lanczos插值;可是效率和效果成反比,因此根据本身的状况酌情使用。

  3. 正常状况下,在使用以前dst图像的大小和类型都是不知道的,类型从src图像继承而来,大小也是从原图像根据参数计算出来。可是若是你事先已经指定好dst图像的大小,那么你能够经过下面这种方式来调用函数:

cv::Mat mat;  
// mat 中已经有了图片数据(赋值)
cv::resize(mat, mat, cv::Size(608, 912));   // 重置图片尺寸

开发案例

获取 cv::mat 中的数据

// cv::Mat src_img 假如已经赋值 
std::array<std::uint8_t, 300000000> data;  // or --> std::uint8_t data[300000000];
memset(data, '\0', 300000000);
memcpy((void *)data.data(), src_img.data, src_img.cols * src_img.rows);  // memcpy((void *)data, ...)

视频输出图片

  // 图片数据格式
  struct Image {
    /// @brief Raw image data
    std::array<std::uint8_t, 300000000> data;
    /// @brief Width
    std::uint16_t width;
    /// @brief Height
    std::uint16_t height;
    /// @brief Element size
    std::uint8_t element_size;
    /// @brief Image pointer (for direct lvds access)
    void* data_ptr;
    /// @brief Data size (for compressed image)
    std::uint32_t data_size;
  };

  std::string filename{std::to_string(raw_data_ptr_->GetTimestamp()) + ".jpg"};   //数据图片文件名
  CameraData::Image& image{raw_data_ptr_->GetMutableImage()};  //获取图片数据
  cv::Mat mat{static_cast<std::int32_t>(image.height), static_cast<std::int32_t>(image.width), CV_8UC3, image.data.data()};
  cv::imwrite(filename, mat);  //输出图片

实时预览视频

  // 图片数据格式
  struct Image {
    /// @brief Raw image data
    std::array<std::uint8_t, 300000000> data;
    /// @brief Width
    std::uint16_t width;
    /// @brief Height
    std::uint16_t height;
    /// @brief Element size
    std::uint8_t element_size;
    /// @brief Image pointer (for direct lvds access)
    void* data_ptr;
    /// @brief Data size (for compressed image)
    std::uint32_t data_size;
  };

  CameraData::Image& image{raw_data_ptr_->GetMutableImage()};  //获取图片数据
  cv::Mat mat{static_cast<std::int32_t>(image.height), static_cast<std::int32_t>(image.width), CV_8UC3, image.data.data()};

  cv::cvtColor(mat, mat, cv::COLOR_RGB2BGR);  //转换画面颜色 RGB to BGR,根据实际情况转化
  cv::namedWindow("video", 0);  //定义一个窗口
  cv::resizeWindow("video", static_cast<std::int32_t>(image.height)/2, static_cast<std::int32_t>(image.width)/2); //重定义窗口尺寸
  cv::imshow("video", mat); //预览视频
  cv::waitKey(1);

加载资源

// 加载 jpg
cv::Mat mat = cv::imread("/home/aliven/Picture/001.jpg");

调用电脑摄像头

 更新中....
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值