OpenCV重新映射

本文详细介绍了如何在OpenCV中使用cv::remap函数实现简单的图像重映射,包括理论背景、C++和Java代码示例,以及四种不同的映射操作实例。
摘要由CSDN通过智能技术生成

目标

在本教程中,您将学习如何:

一个。使用 OpenCV 函数 cv::remap 实现简单的重映射例程。

理论

什么是重新映射?

  • 它是从图像中的一个位置获取像素并将它们定位在新图像中的另一个位置的过程。

  • 为了完成映射过程,可能需要对非整数像素位置进行一些插值,因为源图像和目标图像之间并不总是存在一比一像素的对应关系。

  • 我们可以将每个像素位置 的重新映射表示为:(x,y)

    g(x,y)=f(h(x,y))

    其中 g() 是重新映射的图像,f() 是源图像,h(x,y) 是对 (x,y) 进行操作的映射函数。g()f()h(x,y)(x,y)

  • 让我们举一个简单的例子。想象一下,我们有一个图像 I,比如说,我们想要做一个重新映射,这样:我

    h(x,y)=(我。cols−x,y)

    会发生什么?很容易看出图像会沿 x 方向翻转。例如,考虑输入图像:x

    Remap_Tutorial_Theory_0.jpg

    观察红色圆圈相对于 x 的位置如何变化(考虑 x 的水平方向):x

    Remap_Tutorial_Theory_1.jpg

  • 在 OpenCV 中,函数 cv::remap 提供了一个简单的重新映射实现。

法典 C++爪哇岛蟒

  • 这个程序是做什么的?

    • 加载图像
    • 每秒,对图像应用 4 个不同重映射过程中的 1 个,并在窗口中无限期地显示它们。
    • 等待用户退出程序
  • 教程代码如下所示。您也可以从这里下载

    #include“opencv2/imgcodecs.hpp

    #include “opencv2/highgui.hpp

    #include“opencv2/imgproc.hpp

    #include < iostream>

    使用命名空间 CV;

    void update_map( int &ind, Mat &map_x, Mat &map_y );

    int main(int argc, const char** argv)

    {

    CommandLineParser 解析器(argc, argv, “{@image |chicky_512.png|input image name}”);

    std::string 文件名 = parser.get<std::string>(0);

    Mat src = imreadsamples::findFile( filename ), IMREAD_COLOR );

    ​ 如果 (src.empty())

    ​ {

    std::cout << “无法读取图像:” << 文件名<< std::endl;

    ​ 返回 -1;

    ​ }

    dst(src.size(), src.type());

    子map_x(src.size(), CV_32FC1);

    子map_y(src.size(), CV_32FC1);

    ​ const char* remap_window = “重新映射演示”;

    namedWindow( remap_window, WINDOW_AUTOSIZE );

    ​ int ind = 0;

    ​ 为(;😉

    ​ {

    update_map(工业、map_x、map_y);

    remap( src, dst, map_x, map_y, INTER_LINEARBORDER_CONSTANT标量(0, 0, 0) );

    imshow( remap_window, dst );

    ​ 字符 c = (char)waitKey( 1000 );

    ​ 如果( c == 27 )

    ​ {

    ​ 破;

    ​ }

    ​ }

    ​ 返回 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++ )

    ​ {

    ​ 开关( ind )

    ​ {

    ​ 案例 0:

    ​ if( j > map_x.cols*0.25 && j < map_x.cols0.75 && i > map_x.rows0.25 && i < map_x.rows*0.75 )

    ​ {

    map_x.at(i, j) = 2*( j - map_x.cols*0.25f ) + 0.5f;

    map_y.at(i, j) = 2*( i - map_x.rows*0.25f ) + 0.5f;

    ​ }

    ​ 还

    ​ {

    map_x.at(i, j) = 0;

    map_y.at(i, j) = 0;

    ​ }

    ​ 破;

    ​ 案例 1:

    map_x.at(i, j) = (float)j;

    map_y.at(i, j) = (float)(map_x.rows - i);

    ​ 破;

    ​ 案例 2:

    map_x.at(i, j) = (float)(map_x.cols - j);

    map_y.at(i, j) = (float)i;

    ​ 破;

    ​ case 3:

    ​ map_x.at(i, j) = (float)(map_x.cols - j);

    ​ map_y.at(i, j) = (float)(map_x.rows - i);

    ​ break;

    ​ default:

    ​ break;

    ​ } // end of switch

    ​ }

    ​ }

    ​ ind = (ind+1) % 4;

    }

Explanation C++JavaPython

  • Load an image:

​ Mat src = imread( samples::findFile( filename ), IMREAD_COLOR );

​ if (src.empty())

​ {

​ std::cout << "Cannot read image: " << filename << std::endl;

​ return -1;

​ }

  • Create the destination image and the two mapping matrices (for x and y )

​ Mat dst(src.size(), src.type());

​ Mat map_x(src.size(), CV_32FC1);

​ Mat map_y(src.size(), CV_32FC1);

  • Create a window to display results

​ const char* remap_window = “Remap demo”;

namedWindow( remap_window, WINDOW_AUTOSIZE );

  • Establish a loop. Each 1000 ms we update our mapping matrices (mat_x and mat_y) and apply them to our source image:

​ 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;

​ }

​ }

  • The function that applies the remapping is cv::remap . We give the following arguments:

    • src: Source image
    • dst: Destination image of same size as src
    • map_x: The mapping function in the x direction. It is equivalent to the first component of h(i,j)
    • map_y: Same as above, but in y direction. Note that map_y and map_x are both of the same size as src
    • INTER_LINEAR: The type of interpolation to use for non-integer pixels. This is by default.
    • BORDER_CONSTANT: Default

    How do we update our mapping matrices mat_x and mat_y? Go on reading:

  • Updating the mapping matrices: We are going to perform 4 different mappings:

    1. Reduce the picture to half its size and will display it in the middle: for all pairs such that: and

      h(i,j)=(2×i−src.cols/2+0.5,2×j−src.rows/2+0.5)

      (i,j)

      src.cols4<i<3⋅src.cols4

      src.rows4<j<3⋅src.rows4

    2. Turn the image upside down: h(i,j)=(i,src.rows−j)

    3. Reflect the image from left to right: h(i,j)=(src.cols−i,j)

    4. Combination of b and c: h(i,j)=(src.cols−i,src.rows−j)

This is expressed in the following snippet. Here, map_x represents the first coordinate of h(i,j) and map_y the second coordinate.

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.cols0.25 && j < map_x.cols0.75 && i > map_x.rows0.25 && i < map_x.rows0.75 )

​ {

​ map_x.at(i, j) = 2*( j - map_x.cols*0.25f ) + 0.5f;

​ map_y.at(i, j) = 2*( i - map_x.rows*0.25f ) + 0.5f;

​ }

​ else

​ {

​ map_x.at(i, j) = 0;

​ map_y.at(i, j) = 0;

​ }

​ break;

​ case 1:

​ map_x.at(i, j) = (float)j;

​ map_y.at(i, j) = (float)(map_x.rows - i);

​ break;

​ case 2:

​ map_x.at(i, j) = (float)(map_x.cols - j);

​ map_y.at(i, j) = (float)i;

​ break;

​ case 3:

​ map_x.at(i, j) = (float)(map_x.cols - j);

​ map_y.at(i, j) = (float)(map_x.rows - i);

​ break;

​ default:

​ break;

​ } // end of switch

​ }

​ }

​ ind = (ind+1) % 4;

}

Result

  1. After compiling the code above, you can execute it giving as argument an image path. For instance, by using the following image:

    Remap_Tutorial_Original_Image.jpg

  2. 这是将其减小到一半并居中的结果:

    Remap_Tutorial_Result_0.jpg

  3. 把它颠倒过来:

    Remap_Tutorial_Result_1.jpg

  4. 在 x 方向上反射它:

    Remap_Tutorial_Result_2.jpg

  5. 在两个方向上反映它:

    Remap_Tutorial_Result_3.jpg

在线教程

请添加图片描述

人工智能书籍

第一阶段:零基础入门(3-6个月)

新手应首先通过少而精的学习,看到全景图,建立大局观。 通过完成小实验,建立信心,才能避免“从入门到放弃”的尴尬。因此,第一阶段只推荐4本最必要的书(而且这些书到了第二、三阶段也能继续用),入门以后,在后续学习中再“哪里不会补哪里”即可。

第二阶段:基础进阶(3-6个月)

熟读《机器学习算法的数学解析与Python实现》并动手实践后,你已经对机器学习有了基本的了解,不再是小白了。这时可以开始触类旁通,学习热门技术,加强实践水平。在深入学习的同时,也可以探索自己感兴趣的方向,为求职面试打好基础。

第三阶段:工作应用

这一阶段你已经不再需要引导,只需要一些推荐书目。如果你从入门时就确认了未来的工作方向,可以在第二阶段就提前阅读相关入门书籍(对应“商业落地五大方向”中的前两本),然后再“哪里不会补哪里”。

有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值