精华内容
下载资源
问答
  • 今天小编就为大家分享一篇关于Opencv-Python图像透视变换cv2.warpPerspective的示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
  • 本文详细介绍了OpenCV-Python相关的透视变换处理函数getPerspectiveTransform 和warpPerspective的语法及参数含义。

    ☞ ░ 老猿Python博文目录:https://blog.csdn.net/LaoYuanPython

    一、getPerspectiveTransform 函数

    getPerspectiveTransform函数根据源图像和目标图像上的四对点坐标来计算从原图像透视变换到目标头像的透视变换矩阵。

    1.1、调用语法

    getPerspectiveTransform(src, dst, solveMethod=None)

    1.2、语法说明

    • src:源图像上四个点的坐标构成的矩阵,要求其中任意三点不共线
    • dst:目标图像上四个点的坐标构成的矩阵,要求其中任意三个点不共线,且每个点与src的对应点对应
    • solveMethod:矩阵分解方法,传递给cv2.solve(DecompTypes) 求解线性方程组或解决最小二乘问题,默认值为None,表示使用DECOMP_LU。
      solveMethod对应取值及含义如下
      在这里插入图片描述
      注:矩阵分解 ,英文称为matrix decomposition或matrix factorization是将矩阵拆解为数个矩阵的乘积,可分为三角分解、满秩分解、Jordan分解和SVD(奇异值)分解等,常见的有三种:1)三角分解法 (Triangular Factorization),2)QR 分解法 (QR Factorization),3)奇异值分解法 (Singular Value Decompostion)。 在图像处理方面,矩阵分解被广泛用于降维(压缩)、去噪、特征提取、数字水印等,是十分重要的数学工具,其中特征分解(谱分解)和奇异值分解是两种常用方法。


      老猿对矩阵分解目前也只知道概念,参阅资料《浅谈矩阵分解以及应用》,相关具体知识并不熟悉,对此有兴趣的可以进一步查阅相关资料。
    • 返回值:为一3*3的透视变换矩阵

    二、warpPerspective 函数

    warpPerspective函数用于对输入图像进行透视变换,透视变换使用如下公式来计算结果图像和输入图像的对应关系:
    在这里插入图片描述
    其中Mij代表透视变换矩阵的9个元素。

    2.1、调用语法

    warpPerspective(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)

    2.2、语法说明

    • src:输入图像矩阵
    • M:3*3的透视变换矩阵,可以通过getPerspectiveTransform等函数获取
    • dsize:结果图像大小,为宽和高的二元组
    • dst:输出结果图像,可以省略,结果图像会作为函数处理结果输出
    • flags:可选参数,插值方法的组合(int 类型),默认值 INTER_LINEAR,本函数官方材料说明取值为INTER_LINEAR 或 INTER_NEAREST与 WARP_INVERSE_MAP的组合,但老猿测试其他标志也是支持的,具体取值及含义请参考《https://blog.csdn.net/LaoYuanPython/article/details/111771138 OpenCV-Python图像处理:插值方法及使用resize函数进行图像缩放》的介绍
    • borderMode:可选参数,边界像素模式(int 类型),默认值 BORDER_CONSTANT,本函数官方材料说明取值为BORDER_CONSTANT 或 BORDER_REPLICATE,实际上所有取值类型都支持,包括形态变换中不支持的BORDER_WRAP、BORDER_TRANSPARENT都能支持,并且不同取值有不同效果,具体取值及含义请参考《https://blog.csdn.net/LaoYuanPython/article/details/109441709 OpenCV-Python图像处理:腐蚀和膨胀原理及erode、dilate函数介绍》的介绍
    • borderValue:可选参数,边界填充值,当borderMode为cv2.BORDER_CONSTANT时使用,默认值为None;
    • 返回值:为透视变换后的结果图像矩阵,最后的结果矩阵每个像素与原图像像素的对应关系为:
      在这里插入图片描述

    如果flags标记设置了WARP_INVERSE_MAP标记,首先使用invertAffineTransform对变换矩阵进行反转即求其逆矩阵,然后将其放入上面的公式中,而不是将M直接放入

    • 返回值:透视变换后的结果图像

    三、小结

    本文详细介绍了OpenCV-Python相关的透视变换处理函数getPerspectiveTransform 和warpPerspective的语法及参数含义。

    更多透视变换概念、原理及案例的介绍请参考《https://blog.csdn.net/LaoYuanPython/article/details/114003964 OpenCV-Python图像处理:透视变换概念、矩阵及实现案例详解》的介绍。

    要理解投影变换的原理最好能理解仿射变换的原理,关于仿射变换可参考老猿的仿射变换相关系列博文。

    仿射变换博文传送门(带星号的为付费专栏文章):
    1. *图像仿射变换原理1:齐次坐标来龙去脉详解
    2. *图像仿射变换原理2:矩阵变换、线性变换和图像线性变换矩阵
    3. *图像仿射变换原理3:仿射变换类型及变换矩阵详解
    4. *图像仿射变换原理4:组合变换及对应变换矩阵
    5. *图像仿射变换原理5:组合变换矩阵的OpenCV-Python实现
    6. OpenCV-Python图像处理:仿射变换详解及案例
    7. OpenCV-Python仿射变换开发中遇到的坑
    8. openCV仿射变换:getAffineTransform的案例
    9. 为什么称图像旋转、错切、缩放变换是线性变换?
    10. 图像仿射变换:绕点旋转和指定直线依赖轴shear错切变换矩阵
    11. 图像仿射变换shear怎么翻译?剪切、错切、推移哪个译词好?
    12. 仿射变换原理和其OpenCV-Python实现知识汇总

    更多图像处理的介绍请参考专栏《OpenCV-Python图形图像处理 https://blog.csdn.net/laoyuanpython/category_9979286.html》和《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》相关文章。

    更多图像处理的数学基础知识请参考专栏《人工智能数学基础 https://blog.csdn.net/laoyuanpython/category_10382948.html

    写博不易,敬请支持:

    如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

    如果对文章内容存在疑问,可以在博客评论区留言,或关注:老猿Python 微信公号发消息咨询。

    关于老猿的付费专栏

    1. 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;
    2. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;
    3. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python初学者疑难问题集专栏目录
    4. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10762553.html Python爬虫入门 》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取CSDN文章信息、博主信息、给文章点赞、评论等实战内容。

    前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。

    对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。

    如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

    跟老猿学Python!

    ☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython

    展开全文
  • OpenCV代码提取 warpPerspective函数的实现
                   

     For perspective transformation, you need a 3x3 transformation matrix. Straight lines will remain straight even after the transformation. To find this transformation matrix, you need 4 points on the input image and corresponding points on the output image. Among these 4 points,3 of them should not be collinear.

     透视变换(perspective transformation)是将图像投影到一个新的视平面,也称为投影映射。

             公式:dst(x,y) = src((M11x+M12y+M13)/(M31x+M32y+M33), (M21x+M22y+M23)/(M31x+M32y+M33))

     仿射变换与透视变换的区别:

     (1)、仿射变换,它可以将矩形转换成平行四边形,也可以将矩形的边压扁但必须保持边是平行的,也可以将矩形旋转或者按比例缩放。透视变换除了能够处理仿射变换的操作外,还可以将矩形转换成梯形。即仿射变换后还是平行四边形,透视变换后是四边形。因此可以说仿射变换是透视变换的一个子集。

             (2)、在OpenCV中,基于2*3矩阵进行的变换,是图像的仿射变换;基于3*3矩阵进行的变换,是图像的透视变换或者单应性映射。图像透视变换多用于图像校正

             下图是截取的《Learning OpenCV》一书中的插图:


     目前支持uchar和float两种类型,经测试,与OpenCV3.1结果完全一致。

     实现代码warpPerspective.hpp:

    // fbc_cv is free software and uses the same licence as OpenCV// Email: fengbingchun@163.com#ifndef FBC_CV_WARP_PERSPECTIVE_HPP_#define FBC_CV_WARP_PERSPECTIVE_HPP_/* reference: include/opencv2/imgproc.hpp              modules/imgproc/src/imgwarp.cpp*/#include <typeinfo>#include "core/mat.hpp"#include "core/invert.hpp"#include "imgproc.hpp"#include "remap.hpp"namespace fbc {// Calculates a perspective transform from four pairs of the corresponding pointsFBC_EXPORTS int getPerspectiveTransform(const Point2f src1[], const Point2f src2[], Mat_<double, 1>& dst);// Applies a perspective transformation to an image// The function cannot operate in - place// support type: uchar/float/* \f[\texttt{ dst } (x, y) = \texttt{ src } \left(\frac{ M_{ 11 } x + M_{ 12 } y + M_{ 13 } }{M_{ 31 } x + M_{ 32 } y + M_{ 33 }}, \frac{ M_{ 21 } x + M_{ 22 } y + M_{ 23 } }{M_{ 31 } x + M_{ 32 } y + M_{ 33 }} \right)\f]*/template<typename _Tp1, typename _Tp2, int chs1, int chs2>int warpPerspective(const Mat_<_Tp1, chs1>& src, Mat_<_Tp1, chs1>& dst, const Mat_<_Tp2, chs2>& M_, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, const Scalar& borderValue = Scalar()){ FBC_Assert(src.data != NULL && dst.data != NULL && M_.data != NULL); FBC_Assert(src.cols > 0 && src.rows > 0 && dst.cols > 0 && dst.rows > 0); FBC_Assert(src.data != dst.data); FBC_Assert(typeid(double).name() == typeid(_Tp2).name() && M_.rows == 3 && M_.cols == 3); FBC_Assert((typeid(uchar).name() == typeid(_Tp1).name()) || (typeid(float).name() == typeid(_Tp1).name())); // uchar/float double M[9]; Mat_<double, 1> matM(3, 3, M); int interpolation = flags & INTER_MAX; if (interpolation == INTER_AREA)  interpolation = INTER_LINEAR; if (!(flags & WARP_INVERSE_MAP))  invert(M_, matM); Range range(0, dst.rows)const int BLOCK_SZ = 32short XY[BLOCK_SZ*BLOCK_SZ * 2], A[BLOCK_SZ*BLOCK_SZ]; int x, y, x1, y1, width = dst.cols, height = dst.rows; int bh0 = std::min(BLOCK_SZ / 2, height); int bw0 = std::min(BLOCK_SZ*BLOCK_SZ / bh0, width); bh0 = std::min(BLOCK_SZ*BLOCK_SZ / bw0, height); for (y = range.start; y < range.end; y += bh0) {  for (x = 0; x < width; x += bw0) {   int bw = std::min(bw0, width - x);   int bh = std::min(bh0, range.end - y); // height   Mat_<short, 2> _XY(bh, bw, XY), matA;   Mat_<_Tp1, chs1> dpart;   dst.getROI(dpart, Rect(x, y, bw, bh));   for (y1 = 0; y1 < bh; y1++) {    short* xy = XY + y1*bw * 2;    double X0 = M[0] * x + M[1] * (y + y1) + M[2];    double Y0 = M[3] * x + M[4] * (y + y1) + M[5];    double W0 = M[6] * x + M[7] * (y + y1) + M[8];    if (interpolation == INTER_NEAREST) {     x1 = 0;     for (; x1 < bw; x1++) {      double W = W0 + M[6] * x1;      W = W ? 1. / W : 0;      double fX = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * x1)*W));      double fY = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * x1)*W));      int X = saturate_cast<int>(fX);      int Y = saturate_cast<int>(fY);      xy[x1 * 2] = saturate_cast<short>(X);      xy[x1 * 2 + 1] = saturate_cast<short>(Y);     }    } else {     short* alpha = A + y1*bw;     x1 = 0;     for (; x1 < bw; x1++) {      double W = W0 + M[6] * x1;      W = W ? INTER_TAB_SIZE / W : 0;      double fX = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * x1)*W));      double fY = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * x1)*W));      int X = saturate_cast<int>(fX);      int Y = saturate_cast<int>(fY);      xy[x1 * 2] = saturate_cast<short>(X >> INTER_BITS);      xy[x1 * 2 + 1] = saturate_cast<short>(Y >> INTER_BITS);      alpha[x1] = (short)((Y & (INTER_TAB_SIZE - 1))*INTER_TAB_SIZE + (X & (INTER_TAB_SIZE - 1)));     }    }   }   if (interpolation == INTER_NEAREST) {    remap(src, dpart, _XY, Mat_<float, 1>(), interpolation, borderMode, borderValue);   } else {    Mat_<ushort, 1> _matA(bh, bw, A);    remap(src, dpart, _XY, _matA, interpolation, borderMode, borderValue);   }  } } return 0;}} // namespace fbc#endif // FBC_CV_WARP_PERSPECTIVE_HPP_
     测试代码test_warpPerspective.cpp:

    #include "test_warpPerspective.hpp"#include <assert.h>#include <opencv2/opencv.hpp>#include <warpPerspective.hpp>int test_getPerspectiveTransform(){ cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1); if (!matSrc.data) {  std::cout << "read image fail" << std::endl;  return -1; } fbc::Point2f src_vertices[4], dst_vertices[4]; src_vertices[0] = fbc::Point2f(0, 0); src_vertices[1] = fbc::Point2f(matSrc.cols - 5, 0); src_vertices[2] = fbc::Point2f(matSrc.cols - 10, matSrc.rows - 1); src_vertices[3] = fbc::Point2f(8, matSrc.rows - 13); dst_vertices[0] = fbc::Point2f(17, 21); dst_vertices[1] = fbc::Point2f(matSrc.cols - 23, 19); dst_vertices[2] = fbc::Point2f(matSrc.cols / 2 + 5, matSrc.rows / 3 + 7); dst_vertices[3] = fbc::Point2f(55, matSrc.rows / 5 + 33); fbc::Mat_<double, 1> warpMatrix(3, 3); fbc::getPerspectiveTransform(src_vertices, dst_vertices, warpMatrix); cv::Point2f src_vertices_[4], dst_vertices_[4]; src_vertices_[0] = cv::Point2f(0, 0); src_vertices_[1] = cv::Point2f(matSrc.cols - 5, 0); src_vertices_[2] = cv::Point2f(matSrc.cols - 10, matSrc.rows - 1); src_vertices_[3] = cv::Point2f(8, matSrc.rows - 13); dst_vertices_[0] = cv::Point2f(17, 21); dst_vertices_[1] = cv::Point2f(matSrc.cols - 23, 19); dst_vertices_[2] = cv::Point2f(matSrc.cols / 2 + 5, matSrc.rows / 3 + 7); dst_vertices_[3] = cv::Point2f(55, matSrc.rows / 5 + 33); cv::Mat warpMatrix_ = cv::getPerspectiveTransform(src_vertices_, dst_vertices_); assert(warpMatrix.cols == warpMatrix_.cols && warpMatrix.rows == warpMatrix_.rows); assert(warpMatrix.step == warpMatrix_.step); for (int y = 0; y < warpMatrix.rows; y++) {  const fbc::uchar* p = warpMatrix.ptr(y);  const uchar* p_ = warpMatrix_.ptr(y);  for (int x = 0; x < warpMatrix.step; x++) {   assert(p[x] == p_[x]);  } } return 0;}int test_warpPerspective_uchar(){ cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1); if (!matSrc.data) {  std::cout << "read image fail" << std::endl;  return -1; } for (int interpolation = 0; interpolation < 5; interpolation++) {  fbc::Point2f src_vertices[4], dst_vertices[4];  src_vertices[0] = fbc::Point2f(0, 0);  src_vertices[1] = fbc::Point2f(matSrc.cols - 5, 0);  src_vertices[2] = fbc::Point2f(matSrc.cols - 10, matSrc.rows - 1);  src_vertices[3] = fbc::Point2f(8, matSrc.rows - 13);  dst_vertices[0] = fbc::Point2f(17, 21);  dst_vertices[1] = fbc::Point2f(matSrc.cols - 23, 19);  dst_vertices[2] = fbc::Point2f(matSrc.cols / 2 + 5, matSrc.rows / 3 + 7);  dst_vertices[3] = fbc::Point2f(55, matSrc.rows / 5 + 33);  fbc::Mat_<double, 1> warpMatrix(3, 3);  fbc::getPerspectiveTransform(src_vertices, dst_vertices, warpMatrix);  fbc::Mat_<uchar, 3> mat(matSrc.rows, matSrc.cols, matSrc.data);  fbc::Mat_<uchar, 3> warp_dst;  warp_dst.zeros(mat.rows, mat.cols);  fbc::warpPerspective(mat, warp_dst, warpMatrix, interpolation);  cv::Point2f src_vertices_[4], dst_vertices_[4];  src_vertices_[0] = cv::Point2f(0, 0);  src_vertices_[1] = cv::Point2f(matSrc.cols - 5, 0);  src_vertices_[2] = cv::Point2f(matSrc.cols - 10, matSrc.rows - 1);  src_vertices_[3] = cv::Point2f(8, matSrc.rows - 13);  dst_vertices_[0] = cv::Point2f(17, 21);  dst_vertices_[1] = cv::Point2f(matSrc.cols - 23, 19);  dst_vertices_[2] = cv::Point2f(matSrc.cols / 2 + 5, matSrc.rows / 3 + 7);  dst_vertices_[3] = cv::Point2f(55, matSrc.rows / 5 + 33);  // Get the Perspective Transform  cv::Mat warpMatrix_ = cv::getPerspectiveTransform(src_vertices_, dst_vertices_);  // Set the dst image the same type and size as src  cv::Mat warp_dst_ = cv::Mat::zeros(matSrc.rows, matSrc.cols, matSrc.type());  cv::Mat mat_;  matSrc.copyTo(mat_);  // Apply the Affine Transform just found to the src image  cv::warpPerspective(mat_, warp_dst_, warpMatrix_, warp_dst_.size(), interpolation);  assert(warp_dst.cols == warp_dst_.cols && warp_dst.rows == warp_dst_.rows);  assert(warp_dst.step == warp_dst_.step);  for (int y = 0; y < warp_dst.rows; y++) {   const fbc::uchar* p = warp_dst.ptr(y);   const uchar* p_ = warp_dst_.ptr(y);   for (int x = 0; x < warp_dst.step; x++) {    assert(p[x] == p_[x]);   }  } } return 0;}int test_warpPerspective_float(){ cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1); if (!matSrc.data) {  std::cout << "read image fail" << std::endl;  return -1; } cv::cvtColor(matSrc, matSrc, CV_BGR2GRAY); matSrc.convertTo(matSrc, CV_32FC1); for (int interpolation = 0; interpolation < 5; interpolation++) {  fbc::Point2f src_vertices[4], dst_vertices[4];  src_vertices[0] = fbc::Point2f(0, 0);  src_vertices[1] = fbc::Point2f(matSrc.cols - 5, 0);  src_vertices[2] = fbc::Point2f(matSrc.cols - 10, matSrc.rows - 1);  src_vertices[3] = fbc::Point2f(8, matSrc.rows - 13);  dst_vertices[0] = fbc::Point2f(17, 21);  dst_vertices[1] = fbc::Point2f(matSrc.cols - 23, 19);  dst_vertices[2] = fbc::Point2f(matSrc.cols / 2 + 5, matSrc.rows / 3 + 7);  dst_vertices[3] = fbc::Point2f(55, matSrc.rows / 5 + 33);  fbc::Mat_<double, 1> warpMatrix(3, 3);  fbc::getPerspectiveTransform(src_vertices, dst_vertices, warpMatrix);  fbc::Mat_<float, 1> mat(matSrc.rows, matSrc.cols, matSrc.data);  fbc::Mat_<float, 1> warp_dst;  warp_dst.zeros(mat.rows, mat.cols);  fbc::warpPerspective(mat, warp_dst, warpMatrix, interpolation);  cv::Point2f src_vertices_[4], dst_vertices_[4];  src_vertices_[0] = cv::Point2f(0, 0);  src_vertices_[1] = cv::Point2f(matSrc.cols - 5, 0);  src_vertices_[2] = cv::Point2f(matSrc.cols - 10, matSrc.rows - 1);  src_vertices_[3] = cv::Point2f(8, matSrc.rows - 13);  dst_vertices_[0] = cv::Point2f(17, 21);  dst_vertices_[1] = cv::Point2f(matSrc.cols - 23, 19);  dst_vertices_[2] = cv::Point2f(matSrc.cols / 2 + 5, matSrc.rows / 3 + 7);  dst_vertices_[3] = cv::Point2f(55, matSrc.rows / 5 + 33);  // Get the Perspective Transform  cv::Mat warpMatrix_ = cv::getPerspectiveTransform(src_vertices_, dst_vertices_);  // Set the dst image the same type and size as src  cv::Mat warp_dst_ = cv::Mat::zeros(matSrc.rows, matSrc.cols, matSrc.type());  cv::Mat mat_;  matSrc.copyTo(mat_);  // Apply the Affine Transform just found to the src image  cv::warpPerspective(mat_, warp_dst_, warpMatrix_, warp_dst_.size(), interpolation);  assert(warp_dst.cols == warp_dst_.cols && warp_dst.rows == warp_dst_.rows);  assert(warp_dst.step == warp_dst_.step);  for (int y = 0; y < warp_dst.rows; y++) {   const fbc::uchar* p = warp_dst.ptr(y);   const uchar* p_ = warp_dst_.ptr(y);   for (int x = 0; x < warp_dst.step; x++) {    assert(p[x] == p_[x]);   }  } } return 0;}

     GitHub: https://github.com/fengbingchun/OpenCV_Test

               

    再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

    展开全文
  • warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) -> dst @brief Applies a perspective transformation to an image. The function warpPerspective transforms the ...

    warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) -> dst

    @brief Applies a perspective transformation to an image.

    The function warpPerspective transforms the source image using the specified matrix:

    \f[\texttt{dst} (x,y) = \texttt{src} \left ( \frac{M_{11} x + M_{12} y + M_{13}}{M_{31} x + M_{32} y + M_{33}} ,
         \frac{M_{21} x + M_{22} y + M_{23}}{M_{31} x + M_{32} y + M_{33}} \right )\f]

    when the flag #WARP_INVERSE_MAP is set. Otherwise, the transformation is first inverted with invert and then put in the formula above instead of M. The function cannot operate in-place.

    @param src input image.

    @param dst output image that has the size dsize and the same type as src .

    @param M \f$3\times 3\f$ transformation matrix.

    @param dsize size of the output image.

    @param flags combination of interpolation methods (#INTER_LINEAR or #INTER_NEAREST) and the optional flag #WARP_INVERSE_MAP, that sets M as the inverse transformation ( \f$\texttt{dst}\rightarrow\texttt{src}\f$ ).

    @param borderMode pixel extrapolation method (#BORDER_CONSTANT or #BORDER_REPLICATE).

    @param borderValue value used in case of a constant border; by default, it equals 0.

    @sa warpAffine, resize, remap, getRectSubPix, perspectiveTransform

    warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) -> dst

    @brief 对图像应用透视变换。

    函数 warpPerspective 使用指定的矩阵转换源图像:

    当flag #WARP_INVERSE_MAP 被设置时。

    否则,变换先用invert取反,然后代入上面的公式而不是M。该函数不能就地操作。

    @param src 输入图像。

    @param dst 输出图像,其大小为 dsize 且类型与 src 相同。

    @param M \f$3\times 3\f$ 变换矩阵。

    @param dsize 输出图像的大小。

    @param 标记插值方法(#INTER_LINEAR 或 #INTER_NEAREST)和可选标记 #WARP_INVERSE_MAP 的组合,将 M 设置为逆变换。

    @param borderMode 像素外推方法(#BORDER_CONSTANT 或 #BORDER_REPLICATE)。

    @param borderValue 用于恒定边框的值;默认情况下,它等于 0。

    @sa warpAffine、调整大小、重新映射、getRectSubPix、perspectiveTransform

    函数原理:


    透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。通用的变换公式为:


    u,v是原始图片左边,对应得到变换后的图片坐标x,y,其中
    变换矩阵可以拆成4部分,表示线性变换,比如scaling,shearing和ratotion。用于平移,产生透视变换。所以可以理解成仿射等是透视变换的特殊形式。经过透视变换之后的图片通常不是平行四边形(除非映射视平面和原来平面平行的情况)。
    重写之前的变换公式可以得到:

     

    所以,已知变换对应的几个点就可以求取变换公式。反之,特定的变换公式也能新的变换后的图片。简单的看一个正方形到四边形的变换:
    变换的4组对应点可以表示成:

    根据变换公式得到:


    定义几个辅助变量:

     

    都为0时变换平面与原来是平行的,可以得到:

    不为0时,得到:

    求解出的变换矩阵就可以将一个正方形变换到四边形。反之,四边形变换到正方形也是一样的。于是,我们通过两次变换:四边形变换到正方形+正方形变换到四边形就可以将任意一个四边形变换到另一个四边形。

     

     

     参考链接:

    warpPerspective函数_qq_2773878606的博客-CSDN博客_warpperspective

    展开全文
  • Homography和warpPerspective

    2021-03-23 15:36:48
    平面射影变换是关于其次3维...两张图间的H映射关系就可以表示成 参考文献 Opencv日常之Homography 透视变换warpPerspective 使用 OpenCV 对图像中的区域进行透视变换 【图像处理】透视变换 Perspective Transformation

    平面射影变换是关于其次3维矢量的一种线性变换,可以使用一个非奇异的3×3矩阵H表示,X′=HX,射影变换也叫做单应(Homography)。计算出两幅图像之间的单应矩阵H,那么应用这个关系可以将一个视图中的所有点变换到另一个视图中。
    因为Homography是一个3*3矩阵,所以可以写成
    H = [ h 00 h 01 h 02 h 10 h 11 h 12 h 20 h 21 h 22 ] H = \begin{bmatrix} h00&h01 & h02 \\ h10& h11 & h12\\ h20& h21& h22 \end{bmatrix} H=h00h10h20h01h11h21h02h12h22
    两张图间的H映射关系就可以表示成
    在这里插入图片描述
    参考文献 Opencv日常之Homography

    透视变换warpPerspective

    使用 OpenCV 对图像中的区域进行透视变换

    【图像处理】透视变换 Perspective Transformation

    展开全文
  • 我通过使用getHomography和warpPerspective将图像从前视角更改为出价视图.它的工作原理是图像扭曲到所需的视角,但裁剪关闭.它将扭曲的图像移动到图像框之外.我假设原因是因为操作导致负坐标.我已经计算了手动计算...
  • 我会: >角落里面我要映射扭曲的图像 >单应矩阵,用于映射徽标图像的变换 进入最终图像内部的徽标图像(使用OpenCV warpPerspective),像这样: [[ 2.59952324e+00, 3.33170976e-01, -2.17014066e+02], [ 8.64133587e-...
  • Python+OpenCV 图像透视变换 warpPerspective函数1、函数介绍2、代码实例3、实现效果 1、函数介绍 warpPerspective():对图像进行透视变换。简单来说,就是有这么一副图像,它的拍摄视角不是从正面拍摄的,而是带有...
  • OpenCV代码提取:warpPerspective函数的实现

    万次阅读 热门讨论 2016-07-23 14:23:41
    OpenCV代码提取:warpPerspective函数的实现
  • cv2.warpPerspective API小记

    千次阅读 2021-03-11 17:35:37
    cv2.warpPerspective(src,M,dsize=(width,height),flags=INTER_LINEAR,borderMode=BORDER_CONSTANT,borderValue=None) 不设置WARP_INVERSE_MAP时,使用MMM进行warp;设置WARP_INVERSE_MAP时,使用M−1M^{-1}M−1进行...
  • 本节介绍了使用OpenCV-Python的getPerspectiveTransform函数,通过4个源图像的点映射到目标图像的四角对应点得到投影变换的变换矩阵,然后使用warpPerspective进行投影变换,可以对选择4个点进行投影变换的步骤有...
  • 2D图像几何基元 一般的,表示一个2d几何基元只用两个维度(比如x,y)就可以表示了,但是在计算机视觉研究中,为了统一对2d几何基元的操作(后面讲到的仿射,透射变换),一般会以增广矢量的方式表示几何基元。...
  • 参数 solveMethod 传递给cv::solve(#DecompTypes)的计算方法,默认是DECOMP_LU 参考 findHomography, warpPerspective, perspectiveTransform 二、透视变换函数warpPerspective 功能描述 通过透视矩阵把透视变换...
  • cv2.warpPerspective(src, M, dsize=(cols, rows)) 参数: src: 原图 M: 一个3x3的变换矩阵 dsize: 输出图像的尺寸大小, 先指定(第一个参数是)col,再指定(第二个参数是)row 那么转换矩阵怎么得到呢?可以通过...
  • 1、什么是Homography 在图1中有两张书的平面图,两张图分别有四个相对位置相同的点,Homography就是一个变换(3*3矩阵),将一张图中的点映射到另一张图中对应的点。 两张图间的H映射关系就可以表示成: ...
  • python的cv2.warpAffine()和cv2.warpPerspective()解析对比

    万次阅读 多人点赞 2019-10-17 19:35:33
    变换方法为: 先构造一个3×1的矩阵,则 2、cv2.warpPerspective()透视变换函数,可保持直线不变形,但是平行线可能不再平行 cv2.warpPerspective(src, M, dsize, dst=None, flags=None, borderMode=None, ...
  • Opencv学习(15)—warpPerspective()

    千次阅读 2019-09-11 18:37:43
    warpPerspective()函数 主要作用:对图像进行透视变换,就是变形 void cv::warpPerspective ( InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR, int borderMode...
  • OpenCV 提供了两个变换函数,cv2.warpAffine 和 cv2.warpPerspective,使用这两个函数你可以实现所有类型的变换。cv2.warpAffine 接收的参数是2 × 3 的变换矩阵,而 cv2.warpPerspective 接收的参数是 3 × 3 的...
  • OpenCV之warpPerspective--透视变换

    万次阅读 多人点赞 2019-06-14 18:44:42
    OpenCV之warpPerspective–透视变换 参考博客链接:https://blog.csdn.net/liuphahaha/article/details/50719275 为了记录自己的学习: 一 OpenCV透视变化进行图像中的关键图提取(抠图) 上代码: #include<...
  • 0 in function 'warpPerspective',错误的详细信息如下 cv2.error: OpenCV(4.4.0) /tmp/pip-req-build-dglzv4yn/opencv/modules/imgproc/src/imgwarp.cpp:3143: error: (-215:Assertion failed) _src.total()
  • 用OpenCV库中的warpPerspective函数,搜了一下网上,没找到可以显示全部的图像信息,所以自己写了一个,用于后面的图像进一步处理。 公式:dst(x,y) = src((M11x+M12y+M13)/(M31x+M32y+M33),   &...
  • 稍加改进OpenCV的warpPerspective方法

    千次阅读 2018-04-06 22:42:24
    背景知识OpenCV的例程warpPerspective是用来矫正畸变图像,warpPerspective函数原型为:CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst, InputArray M, Size dsize, ...
  • Opencv-Python 图像透视变换cv2.warpPerspective

    万次阅读 多人点赞 2018-05-10 21:18:04
    result = cv2.warpPerspective(img, warpR, (h, w)) cv2.namedWindow('result',2) cv2.imshow("result", result) c = cv2.waitKey(30) control() cv2.destroyAllWindows() 运行效果: 控制: s控制垂直方向上...
  • 试验说明 本试验是想模拟自动驾驶识别车道线拟合函数时,可能会用到的一种图像处理手段,即将相机拍摄到的透视图像转换成为逆透视图像(鸟瞰图),便于对车道线的后续处理,同时对基于单目视觉...cv2.warpPerspective(s
  • 图像要求比较严苛,但有时候自己手抖加脑子抽了拍了图片回去写报告才发现:wtf这tm我当时拍的啥玩意,也没法再重排,这时候其实可以利用opencv中的WarpPerspective 投影变换对图像进行矫正。 方法二:另外一个对...
  • OpenCV—透视变换warpPerspective

    万次阅读 多人点赞 2017-10-23 22:22:31
    warpPerspective( src, warpPerspective_dst, warpPerspective_mat, src.size() ); //显示结果 namedWindow( source_window, WINDOW_AUTOSIZE ); imshow( source_window, src ); namedWindow( ...
  • } 计算结果如下: 在获得透视变换矩阵后,即可使用与cv::warpPerspective()进行透视变换,其调用形式如下: void cv::warpPerspective( cv::InputArray src, // 输入图像 cv::OutputArray dst, // 输出图像 ...
  • warpPerspective函数

    万次阅读 2015-08-24 17:14:12
    warpPerspective函数 主要作用:对图像进行透视变换,就是变形 函数的调用形式: C++: void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,615
精华内容 1,446
关键字:

warpperspective