opencv之saturate_cast模板函数
2012-11-02 09:18
253 查看
saturate_cast¶
Template function for accurate conversion from one primitive type to another.C++:template<...> _Tpsaturate_cast(_Tp2v)¶
Parameters: | v – Function parameter. |
---|
They perform an efficient and accurate conversion from one primitive type to another (see the introduction chapter).saturate in the name means that when the input valuev
is out of the range of the target type, the result is not formed just by taking low bits of the input, but instead the value is clipped. For example:
uchar a = saturate_cast<uchar>(-100); // a = 0 (UCHAR_MIN) short b = saturate_cast<short>(33333.33333); // b = 32767 (SHRT_MAX)
Such clipping is done when the target type is unsignedchar ,signedchar ,unsignedshort
orsignedshort . For 32-bit integers, no clipping is done.
When the parameter is a floating-point value and the target type is an integer (8-, 16- or 32-bit), the floating-point value is first rounded to the nearest integer and then clipped if needed (when the target type is 8- or 16-bit).
This operation is used in the simplest or most complex image processing functions in OpenCV.
See also
add(),subtract(),multiply(),divide(),Mat::convertTo()
考虑:为什么上面的函数会用到saturate_cast呢,因为无论是加是减,乘除,都会超出一个像素灰度值的范围(0~255)所以,所以当运算完之后,结果为负,则转为0,结果超出255,则为255。
另外在梯度锐化的函数里,也会涉及到saturate_cast。
如:
from: http://ggicci.blog.163.com/blog/static/210364096201262123236955/
OpenCV图像处理 空间域图像增强(图像锐化 1 基于拉普拉斯算子)
2012-07-21 14:32:36| 分类:OpenCV/EmguCV| 标签:opencv图像处理 opencv图像锐化 拉普拉斯算子 空间域图像增强 opencv |字号大中小 订阅Title :
OpenCV
OpenCV 图像锐化
拉普拉斯算子 ( Laplacian operator )
Quote :
It is indeed a well-known result in image processing that if you subtract its Laplacian from an image, the image edges are amplified giving a sharper image. [FromOpenCV 2 Computer Vision Application Programming
Cookbook]
对于求一个锐化后的像素点(sharpened_pixel),这个基于拉普拉斯算子的简单算法主要是遍历图像中的像素点,根据领域像素确定其锐化后的值
计算公式:sharpened_pixel = 5 * current – left – right – up – down ; [见Code1]
当一个运算是通过领域像素进行的时候,我们通常用一个矩阵来表示这种运算关系,也就是我们经常所说的核 (Kernel)。那么上面的锐化滤波器 (Sharpening Filter)
就可以用这个矩阵表示为它的核:
-1 | ||
-1 | 5 | -1 |
-1 |
Code 1 :
/*
Author : Ggicci
Date : 2012.07.19
File : sharp.h
*/
#pragma once
#include <opencv\cv.h>
using namespace cv;
namespace ggicci
{
void sharpen(const Mat& img, Mat& result);
}
/*
Author : Ggicci
Date : 2012.07.19
File : sharp.cpp
*/
#include "sharp.h"
void ggicci::sharpen(const Mat& img, Mat& result)
{
result.create(img.size(), img.type());
//处理边界内部的像素点, 图像最外围的像素点应该额外处理
for (int row = 1; row < img.rows-1; row++)
{
//前一行像素点
const uchar* previous = img.ptr<const uchar>(row-1);
//待处理的当前行
const uchar* current = img.ptr<const uchar>(row);
//下一行
const uchar* next = img.ptr<const uchar>(row+1);
uchar *output = result.ptr<uchar>(row);
int ch = img.channels();
int starts = ch;
int ends = (img.cols - 1) * ch;
for (int col = starts; col < ends; col++)
{
//输出图像的遍历指针与当前行的指针同步递增, 以每行的每一个像素点的每一个通道值为一个递增量, 因为要考虑到图像的通道数
*output++ = saturate_cast<uchar>(5 * current[col] - current[col-ch] - current[col+ch] - previous[col] - next[col]);//因为这里可能
超出了(0~255的范围。如某个像素为黑色0,其周围的四领域都是白色255.这样就结果为负数了。
}
} //end loop
//处理边界, 外围像素点设为 0
result.row(0).setTo(Scalar::all(0));
result.row(result.rows-1).setTo(Scalar::all(0));
result.col(0).setTo(Scalar::all(0));
result.col(result.cols-1).setTo(Scalar::all(0));
}
/*
Author : Ggicci
Date : 2012.07.19
File : main.cpp
*/
#include <opencv\highgui.h>
#pragma comment(lib, "opencv_core231d.lib")
#pragma comment(lib, "opencv_highgui231d.lib")
#pragma comment(lib, "opencv_imgproc231d.lib")
using namespace cv;
#include "sharp.h"
int main()
{
Mat lena = imread("lena.jpg");
Mat sharpenedLena;
ggicci::sharpen(lena, sharpenedLena);
imshow("lena", lena);
imshow("sharpened lena", sharpenedLena);
cvWaitKey();
return 0;
}
Output 1 :
Code 2 :
1: int main()
2: {
3: Mat lena = imread("lena.jpg");
4: Mat sharpenedLena;
5: Mat kernel = (Mat_<float>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
6: cv::filter2D(lena, sharpenedLena, lena.depth(), kernel);
7:
8: imshow("lena", lena);
9: imshow("sharpened lena", sharpenedLena);
10: cvWaitKey();
11: return 0;
12: }
Output 2 :
c++代码:
// 行(除去边缘几行)
for(i = iTempMY; i < lHeight - iTempH + iTempMY + 1; i++)
{
// 列(除去边缘几列)
for(j = iTempMX; j < lWidth - iTempW + iTempMX + 1; j++)
{
// 指向新DIB第i行,第j个象素的指针
lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
fResult = 0;
// 计算
for (k = 0; k < iTempH; k++)
{
for (l = 0; l < iTempW; l++)
{
// 指向DIB第i - iTempMY + k行,第j - iTempMX + l个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i + iTempMY - k) + j - iTempMX + l;
// 保存象素值
fResult += (* lpSrc) * fpArray[k * iTempW + l];
}
}
// 乘上系数
fResult *= fCoef;
// 取绝对值
fResult = (FLOAT ) fabs(fResult);
// 判断是否超过255
if(fResult > 255)
{
// 直接赋值为255
* lpDst = 255;
}
else
{
// 赋值
* lpDst = (unsigned char) (fResult + 0.5);
}
}
}
从这里可以进一步看出:模板平滑可能导致当前像素的值为负活着超出255的范围。但是上面的C++代码中是将负取绝对值有点牵强!变为0可能更合适。
相关文章推荐
- OpenCV学习--saturate_cast防止数据溢出
- OpenCV学习--saturate_cast防止数据溢出
- opencv中的saturate_cast数据溢出保护
- 【Opencv】saturate_cast防止数据溢出
- opencv2.0 saturate_cast<?> 研究
- opencv学习日常之“Saturation Casting“转换saturate_cast<>()
- OpenCV学习--saturate_cast防止数据溢出
- OpenCV学习--saturate_cast防止数据溢出
- OpenCV-saturate_cast
- Opencv之saturate_cast防止数据溢出
- OpenCV学习二:指针操作、saturate_cast
- 聊一聊OpenCV的saturate_cast防溢出
- OpenCV学习--saturate_cast防止数据溢出
- OpenCV不同类型Mat的at方法访问元素时该如何确定模板函数的typename
- 学习笔记 LLVM(3) cast<> 模板函数
- saturate_cast
- saturate_cast 图像对比度与亮度
- saturate_cast<uchar>(int v)的作用
- opencv实现多图像读取并显示,sprintf_s函数,static_cast
- opencv函数之saturate_cast(防止溢出)