聊一聊OpenCV的saturate_cast防溢出
2017-10-18 20:30
330 查看
saturate_cast函数在OpenCV中的作用是防数据溢出,我们在直接操作像素点的时候,如果数值结果是赋值或者超过了255的话,在图片中是没办法显示的,这就是防数据溢出的作用,那么什么时候会有数据溢出的风险呢,这种情况在图像卷积操作的时候比较常见。
下面我们举个栗子吧:
选择一个3*3的锐化作用的卷积核,设计如下:
(0, -1, 0,
-1, 5, -1,
0, -1, 0)
分别使用OpenCV的filter2D函数和自己写的Convlution函数实现对一张图片的卷积:
在不使用防溢出的情况下效果如下:
原图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/e772701d65d11b7c450bf63195d9c0b5)
对原图的灰度图使用filter2D:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/17fc8831b54bdd281b508d9d95ae2719)
对原图的灰度图使用Convlution:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/e6557bec528885efed561c24c7099acb)
然后我们加入防溢出,再看下效果:
对原图的灰度图使用Convlution:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/b5f0b2733df41450b67e28c968c2ab45)
发现和filter2D函数的效果已经没什么区别了,由于函数设计没有考虑边界填充的情况,所以四周是由黑边的,但是这不是本篇内容的重点,暂时忽略它吧,那么为什么加入了防溢出效果就差了这么多么,大家注意到,在上面的程序中,我们注释了几行代码,如果把它解开的话,就可以看到打印的效果了:
没有防溢出-30
防溢出0
没有防溢出写入了什么?226
没有防溢出257
防溢出255
没有防溢出写入了什么?1
我们拿出两条打印结果来看一下,当计算的像素值超过了255,那么防溢出之后会变成255,如果计算的像素值超过了小于0,那么防溢出之后会变成0,而如果没有加防溢出,直接向图片里面写入的话会写进入什么值呢?
-30变成了226
257变成1
可以看到,OpenCV为了让图片可以正常的显示,会把一个负值加上256,把一个超过256的正值减下去256,这样就会出现上面那种奇怪的结果了。
下面我们举个栗子吧:
选择一个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,这样就会出现上面那种奇怪的结果了。
相关文章推荐
- OpenCV学习--saturate_cast防止数据溢出
- 【Opencv】saturate_cast防止数据溢出
- opencv中的saturate_cast数据溢出保护
- OpenCV学习--saturate_cast防止数据溢出
- Opencv之saturate_cast防止数据溢出
- OpenCV学习--saturate_cast防止数据溢出
- OpenCV学习--saturate_cast防止数据溢出
- OpenCV学习--saturate_cast防止数据溢出
- OpenCV学习二:指针操作、saturate_cast
- opencv之saturate_cast模板函数
- opencv学习日常之“Saturation Casting“转换saturate_cast<>()
- OpenCV-saturate_cast
- opencv函数之saturate_cast(防止溢出)
- opencv2.0 saturate_cast<?> 研究
- saturate_cast<uchar>(int v)的作用
- 【OpenCV】内存溢出
- saturate_cast的作用
- Opencv中防止像素数据溢出介绍
- saturate_cast
- saturate_cast 图像对比度与亮度