重映射的意思就是把原始图像中某位置的像素放置到目标图像指定位置的过程,在Emgu CV中,Remap()重映射函数可以实现图像的缩放、翻转等操作,函数定义如下:
public static void Remap(
IInputArray src, // 输入图像
IOutputArray dst, // 输出图像
IInputArray map1, // 输入图像每个像素点在输出图像中对应位置的x坐标系数矩阵
IInputArray map2, // 输入图像每个像素点在输出图像中对应位置的y坐标系数矩阵
Inter interpolation, // 插值方法
BorderType borderMode = BorderType.Constant, // 边界模式
MCvScalar borderValue = default(MCvScalar) // 边界值
)
函数用起来很简单,代码如下:
CvInvoke.Remap(dstMat, dstMat, mapX, mapY, Inter.Linear);
但是,个人认为这个函数用处不大,而且比较难使用。
1、map1和map2对应关系,需要开发人员自己定义,有难度。
2、在C#中,修改Mat类型变量值很麻烦,不像C++配合OpenCV一样,可以直接修改Mat变量值。
关于如何定义Mat类型的mapX和mapY,目前我也没实现呢,读者们可以参考OpenCV里面关于remap函数的说明,我先把OpenCV官方的C++演示代码贴上啊,读者们可以试着转成C#的。
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
void update_map( int &ind, Mat &map_x, Mat &map_y );
int main(int argc, const char** argv)
{
CommandLineParser parser(argc, argv, "{@image |chicky_512.png|input image name}");
std::string filename = parser.get<std::string>(0);
Mat src = imread( samples::findFile( filename ), IMREAD_COLOR );
if (src.empty())
{
std::cout << "Cannot read image: " << filename << std::endl;
return -1;
}
Mat dst(src.size(), src.type());
Mat map_x(src.size(), CV_32FC1);
Mat map_y(src.size(), CV_32FC1);
const char* remap_window = "Remap demo";
namedWindow( remap_window, WINDOW_AUTOSIZE );
int ind = 0;
for(;;)
{
update_map(ind, map_x, map_y);
remap( src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) );
imshow( remap_window, dst );
char c = (char)waitKey( 1000 );
if( c == 27 )
{
break;
}
}
return 0;
}
void update_map( int &ind, Mat &map_x, Mat &map_y )
{
for( int i = 0; i < map_x.rows; i++ )
{
for( int j = 0; j < map_x.cols; j++ )
{
switch( ind )
{
case 0:
if( j > map_x.cols*0.25 && j < map_x.cols*0.75 && i > map_x.rows*0.25 && i < map_x.rows*0.75 )
{
map_x.at<float>(i, j) = 2*( j - map_x.cols*0.25f ) + 0.5f;
map_y.at<float>(i, j) = 2*( i - map_x.rows*0.25f ) + 0.5f;
}
else
{
map_x.at<float>(i, j) = 0;
map_y.at<float>(i, j) = 0;
}
break;
case 1:
map_x.at<float>(i, j) = (float)j;
map_y.at<float>(i, j) = (float)(map_x.rows - i);
break;
case 2:
map_x.at<float>(i, j) = (float)(map_x.cols - j);
map_y.at<float>(i, j) = (float)i;
break;
case 3:
map_x.at<float>(i, j) = (float)(map_x.cols - j);
map_y.at<float>(i, j) = (float)(map_x.rows - i);
break;
default:
break;
} // end of switch
}
}
ind = (ind+1) % 4;
}
注意哈,update_map函数可以设计出四种mapX和mapY的对应关系,分别实现:
1.原始图像长宽个缩小一半并居中显示
2.原始图像上下翻转
3.原始图像左右翻转
4.原始图像上下左右一同翻转
OpenCV介绍的网址是:
remap函数介绍
不建议在Emgu CV里面使用Remap()函数,读者们简单看看就可以了。
原创不易,请勿抄袭。共同进步,相互学习。