图像处理中几个常用函数(Opencv实现)
图像处理中,有一些会经常用到的函数:
1)Gamma校正
void gammaCorrection(Mat& img, Mat& output, double gamma )
{
Mat temp;
img.convertTo(temp, CV_32F);
cv::log( temp, output );
output.mul(output, gamma); //output = gamma* output;
cv::exp( output, output);
output.convertTo(output, CV_8U);
}
2)二值化
void thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type )
{
int i, j, j_scalar = 0;
uchar tab[256];
Size roi = _src.size();
roi.width *= _src.channels();
if( _src.isContinuous() && _dst.isContinuous() )
{
roi.width *= roi.height;
roi.height = 1;
}
switch( type )
{
case THRESH_BINARY:
for( i = 0; i <= thresh; i++ )
tab[i] = 0;
for( ; i < 256; i++ )
tab[i] = maxval;
break;
case THRESH_BINARY_INV:
for( i = 0; i <= thresh; i++ )
tab[i] = maxval;
for( ; i < 256; i++ )
tab[i] = 0;
break;
case THRESH_TRUNC:
for( i = 0; i <= thresh; i++ )
tab[i] = (uchar)i;
for( ; i < 256; i++ )
tab[i] = thresh;
break;
case THRESH_TOZERO:
for( i = 0; i <= thresh; i++ )
tab[i] = 0;
for( ; i < 256; i++ )
tab[i] = (uchar)i;
break;
case THRESH_TOZERO_INV:
for( i = 0; i <= thresh; i++ )
tab[i] = (uchar)i;
for( ; i < 256; i++ )
tab[i] = 0;
break;
default:
CV_Error( CV_StsBadArg, "Unknown threshold type" );
}
if( j_scalar < roi.width )
{
for( i = 0; i < roi.height; i++ )
{
const uchar* src = (const uchar*)(_src.data + _src.step*i);
uchar* dst = (uchar*)(_dst.data + _dst.step*i);
j = j_scalar;
for( ; j < roi.width; j++ )
dst[j] = tab[src[j]];
}
}
}
3)信噪比
double PSNR(InputArray _src1, InputArray _src2)
{
Mat src1 = _src1.getMat(), src2 = _src2.getMat();
CV_Assert( src1.depth() == CV_8U );
double diff = std::sqrt(norm(src1, src2, NORM_L2SQR)/(src1.total()*src1.channels()));
return 20*log10(255./(diff+DBL_EPSILON));
}
4)计算角度
float calcAngle(float x1,float y1,float x2,float y2)
{
float angle_temp;
float xx, yy;
xx = x2 - x1;
yy = y2 - y1;
if (xx == 0.0)
angle_temp = PI / 2.0;
else
angle_temp = atan(fabs(yy / xx));
if ((xx < 0.0) && (yy >= 0.0))
angle_temp = PI - angle_temp;
else if ((xx < 0.0) && (yy < 0.0))
angle_temp = PI + angle_temp;
else if ((xx >= 0.0) && (yy < 0.0))
angle_temp = PI * 2.0 - angle_temp;
return (angle_temp);
}
5)计算均值和方差
double localvariance(const Mat &image, const uint winsize, const uint xpos, const uint ypos) // 单通道8位灰度图像
{
// 原理:方差 = 平方的均值 - 均值的平方
double mean=0.0, var=0.0;
int counter=0;
for(int x=xpos-winsize;x<=xpos+winsize;++x)
{
for(int y=ypos-winsize;y<=ypos+winsize;++y)
{
uchar val = image.at<uchar>(x,y);
mean += val;
var += val*val ;
++counter;
}
}
mean/=double(counter); var/=double(counter);
var-=mean*mean;
return var;
}
6)矩阵归一化
Mat normalizeMat(const Mat input)
{
double minVal, maxVal;
minMaxLoc(input, &minVal, &maxVal);
Mat normMat = (input - minVal) / (maxVal - minVal) * 255;
Mat output;
normMat.convertTo(output, CV_8U);
return output;
}
7)获取一个vector的中值
float median(vector<float> v)
{
int n = cvFloor(v.size() / 2);
nth_element(v.begin(), v.begin()+n, v.end());
return v[n];
}
8)Mat类型数据访问
// chn:number of channel, k: the kth channel (default k=0)
template<typename _T> inline _T getPixelValue( const Mat& image, int x, int y, int chn, int k)
{
return ((_T*)image.data + image.step*y/sizeof(_T))[x*chn+k];
}
template<typename _T> inline void setPixelValue( const Mat& image, int x, int y, int chn, int k, _T _val)
{
return ((_T*)image.data + image.step*y/sizeof(_T))[x*chn+k] = _val;
}
9)将IplImage或Mat转为一位数组或vector
template<typename _T> void MatToVec1D( const Mat& img, std::vector<_T>& pixels)
{
int width = img.cols;
int height = img.rows;
pixels.clear();
pixels.resize(width*height);
for ( int i= 0; i<height; i++)
{
_T* data = (_T*)img.data + i*img.step[0]/sizeof(_T);
for ( int j=0; j<width; j++)
{
pixels[i*width+j]= data[j];
}
}
}
10)将一位数组或vector转为Mat或IplImage
void vector1DToIplImage(unsigned char* data , int WIDTH , int HEIGTH , IplImage* IMG)
{
int k = 0 ;
for (int i = 0 ; i < HEIGTH ; i ++)
{
uchar* ptr = (uchar*)(IMG->imageData + i*IMG->widthStep);
for (int j = 0 ; j < WIDTH ; j ++)
{
ptr[j] = data[k] ;
k ++ ;
}
}
}
11)获取本地时间
std::string getTime()
{
char buffer[40];
struct tm *TM;
time_t t;
time(&t);
TM=localtime(&t);
strftime(buffer,40,"%Y-%m-%d %H:%M:%S",TM);
std::string result(buffer);
return result;
}