1. 概述
在本文中记录集中简单的几何变换的Opencv实现,对于不是依赖Opencv实现的也可以按照类似的写法完成移植,这些函数经过测试都是可以正常使用的。
2. 实现
图像的平移变换:
//************************************************************************
// 函数名称: ImgMove
// 访问权限: public
// 创建日期: 2016/12/05
// 创 建 人:
// 函数说明: 图像平移操作
// 函数参数: cv::Mat & input_img 输入图像
// 函数参数: cv::Mat & output_img 输出图像
// 函数参数: const int x_diff 图像X轴上的平移距离
// 函数参数: const int y_diff 图像Y轴上的平移距离
// 返 回 值: bool
//************************************************************************
bool CCalcMutualInfo::ImgMove(cv::Mat& input_img, cv::Mat& output_img, const int x_diff, const int y_diff)
{
if (!input_img.data)
{
cout << "asad" << endl;
return false;
}
int Nrows(input_img.rows);
int Ncols(input_img.cols);
unsigned char *data1=nullptr, *data2=nullptr;
cv::Mat img_temp(Nrows, Ncols, CV_8UC1, cv::Scalar::all(0));
for (int i = 0; i < Nrows; i++)
{
data2 = img_temp.ptr<uchar>(i);
for (int j = 0; j < Ncols; j++)
{
if ((i >= x_diff) && (j >= y_diff) && (i-x_diff<Nrows) && (j-y_diff<Ncols))
{
data1 = input_img.ptr<uchar>(i - x_diff);
data2[j] = data1[j - y_diff];
}
else
{
data2[j] = 0;
}
}
}
img_temp.copyTo(output_img);
return true;
}
//************************************************************************
// 函数名称: ImgRotate
// 访问权限: public
// 创建日期: 2016/12/06
// 创 建 人:
// 函数说明: 图像旋转
// 函数参数: cv::Mat & input_img 输入图像
// 函数参数: cv::Mat & output_img 输出图像
// 函数参数: const double angle 图像的旋转角度
// 返 回 值: bool
//************************************************************************
bool CCalcMutualInfo::ImgRotate(cv::Mat& input_img, cv::Mat& output_img, const double angle)
{
if (!input_img.data)
{
cout << "asad" << endl;
return false;
}
double image_high = input_img.rows; //the width of image
double image_width = input_img.cols * input_img.channels(); //the high of image
int Nrows = input_img.rows; //the row number of image
int Ncols = input_img.cols * input_img.channels(); //the column number of image
int i=0, j=0; //loop counting
uchar *data1; //the image matrix data pointer
uchar *data2;
cv::Mat Dst_img(input_img.rows, input_img.cols, input_img.type(), cv::Scalar::all(0)); //the destination image matrix that store new image
double Xvar = -0.5*image_high*std::cos(angle) + 0.5*image_width*std::sin(angle) + 0.5*image_high; //the constant of X axis
double Yvar = -0.5*image_high*std::sin(angle) - 0.5*image_width*std::cos(angle) + 0.5*image_width; //the constant of Y axis
for (i=0; i<Nrows; i++)
{
data1 = input_img.ptr<uchar>(i);
data2 = Dst_img.ptr<uchar>(i);
for (j=0; j<Ncols; j++)
{
int X1 = static_cast<int>((double)i*std::cos(angle) - (double)j*std::sin(angle) + Xvar + 0.5);
int Y1 = static_cast<int>((double)i*std::sin(angle) + (double)j*std::cos(angle) + Yvar + 0.5);
if ((X1>=0) && (X1<Nrows) && (Y1>=0) && (Y1<Ncols))
{
data2 = Dst_img.ptr<uchar>(X1);
data2[Y1] = data1[j];
}
}
}
Dst_img.copyTo(output_img);
return true;
}
//************************************************************************
// 函数名称: StretchImg
// 访问权限: public
// 创建日期: 2016/12/07
// 创 建 人:
// 函数说明: 双线性差值缩放图像
// 函数参数: cv::Mat & input_img 输入图像
// 函数参数: cv::Mat & out_img 输出图像
// 函数参数: double x_rate x轴放缩比例
// 函数参数: double y_rate Y轴放缩比例
// 函数参数: int center_x 图像X轴的重心 图像配准使用
// 函数参数: int center_y 图像Y轴的重心 图像配准使用
// 返 回 值: bool
//************************************************************************
bool CCalcMutualInfo::StretchImg(cv::Mat& input_img, cv::Mat& out_img, double x_rate, double y_rate, int center_x, int center_y)
{
if (!input_img.data)
{
cout << "no input img" << endl;
return false;
}
if (0>=x_rate || 0>=y_rate)
{
cout << "rate error" << endl;
return false;
}
//截取重心的512*512的图像,配准用(放缩排除这几行代码)
int center_x1 = (int)((double)center_x*x_rate+0.5);
int center_y2 = (int)((double)center_y*y_rate+0.5);
double dst_rows = input_img.rows * x_rate; //放缩之后目标图像的高度
double dst_cols = input_img.cols * input_img.channels() * y_rate; //放缩之后目标图像的宽度
int Nrows = input_img.rows; //原始图像的高度
int Ncols = input_img.cols * input_img.channels(); //原始图像的宽度
double orig_x = 0, orig_y = 0; //输出图像上换算过去对应原图的点
uchar *data1; //定义三个像素指针
uchar *data2;
uchar *data3;
cv::Mat Dst_img((int)dst_rows, (int)dst_cols / input_img.channels(), input_img.type()); //create a destination image
int i = 0, j = 0; //循环变量
for (i = 0; i < (int)dst_rows; i++)
{
data2 = Dst_img.ptr<uchar>(i);
orig_x = static_cast<double>((double)i * (Nrows - 1) / (dst_rows - 1) + 0.5); //原图中的X坐标值
for (j = 0; j < (int)dst_cols; j++)
{
orig_y = static_cast<double>((double)j * (Ncols - 1) / (dst_cols - 1) + 0.5); //源图像的Y轴坐标
double bx1 = orig_x - (int)orig_x; //计算距离系数,之后按照这个进行加权
double bx2 = 1.0 - bx1;
double by1 = orig_y - (int)orig_y;
double by2 = 1.0 - by1;
if ((orig_x >= 0) && (orig_x < Nrows) && (orig_y >= 0) && (orig_y < Ncols))
{
if ((orig_x < Nrows - 1) && (orig_y < Ncols - 1))
{
data1 = input_img.ptr<uchar>((int)orig_x);
data3 = input_img.ptr<uchar>((int)orig_x + 1);
data2[j] = data1[(int)orig_y] * bx2 * by2 + data1[(int)orig_y + 1] * bx2 * by1 +
data3[(int)orig_y] * bx1 * by2 + data3[(int)orig_y + 1] * bx1 * by1; //计算加权之后的目标像素
}
}
}
}
//截取重心的512*512的图像,配准用(放缩排除这几行代码)
if (dst_rows > Nrows && dst_cols>Ncols)
{
Dst_img = Dst_img(cv::Rect((center_x1-center_x), (center_y-center_y), 512, 512));
}
Dst_img.copyTo(out_img);
return true;
}