OpenCV函数 重映射

重映射是什么意思?

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

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

  • 我们通过重映射来表达每个像素的位置 (x,y) :

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

    这里 g() 是目标图像, f() 是源图像, h(x,y) 是作用于 (x,y) 的映射方法函数.

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

h(x,y) = (I.cols - x, y )

会发生什么? 图像会按照 x 轴方向发生翻转. 

映射函数 remap. 参数说明:

代码如下:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace cv;

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

/// Function Headers
void update_map(void);

/**
* @function main
*/
int main(int argc, char** argv)
{
    /// Load the image
    src = imread("E:\VS2015Opencv\vs2015\project\picture\06.jpg", 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 window
    namedWindow(remap_window, CV_WINDOW_AUTOSIZE);

    /// Loop
    while (true)
    {
        /// Each 1 sec. Press ESC to exit the program
        int c = waitKey(1000);

        if ((char)c == 27)
        {
            break;
        }

        /// Update map_x & map_y. Then apply remap
        update_map();
        remap(src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));

        /// Display results
        imshow(remap_window, dst);
    }
    return 0;
}

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++;
}

主要代码说明:

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

重映射函数 remap. 参数说明:

  • src: 源图像
  • dst: 目标图像,与 src 相同大小
  • map_x: x方向的映射参数. 它相当于方法 h(i,j) 的第一个参数
  • map_y: y方向的映射参数. 注意 map_y 和 map_x 与 src 的大小一致。
  • CV_INTER_LINEAR: 非整数像素坐标插值标志. 这里给出的是默认值(双线性插值).
  • BORDER_CONSTANT: 默认
while (true)
	{
		/// Each 1 sec. Press ESC to exit the program
		int c = waitKey(1000);

		if ((char)c == 27)
		{
			break;
		}

		/// Update map_x & map_y. Then apply remap
		update_map();
		remap(src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));

		/// Display results
		imshow(remap_window, dst);
	}
	return 0;
}

  我们做了什么哪些映射过程?(在这里 map_x 代表第一个坐标 h(i,j) , map_y 是第二个坐标,映射后的坐标)

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

结果如下:

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

 图像上下颠倒:

图像左右颠倒:

 两个方向同时颠倒:

原文地址:https://www.cnblogs.com/fcfc940503/p/11305349.html