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,这样就会出现上面那种奇怪的结果了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值