重映射是什么意思?

  • 把一个图像中一个位置的像素放置到另一个图片指定位置的过程.

  • 为了完成映射过程, 有必要获得一些插值为非整数像素坐标,因为源图像与目标图像的像素坐标不是一一对应的.

  • 我们通过重映射来表达每个像素的位置  :

    这里  是目标图像,  是源图像,  是作用于  的映射方法函数.

  • 让我们来思考一个快速的例子. 想象一下我们有一个图像  , 我们想满足下面的条件作重映射:

    会发生什么? 图像会按照  轴方向发生翻转. 例如, 源图像如下:

    看到红色圈关于 x 的位置改变(  轴水平翻转):

  • 通过 OpenCV 的函数 remap 提供一个简单的重映射实现.

代码

  1. 本程序做什么?

    • 装载一幅图像.
    • 程序按秒循环, 在一个窗口中顺序出现4种重映射过程对相同的图像.
    • 等待用户按 ‘ESC’ 键退出程序。
  2. 下面是本教程代码. 你也可以从 这里 下载。
 #include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>#include <stdio.h>using namespace cv;/// Global variablesMat src, dst;Mat map_x, map_y;char* remap_window = "Remap demo";int ind = 0;/// Function Headersvoid update_map( void );/**
 * @function main
 */int main( int argc, char** argv ){/// Load the imagesrc = imread( argv[1], 1 );/// Create dst, map_x and map_y with the same size as src:dst.create( src.size(), src.type() );map_x.create( src.size(), CV_32FC1 );map_y.create( src.size(), CV_32FC1 );/// Create windownamedWindow( remap_window, CV_WINDOW_AUTOSIZE );/// Loopwhile( true ){/// Each 1 sec. Press ESC to exit the programint c = waitKey( 1000 );if( (char)c == 27 ){ break; }/// Update map_x & map_y. Then apply remapupdate_map();remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) );/// Display resultsimshow( remap_window, dst );}return 0;}/**
 * @function update_map
 * @brief Fill the map_x and map_y matrices with 4 types of mappings
 */void update_map( void ){ind = ind%4;for( int j = 0; j < src.rows; j++ ){ for( int i = 0; i < src.cols; i++ ){switch( ind ){case 0:if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 ){map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;}else{ map_x.at<float>(j,i) = 0 ;map_y.at<float>(j,i) = 0 ;}break;case 1:map_x.at<float>(j,i) = i ;map_y.at<float>(j,i) = src.rows - j ;break;case 2:map_x.at<float>(j,i) = src.cols - i ;map_y.at<float>(j,i) = j ;break;case 3:map_x.at<float>(j,i) = src.cols - i ;map_y.at<float>(j,i) = src.rows - j ;break;} // end of switch}}ind++;
}

说明

  1. 首先准备程序用到的变量:

    Mat src, dst;
    Mat map_x, map_y;
    char* remap_window = "Remap demo";
    int ind = 0;
    

  2. 加载一幅图像:

    src = imread( argv[1], 1 );
    

  3. 创建目标图像和两个映射矩阵.( x 和 y )

    dst.create( src.size(), src.type() );
    map_x.create( src.size(), CV_32FC1 );
    map_y.create( src.size(), CV_32FC1 );
    

  4. 创建一个窗口用于展示结果.

    namedWindow( remap_window, CV_WINDOW_AUTOSIZE );
    

  5. 建立一个间隔1000毫秒的循环,每次循环执行更新映射矩阵参数并对源图像进行重映射处理(使用 mat_x 和 mat_y),然后把更新后的目标图像显示出来:

    while( true )
    {/// Each 1 sec. Press ESC to exit the programint c = waitKey( 1000 );if( (char)c == 27 ){ break; }/// Update map_x & map_y. Then apply remapupdate_map();remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) );/// Display resultsimshow( remap_window, dst );
    }
    

    上面用到的重映射函数 remap. 参数说明:

    • src: 源图像
    • dst: 目标图像,与 src 相同大小
    • map_x: x方向的映射参数. 它相当于方法  的第一个参数
    • map_y: y方向的映射参数. 注意 map_y 和 map_x 与 src 的大小一致。
    • CV_INTER_LINEAR: 非整数像素坐标插值标志. 这里给出的是默认值(双线性插值).
    • BORDER_CONSTANT: 默认

    如何更新重映射矩阵 mat_x 和 mat_y? 请继续看:

  6. 更新重映射矩阵: 我们将分别使用4种不同的映射:

    1. 图像宽高缩小一半,并显示在中间:

      所有成对的参数  处理后都符合:  和 

    2. 图像上下颠倒: 

    3. 图像左右颠倒: 

    4. 同时执行b和c的操作: 

下面的代码片段说明上述的映射过程. 在这里 map_x 代表第一个坐标 h(i,j) , map_y 是第二个坐标.

for( int j = 0; j < src.rows; j++ )
{ for( int i = 0; i < src.cols; i++ ){switch( ind ){case 0:if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 ){map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;}else{ map_x.at<float>(j,i) = 0 ;map_y.at<float>(j,i) = 0 ;}break;case 1:map_x.at<float>(j,i) = i ;map_y.at<float>(j,i) = src.rows - j ;break;case 2:map_x.at<float>(j,i) = src.cols - i ;map_y.at<float>(j,i) = j ;break;case 3:map_x.at<float>(j,i) = src.cols - i ;map_y.at<float>(j,i) = src.rows - j ;break;} // end of switch}}ind++;
}

结果

  1. 上面的代码编译后, 运行时给一个图片路径参数. 例如,使用下面的图片:

  2. 图像宽高缩小一半,并显示在中间:

  3. 图像上下颠倒:

  4. 图像左右颠倒:

  5. 两个方向同时颠倒:

opencv Remap 图像的映射相关推荐

  1. Python OpenCV实例:图像重映射

    为什么80%的码农都做不了架构师?>>>    #coding:utf-8 ''' 图像重映射 ''' import cv2 import numpy as npsrc = cv2. ...

  2. VS+openCV 之操作像素(下)实现简单的图像运算、图像重映射

    一.实现简单的图像运算 [事前准备]准备两张大小一样的图片 [实现] cv::Mat image1;image1 = cv::imread("1.jpg");cv::Mat ima ...

  3. Opencv remap函数

    Opencv remap函数 函数签名 实例 应用 亚像素信息 扭曲特效 函数签名 void cv::remap ( InputArray src, OutputArray dst, InputArr ...

  4. opencv之图像翻转、平移、缩放、旋转、仿射学习笔记

    opencv版本:opencv3.4.1 目录 1. 图像翻转(坐标映射) 2.  平移 3. 缩放 4. 旋转 1. 图像翻转(坐标映射) int main() {cv::Mat srcImage ...

  5. 使用Python、OpenCV进行图像接缝雕刻

    使用Python.OpenCV进行图像接缝雕刻 1. 效果图 2. 原理 3. 安装--鉴于算法的专利原因,0.16以上版本均去掉了接缝雕刻算法: 4. 源码 参考 这篇博客将介绍基于图像内容感知调整 ...

  6. 使用OpenCV进行图像全景拼接

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 图像拼接是计算机视觉中最成功的应用之一.如今,很难找到不包含此功能 ...

  7. 使用Numpy和Opencv完成图像的基本数据分析(Part III)

    引言 本文是使用python进行图像基本处理系列的第三部分,在本人之前的文章里介绍了一些非常基本的图像分析操作,见文章<使用Numpy和Opencv完成图像的基本数据分析Part I>和& ...

  8. python全景图像拼接_Python+OpenCV实现图像的全景拼接

    本文实例为大家分享了Python+OpenCV实现图像的全景拼接的具体代码,供大家参考,具体内容如下 环境:python3.5.2 + openCV3.4 1.算法目的 将两张相同场景的场景图片进行全 ...

  9. opencv remap matlab,如何使用OpenCV的remap函数?

    这只是对文件的一个简单的误解,我不怪你--我也花了几次摸索才明白.文档很清楚,但是这个函数可能没有按您预期的方式工作:事实上,它在与我最初预期相反的方向工作. remap()没有做的是获取源图像的坐标 ...

最新文章

  1. 雷林鹏分享:PHP 超级全局变量
  2. linux下创建具有root权限的账户
  3. 1.11.Flink DataSetAPI、DataSet API之Data Sources、DataSet API之Transformations、DataSet Sink部分详解
  4. php推荐码生成,最新最全PHP生成制作验证码代码详解(推荐),验证码详解_PHP教程...
  5. ContentProvider与ContentResolver
  6. 软考中级,软件设计师考试那些内容,考试大纲什么的?
  7. mac上投屏android_简单实用的手机投屏Mac电脑
  8. 优盘插计算机上成快捷方式,u盘一插就变成快捷方式打不开怎么办 u盘变成快捷方式怎么办...
  9. powershell_windows命令行杀进程(pskill)/进程任务管理/服务管理/(查看/关闭/停止/移除windows移除mysql服务)
  10. Python可视化基础----从0学会matplotlib折线图,条形图,散点图
  11. RK3568 Android11从入门到实战项目专栏目录及介绍
  12. EWAHCompressedBitmap数据结构及原理
  13. 人脸识别之FaceNet
  14. 2022年搭载国产芯片的手机推荐 这3款性能就不错
  15. DFS应用:纵火犯题解
  16. C#集合中的Add与AddRange
  17. node实现登录状态保持(cookie-session/token)
  18. (已解决)飞秋安装完毕无法发现局域网内的好友
  19. entity、bo、vo、po、dto、pojo、dao、service、controler如何理解和区分?
  20. 优先级队列priority_queue

热门文章

  1. Qualcomm thermal的介绍
  2. sd 卡驱动--基于高通平台
  3. xp主机用VMware9和10安装Ubuntu12.04后无法进入图像界面
  4. 在EXCEL指定SHEET页,指定文字位置,插入批注
  5. zabbix监控mysql最简单的方法
  6. Web 端的下一代三维图形
  7. 修改文档框架:word-多级列表与标题样式相结合
  8. 【Android开发】构建Android源码编译环境
  9. 谈谈NITE 2与OpenCV结合的第二个程序(提取人体骨骼坐标)
  10. android学习之旅_01