zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    WPF Image控件的Source属性是一个ImageSource对象
    wx:if 与hidden
    切换远程分支
    异步请求(简单一说)
    多维数组降维方法,简单一提
    3.25发版之最后的搜索框
    wepy-城市按字母排序
    new一个新对象。。。对象???
    参数函数是对象的理解
    群辉 MariaDB 10 远程连接
  • 原文地址:https://www.cnblogs.com/chenzhen0530/p/14616087.html
Copyright © 2011-2022 走看看