2016-04-18 11:41:24 GarfieldEr007 阅读数 2339
  • Excel数据透视表实战视频课程【你学得会】

    数据透视表是Excel的重要内容,是Excel交叉数据报表,是Excel分析数据的工具。之所以称为数据透视表,是因为它可以动态地改变布局,以便按照不同方式分析数据。所以它综合了排序。筛选。分类汇总的特点。 杨老师通过《Excel数据透视表实战视频课程【你学得会】》的课程从入门基础,常见应用,其他案例这三个方面着手,讲解包括数据透视表的组成,创建,使用,案例等,深刻地教你使用Excel数据透视表

    9751 人正在学习 去看看 杨仕航

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


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

重写之前的变换公式可以得到:


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

根据变换公式得到:


定义几个辅助变量:


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


不为0时,得到:


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


看一段代码:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. PerspectiveTransform::PerspectiveTransform(float inA11, float inA21,   
  2.                                            float inA31, float inA12,   
  3.                                            float inA22, float inA32,   
  4.                                            float inA13, float inA23,   
  5.                                            float inA33) :   
  6.   a11(inA11), a12(inA12), a13(inA13), a21(inA21), a22(inA22), a23(inA23),  
  7.   a31(inA31), a32(inA32), a33(inA33) {}  
  8.   
  9. PerspectiveTransform PerspectiveTransform::quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1,  
  10.     float x2, float y2, float x3, float y3, float x0p, float y0p, float x1p, float y1p, float x2p, float y2p,  
  11.     float x3p, float y3p) {  
  12.   PerspectiveTransform qToS = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);  
  13.   PerspectiveTransform sToQ =  
  14.     PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);  
  15.   return sToQ.times(qToS);  
  16. }  
  17.   
  18. PerspectiveTransform PerspectiveTransform::squareToQuadrilateral(float x0, float y0, float x1, float y1, float x2,  
  19.     float y2, float x3, float y3) {  
  20.   float dx3 = x0 - x1 + x2 - x3;  
  21.   float dy3 = y0 - y1 + y2 - y3;  
  22.   if (dx3 == 0.0f && dy3 == 0.0f) {  
  23.     PerspectiveTransform result(PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0f,  
  24.                                      0.0f, 1.0f));  
  25.     return result;  
  26.   } else {  
  27.     float dx1 = x1 - x2;  
  28.     float dx2 = x3 - x2;  
  29.     float dy1 = y1 - y2;  
  30.     float dy2 = y3 - y2;  
  31.     float denominator = dx1 * dy2 - dx2 * dy1;  
  32.     float a13 = (dx3 * dy2 - dx2 * dy3) / denominator;  
  33.     float a23 = (dx1 * dy3 - dx3 * dy1) / denominator;  
  34.     PerspectiveTransform result(PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0  
  35.                                      + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0f));  
  36.     return result;  
  37.   }  
  38. }  
  39.   
  40. PerspectiveTransform PerspectiveTransform::quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2,  
  41.     float y2, float x3, float y3) {  
  42.   // Here, the adjoint serves as the inverse:  
  43.   return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();  
  44. }  
  45.   
  46. PerspectiveTransform PerspectiveTransform::buildAdjoint() {  
  47.   // Adjoint is the transpose of the cofactor matrix:  
  48.   PerspectiveTransform result(PerspectiveTransform(a22 * a33 - a23 * a32, a23 * a31 - a21 * a33, a21 * a32  
  49.                                    - a22 * a31, a13 * a32 - a12 * a33, a11 * a33 - a13 * a31, a12 * a31 - a11 * a32, a12 * a23 - a13 * a22,  
  50.                                    a13 * a21 - a11 * a23, a11 * a22 - a12 * a21));  
  51.   return result;  
  52. }  
  53.   
  54. PerspectiveTransform PerspectiveTransform::times(PerspectiveTransform other) {  
  55.   PerspectiveTransform result(PerspectiveTransform(a11 * other.a11 + a21 * other.a12 + a31 * other.a13,  
  56.                                    a11 * other.a21 + a21 * other.a22 + a31 * other.a23, a11 * other.a31 + a21 * other.a32 + a31  
  57.                                    * other.a33, a12 * other.a11 + a22 * other.a12 + a32 * other.a13, a12 * other.a21 + a22  
  58.                                    * other.a22 + a32 * other.a23, a12 * other.a31 + a22 * other.a32 + a32 * other.a33, a13  
  59.                                    * other.a11 + a23 * other.a12 + a33 * other.a13, a13 * other.a21 + a23 * other.a22 + a33  
  60.                                    * other.a23, a13 * other.a31 + a23 * other.a32 + a33 * other.a33));  
  61.   return result;  
  62. }  
  63.   
  64. void PerspectiveTransform::transformPoints(vector<float> &points) {  
  65.   int max = points.size();  
  66.   for (int i = 0; i < max; i += 2) {  
  67.     float x = points[i];  
  68.     float y = points[i + 1];  
  69.     float denominator = a13 * x + a23 * y + a33;  
  70.     points[i] = (a11 * x + a21 * y + a31) / denominator;  
  71.     points[i + 1] = (a12 * x + a22 * y + a32) / denominator;  
  72.   }  
  73. }  
对一张透视图片变换回正面图的效果:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int main(){  
  2.     Mat img=imread("boy.png");  
  3.     int img_height = img.rows;  
  4.     int img_width = img.cols;  
  5.     Mat img_trans = Mat::zeros(img_height,img_width,CV_8UC3);  
  6.     PerspectiveTransform tansform = PerspectiveTransform::quadrilateralToQuadrilateral(  
  7.         0,0,  
  8.         img_width-1,0,  
  9.         0,img_height-1,  
  10.         img_width-1,img_height-1,  
  11.         150,250, // top left  
  12.         771,0, // top right  
  13.         0,1023,// bottom left  
  14.         650,1023  
  15.         );  
  16.     vector<float> ponits;  
  17.     for(int i=0;i<img_height;i++){  
  18.         for(int j=0;j<img_width;j++){  
  19.             ponits.push_back(j);  
  20.             ponits.push_back(i);  
  21.         }  
  22.     }  
  23.     tansform.transformPoints(ponits);  
  24.     for(int i=0;i<img_height;i++){  
  25.         uchar*  t= img_trans.ptr<uchar>(i);  
  26.         for (int j=0;j<img_width;j++){  
  27.             int tmp = i*img_width+j;  
  28.             int x = ponits[tmp*2];  
  29.             int y = ponits[tmp*2+1];  
  30.             if(x<0||x>(img_width-1)||y<0||y>(img_height-1))  
  31.                 continue;  
  32.             uchar* p = img.ptr<uchar>(y);  
  33.             t[j*3] = p[x*3];  
  34.             t[j*3+1] = p[x*3+1];  
  35.             t[j*3+2] = p[x*3+2];  
  36.         }  
  37.     }  
  38.     imwrite("trans.png",img_trans);  
  39.     return 0;  
  40. }  




另外在OpenCV中也实现了基础的透视变换操作,有关函数使用请见下一篇:【OpenCV】透视变换 Perspective Transformation(续)



(转载请注明作者和出处:http://blog.csdn.net/xiaowei_cqu 未经允许请勿用于商业用途)


from: http://blog.csdn.net/xiaowei_cqu/article/details/26471527
2017-04-13 20:36:35 Fishmemory 阅读数 3798
  • Excel数据透视表实战视频课程【你学得会】

    数据透视表是Excel的重要内容,是Excel交叉数据报表,是Excel分析数据的工具。之所以称为数据透视表,是因为它可以动态地改变布局,以便按照不同方式分析数据。所以它综合了排序。筛选。分类汇总的特点。 杨老师通过《Excel数据透视表实战视频课程【你学得会】》的课程从入门基础,常见应用,其他案例这三个方面着手,讲解包括数据透视表的组成,创建,使用,案例等,深刻地教你使用Excel数据透视表

    9751 人正在学习 去看看 杨仕航

图像处理中主要涉及两种几何变换:仿射变换和透视变换。

Sec1. 仿射变换
仿射变换描述二维坐标下的变换操作,主要包括:平移(Translation)、旋转(Rotation)、缩放(Scale)、翻转(Flip)、错切(Shear)几种,每种操作均可以表示为矩阵的形式。尤其注意的是,图像经过仿射变换后,原来的直线和平行线,仿射变换之后仍然为直线和平行线。

平移变换

[xy]=[1001txty][xy]

旋转变换(绕原点逆时针旋转角度θ
[xy]=[cos(θ)sin(θ)sin(θ)cos(θ)][xy]

缩放变换
[xy]=[sx00sy][xy]

翻转变换(以x轴翻转变换为例)
[xy]=[1001][xy]

错切(以x轴错切为例)
[xy]=[10bx1][xy]

综上所述,仿射变换的基本形式可以综合表述为,
[xy]=[m11m21m12m22b1b2][xy]

变换矩阵M表示旋转缩放翻转错切参数,矩阵B表示平移参数,
M=[m11m21m12m22]B=[b1b2]

所以仿射变换可以由6个自由参数来表达。

2.透视变换
相比于仿射变换,透视变换描述的是三维坐标下的变换操作,它其实就是小孔成像模型的变换矩阵,变换结果就是摄像头采集实际物体获得的图像。(个人感觉这与立体几何中的单应矩阵是一个概念)基本形式为,

x^y^z^=h11h21h31h12h22h32h13h231xy1

[x^,y^,z^]是齐次坐标表示,真正的坐标[x,y,1][x^z^,y^z^,1]。可以求解得到坐标值为,

x=x^z^=h11x+h12y+h13h31x+h32y+1(1)

y=y^z^=h21x+h22y+h23h31x+h32y+1(2)

可以看出,透视变换方程中,每个匹配点对可以贡献两个求解方程,而透视变换矩阵中共存在8个未知数,因而至少需要4个匹配点对才可以求解透视变换方程;相比而言,仿射变换矩阵中存在6个未知数,则至少需要3个匹配点可以求解。

关于该矩阵的求解是这样的:有一个对点(x,y)(x,y)时,由公式(1)和(2)可以推导得到

x(h31x+h32y+1)=h11x+h12y+h13

y(h31x+h32y+1)=h21x+h22y+h13

这可以写成矩阵相乘的形式,
ah=v

其中,
h=[h11,h12,h13,h21,h22,h23,h31,h32]T

a=[x0y0100x0y01xxxyxyyy]

v=[x,y]T

那么,有N个点对时,依次按照矩阵a的方式罗列成多行,构成矩阵A
A=a1a2...aN

同理得到矩阵V
V=v1v2...vN

求解方程Ah=V,得到的解h即为透视变换矩阵。我们已经知道,透视变换矩阵包含8个未知数,则至少需要4个点对才可以求解,而当点对的数量多于4个点对时,此时的方程为超定方程,可以通过最小二乘或SVD的方式求解。在matlab中,可以通过左除的方式求解。

h = A\V;

另外,在matlab中求解变换的矩阵的过程封装在函数fitgeotrans()中,在下面图像拼接的例子中会使用该函数求解两个图像的变换矩阵。
例子(该例子取自Rich Radke的公开课 https://www.youtube.com/playlist?list=PLuh62Q4Sv7BUf60vkjePfcOQc8sHxmnDX):假设有两张待拼接的图像I和J,这里采用手动选择若干匹配点的方式来求解变换矩阵(当然可以采用特征点的方式,这里只是采用手动选择匹配点对来进行说明)。
图像I和J分别为,

这里写图片描述
这里写图片描述

代码,

%I and J is two image,pt1 and pt2 is the corresponding matching points
function out = mosaic2(I, J, pt1, pt2)

s = size(I);
%compute transformation matrix
T = fitgeotrans(pt1, pt2, 'projective');

Iregistered = imwarp(I, T, 'OutputView',imref2d([s(1), 2*s(2)]));
Jregistered = imwarp(J, affine2d(eye(3)),'OutputView',imref2d([s(1), 2*s(2)]));

%combine two warpping image
Jmask = any(Jregistered,3)>0;
out = Iregistered;

nonempty = find(Jmask>0);

%set rgb channel value
out(nonempty) = Jregistered(nonempty);
out(nonempty+size(out,1)*size(out,2)) = Jregistered(nonempty+size(out,1)*size(out,2));
out(nonempty+size(out,1)*size(out,2)*2) = Jregistered(nonempty+size(out,1)*size(out,2)*2);

figure;
imshow(out);

end

拼接结果图,
这里写图片描述

2016-07-24 00:08:48 oHanTanYanYing 阅读数 3877
  • Excel数据透视表实战视频课程【你学得会】

    数据透视表是Excel的重要内容,是Excel交叉数据报表,是Excel分析数据的工具。之所以称为数据透视表,是因为它可以动态地改变布局,以便按照不同方式分析数据。所以它综合了排序。筛选。分类汇总的特点。 杨老师通过《Excel数据透视表实战视频课程【你学得会】》的课程从入门基础,常见应用,其他案例这三个方面着手,讲解包括数据透视表的组成,创建,使用,案例等,深刻地教你使用Excel数据透视表

    9751 人正在学习 去看看 杨仕航

   图像的透视变换,在图像处理中经常被用到,本篇文章用以记录相关的一些算法研究和内容。由于作者近期比较忙,暂时只是记录了用OpenCV如何实现该算法,后续会加上相关的内容。

#include <opencv2/opencv.hpp>
#include <opencv2/legacy/legacy.hpp>
using namespace cv;

int main()
{
    //读入待处理图像
    Mat image = imread("矫正后图像.jpg");
    Mat drcimage;
    //创建透视变换之后的图像
    drcimage = Mat::zeros(image.rows, image.cols, image.type());
    //描述透视变换的四个点
    Point2f srcTri[4];//源图像点
    Point2f dstTri[4];//目标图像点
    //源坐标
    srcTri[0] = Point2f(1040, 1155);//左上
    srcTri[1] = Point2f(1345, 1177);//右上
    srcTri[2] = Point2f(1118, 962);//左下
    srcTri[3] = Point2f(1358, 975);//右下
    //目标坐标
    dstTri[0] = Point2f(1040, 1155);
    dstTri[1] = Point2f(1345, 1177);
    dstTri[2] = Point2f(1066, 878);
    dstTri[3] = Point2f(1372, 900);
    //求得透视变换矩阵
    Mat transform = getPerspectiveTransform(srcTri, dstTri);
    //透视变换
    warpPerspective(image, drcimage, transform, drcimage.size());
    //完成,显示和保存图像
    imshow("Image", drcimage);
    imwrite("保存图像.jpg", drcimage);
    waitKey();
    return 0;
}
2016-05-09 20:08:08 u012590570 阅读数 17244
  • Excel数据透视表实战视频课程【你学得会】

    数据透视表是Excel的重要内容,是Excel交叉数据报表,是Excel分析数据的工具。之所以称为数据透视表,是因为它可以动态地改变布局,以便按照不同方式分析数据。所以它综合了排序。筛选。分类汇总的特点。 杨老师通过《Excel数据透视表实战视频课程【你学得会】》的课程从入门基础,常见应用,其他案例这三个方面着手,讲解包括数据透视表的组成,创建,使用,案例等,深刻地教你使用Excel数据透视表

    9751 人正在学习 去看看 杨仕航

图像处理的仿射变换和透视变换

其实一直也没理解“仿射”俩字是啥意思,但是大家都这么叫,其实仿射变换和透视变换更直观的叫法可以叫做“平面变换”和“空间变换”或者“二维坐标变换”和“三维坐标变换”。如果这么命名的话,其实很显然,这俩是一回事,只不过一个是二维坐标(x,y),一个是三维坐标(x,y,z)。也就是:

仿射变换:
这里写图片描述

透视变换:
这里写图片描述

从另一个角度也能说明三维变换和二维变换的意思,仿射变换的方程组有6个未知数,所以要求解就需要找到3组映射点,三个点刚好确定一个平面。透视变换的方程组有8个未知数,所以要求解就需要找到4组映射点,四个点就刚好确定了一个三维空间。

写个程序求解线性方程组相信不是什么难事。

解出方程组之后,就可以按照上面的方程,找到与结果图像上对应的源像素点。然后做插值。

看一下效果啊:

原图:
这里写图片描述

仿射变换之后:
这里写图片描述

透视变换之后:
这里写图片描述

从上图也能看出来区别,仿射变换之后还是平行四边形,透视变换之后就只剩下四边形了。图像的旋转缩放理论上都能用仿射变换来实现(90度、180度、270度的旋转用仿射变换实现不划算)。透视变换的用途可能更多一些,比如:
你扫到的二维码是这样的:
这里写图片描述
这样你直接读二维码信息肯定不行,所以需要透视变换一下,成这样:
这里写图片描述
就可以读出信息了。

刚才讲,求解仿射变换需要3组对应的点,求解透视变换需要4组对应的点,如果找到的映射点的数量少于3组或4组就肯定解不出来,但是如果多于3组或4组怎么办?那就要最小二乘法做拟合,找到一个最佳变换方程。这个不细说了。

2017-06-23 21:11:31 u011574296 阅读数 3982
  • Excel数据透视表实战视频课程【你学得会】

    数据透视表是Excel的重要内容,是Excel交叉数据报表,是Excel分析数据的工具。之所以称为数据透视表,是因为它可以动态地改变布局,以便按照不同方式分析数据。所以它综合了排序。筛选。分类汇总的特点。 杨老师通过《Excel数据透视表实战视频课程【你学得会】》的课程从入门基础,常见应用,其他案例这三个方面着手,讲解包括数据透视表的组成,创建,使用,案例等,深刻地教你使用Excel数据透视表

    9751 人正在学习 去看看 杨仕航

图像处理的仿射变换和透视变换

仿射变换和透视变换更直观的叫法可以叫做“平面变换”和“空间变换”。一个是二维坐标(x,y),一个是三维坐标(x,y,z)

仿射变换:二维平面的变换 ; 线性变换 ;已知3对坐标点就可以求得变换矩阵

透视变换:三维空间的变换 ; 非线性变换 ;已知4对坐标点可以求得变换矩阵

仿射变换(affine transformation)

仿射变换是空间直角坐标系的变换,从一个二维坐标变换到另一个二维坐标,仿射变换是一个线性变换,他保持了图像的“平行性”和“平直性”,即图像中原来的直线和平行线,变换后仍然保持原来的直线和平行线,仿射变换比较常用的特殊变换有平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和剪切(Shear)。
用公式可以表示为:

q⃗ =Ap⃗ +b⃗ 

其中,p为变换前原始向量,q为变换后目标向量,A为线性变换矩阵,b为平移变换向量。公式可统一写成矩阵形式以方便计算:
[q⃗ 1]=[A0b⃗ 1][p⃗ 1]

在图像处理中,我们所谓的向量是二维坐标(x,y),所以向量p、q可以如下表示:

q⃗ =[xy]p⃗ =[xy]

因此我们又能将上述矩阵改写成:
xy1=a1a30a2a40b1b21xy1

其中
T=a1a30a2a40b1b21,A=[a1a3a2a4],b=[b1b2]

T矩阵只有6个参数,所以只要知道3个点对的对应坐标,就可以求出T矩阵,也就得到A矩阵和b向量。

仿射变换也可以看成坐标系的旋转和缩放以及平移:

这里写图片描述

P点位置不变,坐标系由(Xt,Yt)变换到(Xs,Ys),相应的坐标有(Xtp,Ytp)变换成(Xsp,Ysp)。

其中(Xtp,Ytp)与(Xsp,Ysp)的关系如下:
这里写图片描述

OpenCV3中相应的函数:

estimateRigidTransform():计算多个二维点对或者图像之间的最优仿射变换矩阵 (2行x3列),H可以是部分自由度,比如各向一致的切变。
getAffineTransform():计算3个二维点对之间的仿射变换矩阵H(2行x3列),自由度为6.
warpAffine():对输入图像进行仿射变换

透视变换(Perspective transformation)

透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。通用的变换公式为:
这里写图片描述
变换矩阵可以拆成4部分,表示线性变换,比如scaling,shearing和ratotion。用于平移,产生透视变换。所以可以理解成仿射等是透视变换的特殊形式。经过透视变换之后的图片通常不是平行四边形(除非映射视平面和原来平面平行的情况)。

OpenCV3中相应的函数:

findHomography: 计算多个二维点对之间的最优单映射变换矩阵 H(3行x3列) ,使用最小均方误差或者RANSAC方法 。
getPerspectiveTransform():计算4个二维点对之间的透射变换矩阵 H(3行x3列)
warpPerspective(): 对输入图像进行透射变换
perspectiveTransform():对二维或者三维矢量进行透射变换,也就是对输入二维坐标点或者三维坐标点进行投射变换。
estimateAffine3D:计算多个三维点对之间的最优三维仿射变换矩阵H (3行x4列)
transform():对输入的N维矢量进行变换,可用于进行仿射变换、图像色彩变换.
findFundamentalMat:计算多个点对之间的基矩阵H。

参考:
作者:ruiruige1991
恋上蛋炒面的专栏

没有更多推荐了,返回首页