原理
图片重映射就是将图片中的像素从一个位置移动到另一个位置,从而形成新的图片。
要实现图片重映射,就有必要使用插值和非整数的像素位置,因此原图和结果图之间不可能总是存在像素的一一对应的。
用公式表示重映射的过程,如下:
g ( x , y ) = f ( h ( x , y ) ) g(x,y)=f(h(x,y)) g(x,y)=f(h(x,y))
- g ( x , y ) g(x,y) g(x,y)是重映射之后的结果图
- f ( ) f() f()是原图
- h ( x , y ) h(x,y) h(x,y)是在 ( x , y ) (x,y) (x,y)像素上的重映射操作
比如,对图片 I I I进行如下重映射操作:
h ( x , y ) = ( I . c o l s − x , y ) h(x,y)=(I.cols-x,y) h(x,y)=(I.cols−x,y)
通过用总列数减去当前列数,可以实现图片在 x x x方向的翻转,就像下面的2张图一样:
API
在OpenCV中,提供了专门的重映射方法cv::remap()
,其函数原型如下:
void cv::remap( InputArray src,
OutputArray dst,
InputArray map1,
InputArray map2,
int interpolation,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar())
- 虽然该函数提供了
map1
和map2
两个map参数,但是可以只有map1
用来提供 ( x , y ) (x,y) (x,y)两个方向上的重映射矩阵;或者map1
提供 x x x上的重映射矩阵、而map2
提供 y y y上的重映射矩阵;interpolation
参数指定插值方法,包括:双线性插值(INTER_LINEAR)、双三次插值(INTER_CUBIC)、最近邻插值(INTER_NEARES)等;注意,在该函数中不能使用INTER_AREA, INTER_LINEAR_EXACT, INTER_NEAREST_EXACT,这3中插值方法borderMode
为边框扩充方法,默认是BORDER_CONSTANT
,即单一颜色边框;当该参数取BORDER_TRANSPARENT
值的时候,表示重映射后超出原图范围的像素将不会被函数修改borderValue
只有在borderMode = BORDER_CONSTANT
的时候才需要提供,用来指定边框的颜色。
注意:该函数目前只支持小于 32767 × 32767 32767 \times 32767 32767×32767尺寸的输入图和输出图。
实现
重映射的关键就是建立映射矩阵。映射矩阵要和原图具有相同的尺寸:
//导入原图
Mat src{
imread("chicky_512.png", IMREAD_COLOR) };
Mat map_x(src.size()