聊一聊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 条评论
登录 后参与评论

相关文章

来自专栏数据结构与算法

P1823 音乐会的等待

题目描述 N个人正在排队进入一个音乐会。人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人。队列中任意两个人A和B,如果他们是相邻或他们之间没有人比...

35213
来自专栏小詹同学

Leetcode打卡 | No.012 整数转罗马数字

欢迎和小詹一起定期刷leetcode,每周一和周五更新一题,每一题都吃透,欢迎一题多解,寻找最优解!这个记录帖哪怕只有一个读者,小詹也会坚持刷下去的!

971
来自专栏塔奇克马敲代码

RTKLIB源码解析(一)——单点定位(pntpos.c)

4264
来自专栏数据之美

相似文档查找算法之 simHash 简介及其 java 实现

传统的 hash 算法只负责将原始内容尽量均匀随机地映射为一个签名值,原理上相当于伪随机数产生算法。产生的两个签名,如果相等,说明原始内容在一定概 率 下是相...

31110
来自专栏琦小虾的Binary

Opencv中数据结构Mat的相关属性

Opencv中数据结构Mat的相关属性 前言: The class Mat represents an n-dimensional dense numeric...

2057
来自专栏C/C++基础

定点数的加减法

数值运算的核心是指加、减、乘、除四则算术。由于计算机中的数有定点和浮点两种表示形式,因此相应有定点数的运算和浮点数的运算。本文将介绍计算机中定点数的加减法运算过...

1144
来自专栏数据科学学习手札

(数据科学学习手札03)Python与R在随机数生成上的异同

随机数的使用是很多算法的关键步骤,例如蒙特卡洛法、遗传算法中的轮盘赌法的过程,因此对于任意一种语言,掌握其各类型随机数生成的方法至关重要,Python与R在随机...

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

拉格朗日插值

存在性和唯一性的证明以后再补。。。。 拉格朗日插值 拉格朗日插值,emmmm,名字挺高端的:joy: 它有什么应用呢? 我们在FFT中讲到过 设n-1次多项式为...

2597
来自专栏james大数据架构

简单的jquery拖曵原理js特效实例

<!DOCTYPE html> <html> <title>简单拖曵原理实例</title> <script language="javascript" src...

1877
来自专栏CreateAMind

浅析互信息与特征选择

那么什么是互信息呢?变量x与变量y之间的互信息,可以用来衡量已知变量x时变量y的不确定性减少的程度,同样的,也可以衡量已知变量y时变量x的不确定性减少的程度。

722

扫码关注云+社区