OpenCV中实现图像翻转的函数flip,公式为:

目前fbc_cv库中也实现了flip函数,支持多通道,uchar和float两种数据类型,经测试,与OpenCV3.1结果完全一致。

实现代码flip.hpp:

  1. // fbc_cv is free software and uses the same licence as OpenCV
  2. // Email: fengbingchun@163.com
  3.  
  4. #ifndef FBC_CV_FLIP_HPP_
  5. #define FBC_CV_FLIP_HPP_
  6.  
  7. /* reference: include/opencv2/core.hpp
  8. modules/core/src/copy.cpp
  9. */
  10.  
  11. #include <typeinfo>
  12. #include "core/mat.hpp"
  13.  
  14. namespace fbc {
  15.  
  16. template<typename _Tp, int chs> static int flipHoriz(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);
  17. template<typename _Tp, int chs> static int flipVert(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);
  18.  
  19. // Flips a 2D array around vertical, horizontal, or both axes
  20. // flipCode: 0 means flipping around the x - axis and positive value means flipping around y - axis.
  21. // Negative value means flipping around both axes
  22. // support type: uchar/float, multi-channels
  23. template <typename _Tp, int chs>
  24. int flip(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst, int flipCode)
  25. {
  26. FBC_Assert(typeid(uchar).name() == typeid(_Tp).name() || typeid(float).name() == typeid(_Tp).name()); // uchar || float
  27. if (dst.empty()) {
  28. dst = Mat_<_Tp, chs>(src.rows, src.cols);
  29. } else {
  30. FBC_Assert(src.rows == dst.rows && src.cols == dst.cols);
  31. }
  32.  
  33. Size size = src.size();
  34.  
  35. if (flipCode < 0) {
  36. if (size.width == 1)
  37. flipCode = 0;
  38. if (size.height == 1)
  39. flipCode = 1;
  40. }
  41.  
  42. if ((size.width == 1 && flipCode > 0) ||
  43. (size.height == 1 && flipCode == 0) ||
  44. (size.height == 1 && size.width == 1 && flipCode < 0)) {
  45. src.copyTo(dst);
  46. return 0;
  47. }
  48.  
  49. if (flipCode <= 0)
  50. flipVert(src, dst);
  51. else
  52. flipHoriz(src, dst);
  53.  
  54. if (flipCode < 0)
  55. flipHoriz(dst, dst);
  56.  
  57. return 0;
  58. }
  59.  
  60. template<typename _Tp, int chs>
  61. static int flipHoriz(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)
  62. {
  63. Size size = src.size();
  64. size_t esz = sizeof(_Tp) * chs;
  65. int i, j, limit = (int)(((size.width + 1) / 2) *esz );
  66. AutoBuffer<int> _tab(size.width * esz);
  67. int* tab = _tab;
  68. size_t sstep = src.step;
  69. size_t dstep = dst.step;
  70. const uchar* src_ = src.ptr();
  71. uchar* dst_ = dst.ptr();
  72.  
  73. for (i = 0; i < size.width; i++) {
  74. for (size_t k = 0; k < esz; k++) {
  75. tab[i*esz + k] = (int)((size.width - i - 1) * esz + k);
  76. }
  77. }
  78.  
  79. for (; size.height--; src_ += sstep, dst_ += dstep) {
  80. for (i = 0; i < limit; i++) {
  81. j = tab[i];
  82. uchar t0 = src_[i], t1 = src_[j];
  83. dst_[i] = t1; dst_[j] = t0;
  84. }
  85. }
  86.  
  87. return 0;
  88. }
  89.  
  90. template<typename _Tp, int chs>
  91. static int flipVert(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)
  92. {
  93. const uchar* src0 = src.ptr();
  94. uchar* dst0 = dst.ptr();
  95. Size size = src.size();
  96. size_t sstep = src.step;
  97. size_t dstep = dst.step;
  98. size_t esz = sizeof(_Tp) * chs;
  99. const uchar* src1 = src0 + (size.height - 1)*sstep;
  100. uchar* dst1 = dst0 + (size.height - 1)*dstep;
  101. size.width *= (int)esz;
  102.  
  103. for (int y = 0; y < (size.height + 1) / 2; y++, src0 += sstep, src1 -= sstep, dst0 += dstep, dst1 -= dstep) {
  104. int i = 0;
  105. if (((size_t)src0 | (size_t)dst0 | (size_t)src1 | (size_t)dst1) % sizeof(int) == 0) {
  106. for (; i <= size.width - 16; i += 16) {
  107. int t0 = ((int*)(src0 + i))[0];
  108. int t1 = ((int*)(src1 + i))[0];
  109.  
  110. ((int*)(dst0 + i))[0] = t1;
  111. ((int*)(dst1 + i))[0] = t0;
  112.  
  113. t0 = ((int*)(src0 + i))[1];
  114. t1 = ((int*)(src1 + i))[1];
  115.  
  116. ((int*)(dst0 + i))[1] = t1;
  117. ((int*)(dst1 + i))[1] = t0;
  118.  
  119. t0 = ((int*)(src0 + i))[2];
  120. t1 = ((int*)(src1 + i))[2];
  121.  
  122. ((int*)(dst0 + i))[2] = t1;
  123. ((int*)(dst1 + i))[2] = t0;
  124.  
  125. t0 = ((int*)(src0 + i))[3];
  126. t1 = ((int*)(src1 + i))[3];
  127.  
  128. ((int*)(dst0 + i))[3] = t1;
  129. ((int*)(dst1 + i))[3] = t0;
  130. }
  131.  
  132. for (; i <= size.width - 4; i += 4) {
  133. int t0 = ((int*)(src0 + i))[0];
  134. int t1 = ((int*)(src1 + i))[0];
  135.  
  136. ((int*)(dst0 + i))[0] = t1;
  137. ((int*)(dst1 + i))[0] = t0;
  138. }
  139. }
  140.  
  141. for (; i < size.width; i++) {
  142. uchar t0 = src0[i];
  143. uchar t1 = src1[i];
  144.  
  145. dst0[i] = t1;
  146. dst1[i] = t0;
  147. }
  148. }
  149.  
  150. return 0;
  151. }
  152.  
  153. } // namespace fbc
  154.  
  155. #endif // FBC_CV_FLIP_HPP_

测试代码test_flip.cpp:

  1. #include "test_flip.hpp"
  2. #include <assert.h>
  3. #include <iostream>
  4. #include <string>
  5.  
  6. #include <flip.hpp>
  7. #include <opencv2/opencv.hpp>
  8.  
  9. int test_flip_uchar()
  10. {
  11. cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/1.jpg", 1);
  12. if (!matSrc.data) {
  13. std::cout << "read image fail" << std::endl;
  14. return -1;
  15. }
  16.  
  17. int width = matSrc.cols;
  18. int height = matSrc.rows;
  19.  
  20. int flipCode[3] {-1, 0, 1}; // both axes, x axis, y axis
  21.  
  22. for (int i = 0; i < 3; i++) {
  23. fbc::Mat_<uchar, 3> mat1(height, width, matSrc.data);
  24. fbc::Mat_<uchar, 3> mat2(height, width);
  25. fbc::flip(mat1, mat2, flipCode[i]);
  26.  
  27. cv::Mat mat1_(height, width, CV_8UC3, matSrc.data);
  28. cv::Mat mat2_;
  29. cv::flip(mat1_, mat2_, flipCode[i]);
  30.  
  31. assert(mat2.rows == mat2_.rows && mat2.cols == mat2_.cols && mat2.step == mat2_.step);
  32. for (int y = 0; y < mat2.rows; y++) {
  33. const fbc::uchar* p1 = mat2.ptr(y);
  34. const uchar* p2 = mat2_.ptr(y);
  35.  
  36. for (int x = 0; x < mat2.step; x++) {
  37. assert(p1[x] == p2[x]);
  38. }
  39. }
  40.  
  41. std::string name = std::to_string(i);
  42. std::string file_path = "E:/GitCode/OpenCV_Test/test_images/";
  43. std::string name_fbc = file_path + "flip_fbc_" + name + ".jpg";
  44. std::string name_cv = file_path + "flip_cv_" + name + ".jpg";
  45. cv::Mat matSave(height, width, CV_8UC3, mat2.data);
  46. cv::imwrite(name_fbc, matSave);
  47. cv::imwrite(name_cv, mat2_);
  48. }
  49.  
  50. return 0;
  51. }
  52.  
  53. int test_flip_float()
  54. {
  55. cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/1.jpg", 1);
  56. if (!matSrc.data) {
  57. std::cout << "read image fail" << std::endl;
  58. return -1;
  59. }
  60. cv::cvtColor(matSrc, matSrc, CV_BGR2GRAY);
  61. matSrc.convertTo(matSrc, CV_32FC1);
  62.  
  63. int width = matSrc.cols;
  64. int height = matSrc.rows;
  65.  
  66. int flipCode[3] {-1, 0, 1}; // both axes, x axis, y axis
  67.  
  68. for (int i = 0; i < 3; i++) {
  69. fbc::Mat_<float, 1> mat1(height, width, matSrc.data);
  70. fbc::Mat_<float, 1> mat2(height, width);
  71. fbc::flip(mat1, mat2, flipCode[i]);
  72.  
  73. cv::Mat mat1_(height, width, CV_32FC1, matSrc.data);
  74. cv::Mat mat2_;
  75. cv::flip(mat1_, mat2_, flipCode[i]);
  76.  
  77. assert(mat2.rows == mat2_.rows && mat2.cols == mat2_.cols && mat2.step == mat2_.step);
  78. for (int y = 0; y < mat2.rows; y++) {
  79. const fbc::uchar* p1 = mat2.ptr(y);
  80. const uchar* p2 = mat2_.ptr(y);
  81.  
  82. for (int x = 0; x < mat2.step; x++) {
  83. assert(p1[x] == p2[x]);
  84. }
  85. }
  86. }
  87.  
  88. return 0;
  89. }

GitHubhttps://github.com/fengbingchun/OpenCV_Test

OpenCV代码提取:flip函数的实现的更多相关文章

  1. OpenCV代码提取:transpose函数的实现

    OpenCV中的transpose函数实现图像转置,公式为: 目前fbc_cv库中也实现了transpose函数,支持多通道,uchar和float两种数据类型,经测试,与OpenCV3.1结果完全一 ...

  2. OpenCV代码提取:dft函数的实现

    The Fourier Transform will decompose an image into its sinus and cosines components. In other words, ...

  3. OpenCV代码提取: threshold函数的实现

    threshold algorithm: The simplest image segmentation method. All thresholding algorithms take a sour ...

  4. OpenCV代码提取:遍历指定目录下指定文件的实现

    前言 OpenCV 3.1之前的版本,在contrib目录下有提供遍历文件的函数,用起来比较方便.但是在最新的OpenCV 3.1版本给去除掉了.为了以后使用方便,这里将OpenCV 2.4.9中相关 ...

  5. opencv: flip函数的使用;

    flip函数用于图像翻转,比较方便.在opencv中有几种形式: C++: void flip(InputArray src, OutputArray dst, int flipCode) Pytho ...

  6. OpenCV中的绘图函数-OpenCV步步精深

    OpenCV 中的绘图函数 画线 首先要为画的线创造出环境,就要生成一个空的黑底图像 img=np.zeros((512,512,3), np.uint8) 这是黑色的底,我们的画布,我把窗口名叫做i ...

  7. 基础学习笔记之opencv(24):imwrite函数的使用

    http://www.cnblogs.com/tornadomeet/archive/2012/12/26/2834336.html 前言 OpenCV中保存图片的函数在c++版本中变成了imwrit ...

  8. (转)Uri详解之——Uri结构与代码提取

    前言:依然没有前言…… 相关博客:1.<Uri详解之——Uri结构与代码提取>2.<Uri详解之二——通过自定义Uri外部启动APP与Notification启动> 上几篇给大 ...

  9. Uri详解之——Uri结构与代码提取

    目录(?)[+] 前言:依然没有前言…… 相关博客:1.<Uri详解之——Uri结构与代码提取>2.<Uri详解之二——通过自定义Uri外部启动APP与Notification启动& ...

随机推荐

  1. Git的认识与学习

    第一部分:我的git地址是https://github.com/monkeyDyang 第二部分:我对git的认识 Git是一种良好的.支持分支管理的代码管理方式,能很好地解决团队之间协作的问题.每个 ...

  2. 108. Convert Sorted Array to Binary Search Tree (building tree with resursion)

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST. Fo ...

  3. python接口测试-项目实践(一) 测试需求与测试思路

    测试需求: 第三方系统提供了3个接口,需要测试前端显示的字符串里的对应数据与接口数据是否一致. 测试分层: 开发人员的设计:每周从接口取一次数据,拼接完成后保存到数据库.再从数据库取数提供接口给前端开 ...

  4. python解析HTML之:PyQuery库的介绍与使用

    本篇大部分转载于https://www.jianshu.com/p/c07f7cd1b548 先放自已自己解析techweb一个网站图片的代码 from pyquery import PyQuery ...

  5. 【[SDOI2009]晨跑】

    板子 题意就是每个点只能经过一次 所以非常显然拆点,除去\(1,n\)每个点\(i\)向\(i'\)连一条容量为\(1\)费用为\(0\)的边 剩下的边按照输入给出的建就好了 代码 #include& ...

  6. GetClassLoader和GetCallerClass的使用

    GetClassLoader是JAVA中用来得到ClassLoader的 JAVA中有以下几种ClassLoader. 1.  Bootstrap ClassLoader - GetClassLoad ...

  7. 【luogu P1962 斐波那契数列】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1962 给你篇dalao的blog自己看吧,把矩阵快速幂的板子一改就OK #include <algor ...

  8. 运行Python

    安装好python环境,在Windows系统下运行cmd命令行,是windows提供的命令行模式. 在命令行下,可以执行python进入Python交互式环境,也可以执行python hello.py ...

  9. 协议类接口 - I2C

    一.12c总线概述 I2C( Inter-Integrated Circuit,又称IIC)总线是一种串行总线,用 于连接微控制器及其外围设备,硬件图非常简单:一条串行数据线(SDA),一条串行时钟线 ...

  10. c++cmb

    #include<windows.h> #include<bits/stdc++.h> using namespace std; ]; int main() { printf( ...