您的位置:首页 > 运维架构

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.
The functions saturate_cast resemble the standard C++ cast operations, such asstatic_cast<T>() and others.
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 
-15-1
 -1 
因为 滤波 在图像处理中是一个非常普通且常用的操作,所以OpenCV里面已经定义了一个特殊的函数用来执行这个操作。要使用它的话只需要定义一个,然后作为参数传递就行了。[见Code2]
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可能更合适。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: