当前位置:网站首页 > 创业 > 正文

OpenCV:重映射remap vs仿射变换warpAffine

0 张子豪 张子豪 2025-10-12 03:34 1

绪:

重映射就是把一幅图像中某个位置的像素放置到另一个图像中指定位置的过程;

仿射变换是一个标的目的量空间进行一次线性变换并接上一个平移,变换为另一贯量空间的过程;

本文本家儿要分重映射和放射变换的功能;

以及若何利用的。

东西/原料

  • OpenCV 2410

方式/步调

  1. 1

    重映射remap:

    重映射就是把一幅图像中某个位置的像素放置到另一个图像中指定位置的过程;

    公式:

    g(x,y)=f(h(x,y))

    此中f就是映射体例;

    在OpenCV中,利用remap函数实现重映射。

    格局:

    void remap(InputArray src, //输入图像

               OutputArraydst, //输出图像

               InputArray map1,//第一个映射

               InputArray map2, //第二个映射

               int interpolation, //插值

               intborderMode=BORDER_CONSTANT,

               const Scalar& borderValue=Scalar()

               )

  2. 2

    重映射法式如下:

    //根基重映射尝试

    #include <opencv2\opencv.hpp>

    #include <opencv2\highgui\highgui.hpp>

    #include <opencv2\features2d\features2d.hpp>

    #include <opencv2\core\core.hpp>

    using namespace std; 

    using namespace cv; 

    int main()

    {

           Mat srcImage = imread("0.jpg");

           imshow("Src Pic", srcImage);

           Mat dstImage, map_x, map_y;

           dstImage.create(srcImage.size(), srcImage.type());

           map_x.create(srcImage.size(), CV_32FC1);

           map_y.create(srcImage.size(), CV_32FC1);

           //遍历每一个像素点,改变map_x & map_y的值,实现翻转180度

           for (int j = 0; j < srcImage.rows; j++)

           {

                  for (int i = 0; i < srcImage.cols; i++)

                  {

                         map_x.at<float>(j, i) = static_cast<float>(i);//行不变

                         map_y.at<float>(j, i) = static_cast<float>(srcImage.rows - j);//列翻转

                  }

           }

           //进行重映射操作

           remap(srcImage, dstImage, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));

           imshow("重映射结果图", dstImage); 

           waitKey();

           return 0;

    }

    【注】:

    map_x和map_y:代表方针图中的(x,y)点在原图像的x坐标和y坐标;

  3. 3

    仿射变换:

    仿射变换是一个标的目的量空间进行一次线性变换并接上一个平移,变换为另一贯量空间的过程;

    图像进行仿射变换后的特点:

    ①二维图像之间的相对位置关系连结不变,平行线依旧是平行线,且直线上的点的位置挨次连结不变;

    ②一个肆意的仿射变换都可以暗示为乘以一个矩阵(线性变换)接着再加上一个标的目的量(平移)的形式;

    三种常见形式:

    扭转-rotation(线性变换)

    平移-translation(标的目的量加)

    缩放-scale(线性变换)

  4. 4

    仿射变换流程:

    仿射变换素质是一个2* 3的矩阵M乘上原图的每个坐标,获得方针图的对应点坐标。

    2*3矩阵M中的2暗示方针点坐标的x与y,3中的第三维是平移分量。

    是以需要做的就是找到矩阵M;

    OpenCV供给 getAffineTransform 求出仿射变换,

    getRotationMatrix2D 来获得扭转矩阵。

     

    这里简单说说仿射变换是怎么做到的。

    如下有两幅图像,图像二是图像一颠末放射转变得来的。

    那问题来了,我们怎么从这两个图像信息里挖掘出两图之间的映射关系?

    只要在图像一种拿出三个点(1,2,3),

    图像二也拿出对应的三个点(1,2,3),

    就可以求出两图间的映射关系!

  5. 5

    法式1

    OpenCV经由过程两个函数的组合利用来实现仿射变换:

    利用warpAffine来实现简单重映射

    利用getRotationMatrix2D来获得扭转矩阵

     

    #include <opencv2\opencv.hpp>

    #include <opencv2\highgui\highgui.hpp>

    #include <opencv2\features2d\features2d.hpp>

    #include <opencv2\core\core.hpp>

     

    using namespace std; 

    using namespace cv; 

     

    //仿射变换尝试

    int main()

    {

           Mat src = imread("0.jpg");

           Mat dst_warp, dst_warpRotateScale;

           Point2f srcPoints[3];//原图中的三点 

           Point2f dstPoints[3];//方针图中的三点 

     

           //第一种仿射变换的挪用体例:三点法

           //三个点对的值,只要知道变换后图的三个点坐标,就可实现仿射变换 

           srcPoints[0] = Point2f(0, 0);

           srcPoints[1] = Point2f(0, src.rows - 1);

           srcPoints[2] = Point2f(src.cols - 1, 0);

           //映射后的三个坐标值

           dstPoints[0] = Point2f(0, src.rows*0.3);

           dstPoints[1] = Point2f(src.cols*0.25, src.rows*0.75);

           dstPoints[2] = Point2f(src.cols*0.75, src.rows*0.25);

           Mat M1 = getAffineTransform(srcPoints, dstPoints);//计较变换矩阵 

           warpAffine(src, dst_warp, M1, src.size());//仿射变换 

     

           //第二种仿射变换的挪用体例:直接指心猿意马角度和比例                                         

           //扭转加缩放 

           Point2f center(src.cols/2, src.rows/2);//扭转中间 

           double angle = 45;//逆时针扭转45度 

           double scale = 0.5;//缩放比例 

     

           Mat M2 = getRotationMatrix2D(center, angle, scale);//计较扭转加缩放的变换矩阵 

           warpAffine(dst_warp, dst_warpRotateScale, M2, src.size());//仿射变换 

           imshow("原始图", src);

           imshow("仿射变换1", dst_warp);

           imshow("仿射变换2", dst_warpRotateScale);

           waitKey(0);

           return 0;

    }

    【注】:

    有没有发现图片进行仿射变换后的布景被填充为黑色了?

    其实这个布景色是可以调的,像如许:

    warpAffine(dst_warp, dst_warpRotateScale, M2, src.size(), 1, 0, Scalar(11,111, 211));

    //操纵Scalar来填充分歧颜色布景

  6. 6

    法式2

    #include <opencv2\opencv.hpp>

    #include <opencv2\highgui\highgui.hpp>

    #include <opencv2\features2d\features2d.hpp>

    #include <opencv2\core\core.hpp>

     

    using namespace std; 

    using namespace cv; 

     

    //仿射变换尝试

    #define PIC_BEGIN_NUM 100  //这里界说你的肇端图片编号

    #define ANGLE_START -45  //扭转角度的起头

    #define ANGLE_END  0  //扭转角度的竣事

    #define ANGLE_STEP 2 //扭转角度步长

    int main(int argc, char **argv)

    {

           const char* filename = "0.jpg";

           Mat srcImg = imread(filename, 1);

           imshow("source", srcImg);

           Point center(srcImg.cols / 2, srcImg.rows / 2); //图片中间为扭转点

           char file[20];

           int count = PIC_BEGIN_NUM;

           Mat tpimg;

           for (int tp = ANGLE_START; tp < ANGLE_END; tp += ANGLE_STEP)

           {

                  Mat rotMatS = getRotationMatrix2D(center, tp, 0.5); //图片缩小到本来的0.5倍

                  warpAffine(srcImg, tpimg, rotMatS, srcImg.size(), 1, 0, Scalar(0, 0, 0));//填充黑色布景                                                                          

                  sprintf(file, "%d.jpg", count++);  //扭转图片以1.jpg  2.jpg 的名字格局保留

                  imwrite(file, tpimg);

           }

           waitKey(0);

           return 0;

    }

注重事项

  • map_x和map_y:代表方针图中的(x,y)点在原图像的x坐标和y坐标
  • getAffineTransform 求出仿射变换;
  • getRotationMatrix2D 来获得扭转矩阵;

来源:百闻(微信/QQ号:9397569),转载请保留出处和链接!


本文链接:https://www.ibaiwen.com/web/235716.html

张子豪

张子豪

TA很懒,啥都没写...

@百闻娱乐 本站部分内容转自互联网,若有侵权等问题请及时与本站联系,我们将在第一时间删除处理。 | 粤ICP备2024343649号 | (地图