OpenCV学习(三):矩阵的掩模的操作

上一篇介绍了OpenCV中imread,cvtColor,imshow,imwrite的使用,这一篇打算介绍Mat的像素指针,以及掩模操作。

像素指针

对图像操作,基本都是对图像的每个像素操作,在OpenCV中Mat.ptr<uchar>(int i=0)可以获取像素的指针,i表示第i行,从第0列开始操作。

这样获取当前行的像素指针const uchar* current = myImage.ptr<uchar>( row ),那么获取像素点P(row, col)的像素值p(row, col) = current[col]

eg:

Mat inMat = imread("1.png");
uchar u = inMat.ptr<uchar>(0)[0];

上面先载入一张图片到inMat中,然后从inMat中获取第1行第1列的像素并赋给uchar类型的u。


掩模操作

知道了获取图像的像素方法,接下来就可以对图像进行掩模操作,从而提高图片的对比度。

这里写图片描述

接下来就根据上面图片的公式,来实现图片像素的操作。

    Mat inMat = imread("1.png");
    if (!inMat.data) {  //判断图像是否读取成功
        cout << "图像读取失败" << endl;
        return;
    }

    imshow("原图像", inMat);

    int channel = inMat.channels(); //获取图像的通道数
    int row = inMat.rows;
    int col = inMat.cols;
    Mat outMat = Mat(inMat.size(), inMat.type());
    for (int i = 1; i < row-1; i++) {
        for (int j = channel; j < (col-1)*channel; j++) {
            outMat.ptr<uchar>(i)[j] = 5 * inMat.ptr<uchar>(i)[j]-
                                                                (inMat.ptr<uchar>(i - 1)[j] + 
                                                                 inMat.ptr<uchar>(i + 1)[j] +
                                                                 inMat.ptr<uchar>(i)[j-channel] + 
                                                                 inMat.ptr<uchar>(i)[j+channel]);
        }
    }
    imshow("掩模之后的图像", outMat);
}

注意:
< 1 >我们在显示图片的时候,可以不用调用namedwindow来创建窗口,可以直接调用imshow,来创建并显示窗口图像。
< 2 >像素计算操作时,不能直接从原点(0, 0)到最大点(col, row)来计算计算像素值,否则计算就会超过范围 。
< 3 >在对列进行操作时,别忘了图像的通道值。


运行结果

这里写图片描述

可以看见掩模之后的图片失真很严重,这是因为我们像素计算之后的值可能为负数或者超过了范围。

此时我们可以用到一个函数saturate_cast< uchar >,当计算的值为负数,或者很大时,可以使我们计算的像素值保证在0~255之间。

更改之后的代码如下

outMat.ptr<uchar>(i)[j] = saturate_cast<uchar>(5 * inMat.ptr<uchar>(i)[j]-
                                                                (inMat.ptr<uchar>(i - 1)[j] + 
                                                                 inMat.ptr<uchar>(i + 1)[j] +
                                                                 inMat.ptr<uchar>(i)[j-channel] + 
                                                                 inMat.ptr<uchar>(i)[j+channel]));

此时运行的结果如下:

这里写图片描述

可以看见结果好多了


filter2D

对于上面的代码显然是最原始的像素计算方式,此时我们可以使用filter2D达到最简洁的像素计算方式。

< 1 >定义掩模

Mat kernel = (Mat_< char >(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

< 2 >调用filter2D

filter2D(inMat, outMat, inMat.depth(), kernel);

(1)参数一:输入的图像
(2)参数二:输出的图像
(3)参数三:输出的图像深度,一般和输入图像的深度一样,也可以直接填-1,和前面一样


此时附上完整代码

void test4(){
    Mat inMat = imread("1.png");
    if (!inMat.data) {  //判断图像是否读取成功
        cout << "图像读取失败" << endl;
        return;
    }

    imshow("原图像", inMat);

    int channel = inMat.channels(); //获取图像的通道数
    int row = inMat.rows;
    int col = inMat.cols;
    Mat outMat = Mat(inMat.size(), inMat.type());
    for (int i = 1; i < row-1; i++) {
        for (int j = channel; j < (col-1)*channel; j++) {
            outMat.ptr<uchar>(i)[j] = saturate_cast<uchar>(5 * inMat.ptr<uchar>(i)[j]-
                                                                (inMat.ptr<uchar>(i - 1)[j] + 
                                                                 inMat.ptr<uchar>(i + 1)[j] +
                                                                 inMat.ptr<uchar>(i)[j-channel] + 
                                                                 inMat.ptr<uchar>(i)[j+channel]));
        }
    }
    imshow("掩模之后的图像", outMat);

    Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    filter2D(inMat, outMat, inMat.depth(), kernel);
    imshow("filter2D变化之后的图像", outMat);
}

运行结果:

这里写图片描述

可以看见,filter2D和前面的计算结果显示的样子基本一样。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值