zoukankan      html  css  js  c++  java
  • 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++;

    结果如下:

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

     图像上下颠倒:

    图像左右颠倒:

     两个方向同时颠倒:

  • 相关阅读:
    【反射】Java反射机制
    Composer教程之常用命令
    Composer教程之基础用法
    Composer教程之初识Composer
    Composer 的结构详解
    现代 PHP 新特性系列(七) —— 内置的 HTTP 服务器
    现代 PHP 新特性系列(一) —— 命名空间
    现代 PHP 新特性系列(二) —— 善用接口
    现代 PHP 新特性系列(三) —— Trait 概览
    现代 PHP 新特性系列(四) —— 生成器的创建和使用
  • 原文地址:https://www.cnblogs.com/fcfc940503/p/11305349.html
Copyright © 2011-2022 走看看