OpenCV-C++ 图像掩模计算

利用一个掩模处理图像;

0 	-1 	0
-1 	 5 	-1
0 	-1 	0

理解Mat矩阵存储格式

使用opencv读入一张图片,得到是一个表示BGR三个通道的矩阵,那么在内存空间中是怎么存储的呢?

如下图所示,Row 0, Row 1,..., Row n 表示图像的每一行,与图像高度相关;

Column 0, Column 1,..., Column m 表示图像的每一列, 与图像宽度相关;

但是实际在存储的时候,是先连续存储每一个像素的B, G, R三个值,在存储下一个像素;

同时,由于是一个多维数组,必定有一个头指针,指向第一行;对指针加1,用来放来第二行;

这样获取到每一行的指针后,再访问其第几列;

img

C++实现

#include <iostream>
#include <opencv2/opencv.hpp>
#include <math.h>

using namespace std;
using namespace cv;

int main(){
    // 读入图片
    Mat img = imread("/home/chen/dataset/lena.jpg");

    // 显示图片
    namedWindow("lena", WINDOW_AUTOSIZE);
    imshow("lean", img);
    waitKey(0);

    // 执行掩模计算
    int cols = img.cols * img.channels();  // 获取每一行所代表的一维数组有多少元素
    int offset = img.channels();
    int rows = img.rows;

    Mat dst = Mat::zeros(img.size(), img.type());  // 掩模计算后的输出图像
    for (int row = 1; row < (rows - 1); row++){
        const uchar* previous = img.ptr<uchar>(row - 1);  // 获取上一行的指针, 是一个指向常量的指针,不能修改指向对象的值
        const uchar* current = img.ptr<uchar>(row);  // 获取当前行的指针
        const uchar* next = img.ptr<uchar>(row + 1);  // 获取下一行的指针

        uchar* output = dst.ptr<uchar>(row);  // 获取目标图像当前行的指针
        for (int col = offset; col < (cols - 1); col++){
            // 核心掩模计算 
            output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offset] + current[col+offset] + previous[col] + next[col]));
        }
    }

    namedWindow("img after mask.
", WINDOW_AUTOSIZE);
    imshow("img after mask", dst);
    waitKey(0);


    return 0;
}

需要注意的是,从img.ptr<uchar>(0)获取的是第0行的指针; uchar代表的元素类型

API调用

#include <iostream>
#include <opencv2/opencv.hpp>
#include <math.h>

using namespace std;
using namespace cv;

int main(){
    // 读入图片
    Mat img = imread("/home/chen/dataset/lena.jpg");

    // 显示图片
    namedWindow("lena", WINDOW_AUTOSIZE);
    imshow("lean", img);
    printf("col: %d, rows: %d, channels: %d, depth: %d
", img.cols, img.rows, img.channels(), img.depth());
    printf("dims: %d, type: %d
" , img.dims, img.type());
    waitKey(0);

    // 利用API执行掩模计算
    Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

    Mat dst2;
    filter2D(img, dst2, img.depth(), kernel);  // 使用API执行掩模计算

    namedWindow("img after mask-api", WINDOW_AUTOSIZE);
    imshow("img after mask-api", dst2);
    waitKey(0);

    return 0;
}
原文地址:https://www.cnblogs.com/chenzhen0530/p/14616087.html