OpenCV 几何变换-图像镜像

图像镜像是图像基本的几何变换之一,实现起来也很简单,先贴上源码:

#include <opencv/highgui.h>  
#include <time.h>  
#include <opencv2/opencv.hpp>  
#include <opencv/cv.h>  
#include <iostream> 

using namespace std;  
using namespace cv; 

int main()
{
    Mat SrcImage = imread("1.jpg",0);
    imshow("原图",SrcImage);
    Mat dst;    
    dst.create( SrcImage.size(), SrcImage.type());    
    Mat map_x;    
    Mat map_y;    
    map_x.create( SrcImage.size(), CV_32FC1);    
    map_y.create( SrcImage.size(), CV_32FC1);    
    for( int i = 0; i < SrcImage.rows; i++)    
    {    
        for( int j = 0; j < SrcImage.cols; j++)    
        {    
            //map_x.at<float>(i, j) = (float) (SrcImage.cols - j-1) ;    
            //map_y.at<float>(i, j) = (float) i ;  //水平  
            map_x.at<float>(i, j) = (float) j ;    
            map_y.at<float>(i, j) = (float) (SrcImage.rows - i-1) ;  //垂直  
        }    
    }    
        remap(SrcImage, dst, map_x, map_y, CV_INTER_LINEAR);    
        imshow("镜像图", dst); 
        waitKey(0);
        return 0;
}

图像镜像功能主要用到OpenCV中的remap()函数,其原型如下:

CV_EXPORTS_W void remap( 
InputArray src, 
OutputArray dst,
InputArray map1, 
InputArray map2,
int interpolation, 
int borderMode=BORDER_CONSTANT,
const Scalar& borderValue=Scalar());

其功能为根据map1和map2两个矩阵,对输入图像src做出重映射,并将映射结果以dst输出。所以参数就很直观了: 第一个参数:输入图像 第二个参数:输出图像 第三个参数:输入图像中各像素点的坐标映射到目标图像的哪个x(列) 第四个参数:输入图像中各像素点的坐标映射到目标图像的哪个x(行) 第五个参数:图像插值方式,可以参考:常用插值方法 第六个参数:边界模式,有默认值BORDER_CONSTANT。 第七个参数:const Scalar&类型的borderValue,当有常数边界时使用的值,其有默认值Scalar( ),即默认值为0。

所以,到底实现怎样的镜像或者是重映射就是由map1和map2两个矩阵决定的了,我们回到上面的代码中具体看下如何实现:

for( int i = 0; i < SrcImage.rows; i++)    
    {    
        for( int j = 0; j < SrcImage.cols; j++)    
        {    
            //map_x.at<float>(i, j) = (float) (SrcImage.cols - j-1) ;    
            //map_y.at<float>(i, j) = (float) i ;  //水平  
            map_x.at<float>(i, j) = (float) j ;    
            map_y.at<float>(i, j) = (float) (SrcImage.rows - i-1) ;  //垂直  
        }    
    }    

矩阵的赋值就是在这里实现的: 假设原图像为6*3的尺寸,当遍历到i=0,j=0时,及 map_x.at(0, 0) = 0 map_y.at(0, 0) = 3-0-1=2 也就是说,原图像的 (0, 0) 会被映射到目标图像的(0, 2),同理: map_x.at(0, 2) = 0 map_y.at(0, 2) = 3-2-1=0 原图像的 (0, 2) 会被映射到目标图像的(0,0),所以实现了垂直镜像。特别要注意的一点是:OpenCV中图像的行列式标号是从0开始的,所以,要(SrcImage.rows - i-1),不然镜像后的图像会有黑边的。

注意:其实还有一点不知道大家留意到没有,我们只用了单通道,并没有用image.at<Vec3b>(i,j)[0] 这样的写法,为什么可以镜像彩色图呢? 因为map_x和map_y矩阵中放的根本就不是像素的灰度,而是映射前后的位置。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏人工智能LeadAI

有趣的应用 | 使用RNN预测股票价格系列一

01 概述 我们将解释如何建立一个有LSTM单元的RNN模型来预测S&P500指数的价格。 数据集可以从Yahoo!下载。 在例子中,使用了从1950年1月3日...

3184
来自专栏AIUAI

Caffe2 - (三十二) Detectron 之 roi_data - 模型 minibatch blobs

5379
来自专栏大数据挖掘DT机器学习

百度魅族深度学习大赛初赛冠军作品(图像识别.源码)

赛题以识别类似手写体的四则运算式为主题,参赛者需要在充满干扰信息的10万张图片中,设计算法识别图片上数学运算式并计算结果。决赛在初赛的基础上,引入分数和更加复杂...

4526
来自专栏机器学习算法工程师

Histogram of Oriented Gridients(HOG) 方向梯度直方图

作者 张旭 编辑 徐松 1. HOG简介 2. 数字图像梯度定义 3. HOG基本步骤 4. OpenCV实现HOG 5. 用KNN与HOG实现一个手写数字输...

3425
来自专栏专知

【论文推荐】最新六篇对抗自编码器相关论文—多尺度网络节点表示、生成对抗自编码、逆映射、Wasserstein、条件对抗、去噪

【导读】专知内容组整理了最近六篇对抗自编码器(Adversarial Autoencoder)相关文章,为大家进行介绍,欢迎查看! 1. AAANE: Atte...

3507
来自专栏杨熹的专栏

TensorFlow-4: tf.contrib.learn 快速入门

学习资料: https://www.tensorflow.org/get_started/tflearn 相应的中文翻译: http://studyai.s...

3476
来自专栏悦思悦读

决策树告诉你Hello Kitty到底是人是猫

Hello Kitty,一只以无嘴造型40年来风靡全球的萌萌猫,在其40岁生日时,居然被其形象拥有者宣称:HelloKitty不是猫! 2014年八月,研究 H...

3377
来自专栏图像识别与深度学习

2018-04-21CNN经典模型

20410
来自专栏一棹烟波

OpenCV亚像素角点cornerSubPixel()源代码分析

  上一篇博客中讲到了goodFeatureToTrack()这个API函数能够获取图像中的强角点。但是获取的角点坐标是整数,但是通常情况下,角点的真实位置并不...

4854
来自专栏深度学习计算机视觉

【ECCV 2018 .Jian Sun】DetNet: A Backbone network for Object Detection

【Background】:ECCV is one of the top conferences in computer vision,In this blog,...

1501

扫码关注云+社区