聊一聊OpenCV的saturate_cast防溢出

saturate_cast函数在OpenCV中的作用是防数据溢出,我们在直接操作像素点的时候,如果数值结果是赋值或者超过了255的话,在图片中是没办法显示的,这就是防数据溢出的作用,那么什么时候会有数据溢出的风险呢,这种情况在图像卷积操作的时候比较常见。 下面我们举个栗子吧: 选择一个3*3的锐化作用的卷积核,设计如下: (0, -1, 0, -1, 5, -1, 0, -1, 0) 分别使用OpenCV的filter2D函数和自己写的Convlution函数实现对一张图片的卷积:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>

using namespace  std;
using namespace  cv;

Mat Kernel_test_3_3 = (Mat_<double>(3,3) << 
    0,-1,0,
    -1,5,-1,
    0,-1,0);
void Convlution(Mat  InputImage,Mat  OutputImage,Mat kernel)
{
    //计算卷积核的半径
    int sub_x = kernel.cols/2;
    int sub_y = kernel.rows/2;
    //遍历图片  
    for (int image_y=0;image_y<InputImage.rows-2*sub_y;image_y++)
    {
        for(int image_x=0;image_x<InputImage.cols-2*sub_x;image_x++)
        {
            int pix_value = 0;
            for (int kernel_y = 0;kernel_y<kernel.rows;kernel_y++)
            {
                for(int kernel_x = 0;kernel_x<kernel.cols;kernel_x++)
                {
                    double  weihgt = kernel.at<double>(kernel_y,kernel_x)   ;
                    int value =  (int)InputImage.at<uchar>(image_y+kernel_y,image_x+kernel_x); 
                    pix_value +=weihgt*value;
                }
            }
            OutputImage.at<uchar>(image_y+sub_y,image_x+sub_x) = (uchar)pix_value;
            //OutputImage.at<uchar>(image_y+sub_y,image_x+sub_x) = saturate_cast<uchar>((int)pix_value);
            if ((int)pix_value!=(int)saturate_cast<uchar>((int)pix_value))
            {
                //cout<<"没有防溢出"<<(int)pix_value<<endl;
                //cout<<"防溢出"<<(int)saturate_cast<uchar>((int)pix_value)<<endl;
                //cout<<"没有防溢出写入了什么?"<<(int)OutputImage.at<uchar>(image_y+sub_y,image_x+sub_x)<<endl;
                //cout<<endl;
            }
        }
    }
}


int main()
{
    Mat srcImage = imread("1.jpg",0);
    namedWindow("srcImage", WINDOW_AUTOSIZE);
    imshow("原图", srcImage);

    //filter2D卷积
    Mat dstImage_oprncv(srcImage.rows,srcImage.cols,CV_8UC1,Scalar(0));;
    filter2D(srcImage,dstImage_oprncv,srcImage.depth(),Kernel_test_3_3);
    imshow("filter2D卷积图",dstImage_oprncv);
    imwrite("1.jpg",dstImage_oprncv);

    //自定义卷积
    Mat dstImage_mycov(srcImage.rows,srcImage.cols,CV_8UC1,Scalar(0));
    Convlution(srcImage,dstImage_mycov,Kernel_test_3_3);
    imshow("卷积图3",dstImage_mycov);
    imwrite("2.jpg",dstImage_mycov);

    waitKey(0);
    return 0;

}

在不使用防溢出的情况下效果如下:

原图:

对原图的灰度图使用filter2D:

对原图的灰度图使用Convlution:

然后我们加入防溢出,再看下效果:

对原图的灰度图使用Convlution:

发现和filter2D函数的效果已经没什么区别了,由于函数设计没有考虑边界填充的情况,所以四周是由黑边的,但是这不是本篇内容的重点,暂时忽略它吧,那么为什么加入了防溢出效果就差了这么多么,大家注意到,在上面的程序中,我们注释了几行代码,如果把它解开的话,就可以看到打印的效果了:

没有防溢出-30 防溢出0 没有防溢出写入了什么?226

没有防溢出257 防溢出255 没有防溢出写入了什么?1

我们拿出两条打印结果来看一下,当计算的像素值超过了255,那么防溢出之后会变成255,如果计算的像素值超过了小于0,那么防溢出之后会变成0,而如果没有加防溢出,直接向图片里面写入的话会写进入什么值呢?

-30变成了226 257变成1

可以看到,OpenCV为了让图片可以正常的显示,会把一个负值加上256,把一个超过256的正值减下去256,这样就会出现上面那种奇怪的结果了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

算法基础:最大递减数问题(Golang实现)

给出一个非负整数,找到这个非负整数中包括的最大递减数。一个数字的递减数是指相邻的数位从大到小排列的数字。 如: 95345323,递减数有:953,95,53,...

3405
来自专栏程序员的知识天地

Python实现随机生成验证码?小菜一碟!

Python随机生成验证码的方法有很多,今天给大家列举两种,大家也可以在这个基础上进行改造,设计出适合自己的验证码方法

1152
来自专栏landv

c语言_头文件

1653
来自专栏数据结构与算法

洛谷P3807 【模板】卢卡斯定理exgcd

题目背景 这是一道模板题。 题目描述 给定n 求  保证P为prime C表示组合数。 一个测试点内包含多组数据。 输入输出格式 输入格式: 第一行...

3236
来自专栏用户2442861的专栏

OpenCV学习笔记:MAT解析

但手动地做还是可以的:大多数OpenCV函数仍会手动地为输出数据开辟空间。当传递一个已经存在的 Mat 对象时,开辟好的矩阵空间会被重用。也就是说,我们每次...

581
来自专栏V站

PHP把二维数组中的值取出组合整一维数组

小伙伴们,之前我们在开发过程中肯定遇到需要把二维数组转换为一维数组的时候,基本上都运用了foreach循环遍历赋值给新数组. 今天这里介绍一个新的方法,通过两个...

1592
来自专栏数据结构与算法

P2280 [HNOI2003]激光炸弹

题目描述 ? 输入输出格式 输入格式: 输入文件名为input.txt 输入文件的第一行为正整数n和正整数R,接下来的n行每行有3个正整数,分别表示 输...

3075
来自专栏菩提树下的杨过

“AS3.0高级动画编程”学习:第四章 寻路(AStar/A星/A*)算法 (中)

上一部分提到了节点(Node),代价(Cost),估价公式等基本概念,有了这些知识铺垫 就可以正式开启寻路之旅了! ? 如上图,这是一个5行8列的网格,黄色节点...

2346
来自专栏有趣的Python

11-玩转数据结构-并查集

前面我们接触的树结构都是由父亲指向孩子,但是我们的并查集却是由孩子指向父亲。这种奇怪的树结构可以非常高效的回答一类问题: 连接问题 Connectivity P...

1452
来自专栏二进制文集

LeetCode 动态规划 题目分类汇总

A robot is located at the top-left corner of a m x n grid (marked 'Start' in the...

2576

扫码关注云+社区