今天我们聊一聊图像的几何变化。
所谓图像的几何变化,就是指在不改变图像像素的前提下,对图像的像素进行空间几何变化,比较常见的变化有距离变化、坐标映射、平移、镜像旋转、缩放等。

坐标映射

图像的坐标映射就是通过原图像与目标图像之间建立一种映射关系,重映射就是其中的一种,所谓重映射也就是把一张图像中的一个位置的像素通过映射关系转移到另一个图像的指定位置,对于输入像素的函数为f(x,y),目标像素的函数为g(x,y),映射关系为T,会满足函数关系g(x,y)=T(f(x,y)),在OpenCV中也提供了重映射的相关方法。

图像的X轴翻转

public static void remapImgX(){
        Mat srcImg = Imgcodecs.imread("C:\\Users\\Administrator\\Desktop\\ll.jpg");
        HighGui.imshow("原图像", srcImg);
        Mat resultImg= new Mat(srcImg.size(),srcImg.type());
        Mat xMapImg = new Mat(srcImg.size(),CV_32FC1);
        Mat yMapImg = new Mat(srcImg.size(),CV_32FC1);
        int rows = srcImg.rows();
        int cols = srcImg.cols();
        for (int i=0;i<rows;i++){
            for (int j=0;j<cols;j++){
                xMapImg.put(i,j,j);
                yMapImg.put(i,j,rows-i-1);
            }
        }

        Imgproc.remap(srcImg,resultImg,xMapImg,yMapImg,
                INTER_LINEAR,BORDER_CONSTANT,
                new Scalar(0,0,0));
        HighGui.imshow("图像X轴翻转", resultImg);
        HighGui.waitKey(0);
    }

镜像有变化时容器会变化吗 镜像改变什么意思_计算机视觉

图像的Y轴翻转

public static void remapImgY(){
        Mat srcImg = Imgcodecs.imread("C:\\Users\\Administrator\\Desktop\\ll.jpg");
        HighGui.imshow("原图像", srcImg);
        Mat resultImg= new Mat(srcImg.size(),srcImg.type());
        Mat xMapImg = new Mat(srcImg.size(),CV_32FC1);
        Mat yMapImg = new Mat(srcImg.size(),CV_32FC1);
        int rows = srcImg.rows();
        int cols = srcImg.cols();
        for (int i=0;i<rows;i++){
            for (int j=0;j<cols;j++){
                xMapImg.put(i,j,cols-j-1);
                yMapImg.put(i,j,i);
            }
        }

        Imgproc.remap(srcImg,resultImg,xMapImg,yMapImg,
                INTER_LINEAR,BORDER_CONSTANT,
                new Scalar(0,0,0));
        HighGui.imshow("图像Y轴翻转", resultImg);
        HighGui.waitKey(0);
    }

镜像有变化时容器会变化吗 镜像改变什么意思_计算机视觉_02

图像的中心对称

public static void remapImgXY(){
        Mat srcImg = Imgcodecs.imread("C:\\Users\\Administrator\\Desktop\\ll.jpg");
        HighGui.imshow("原图像", srcImg);
        Mat resultImg= new Mat(srcImg.size(),srcImg.type());
        Mat xMapImg = new Mat(srcImg.size(),CV_32FC1);
        Mat yMapImg = new Mat(srcImg.size(),CV_32FC1);
        int rows = srcImg.rows();
        int cols = srcImg.cols();
        for (int i=0;i<rows;i++){
            for (int j=0;j<cols;j++){
                xMapImg.put(i,j,cols-j-1);
                yMapImg.put(i,j,rows-i-1);
            }
        }

        Imgproc.remap(srcImg,resultImg,xMapImg,yMapImg,
                INTER_LINEAR,BORDER_CONSTANT,
                new Scalar(0,0,0));
        HighGui.imshow("图像中心对称", resultImg);
        HighGui.waitKey(0);
    }

镜像有变化时容器会变化吗 镜像改变什么意思_java_03

图像的缩放

图像缩放是指将图像尺寸变小或变大的过程,也就是说减少或增加源图像像素的个数。图像在缩放的过程中会造成一定程度上信息丢失,因此需要考虑适宜的方法进行操作。如果数字图像中像素坐标为非负整数,图像缩过程可能会使得某些坐标为浮点数坐标,因此需要用到图像插值方法。

1、基于等间隔提取图像缩放

等间隔提取图像缩放通过对原图像进行均匀采样完成。对于源图像数据f(x,y),其分辨率MN,如果分辨率改为mn,对于等间隔采样而言,宽度缩放因子kx=M/m,高等缩放因子ky=N/n,对于图像而言,图像缩放在其水平方向等间隔采样为k,垂直反向等间隔采样为k,如果kx=ky,原图像等比例缩放,否则图像数据的宽度和高度发生不同程度的缩放,会造成图像的扭曲。

2、基于区域子块提取图像缩放

区域子块提取图像缩放是通过对源图像进行区域子块划分,提取子块中像素值作为采样像素构成新图像实现,提取子块像素常用方法有,计算子块像素的中值与计算子块像素的均值。对源图像进行区域划分也有多种不同方法,常用方法是根据缩放因子等比例提取子块与自适应因子提取子块。

public static void ImgProduce(){
        Mat srcImg = Imgcodecs.imread("C:\\Users\\Administrator\\Desktop\\ll.jpg");
        HighGui.imshow("原图像", srcImg);
        Mat resultImg= new Mat(srcImg.size(),srcImg.type());
        Mat xMapImg = new Mat(srcImg.size(),CV_32FC1);
        Mat yMapImg = new Mat(srcImg.size(),CV_32FC1);
        int rows = srcImg.rows();
        int cols = srcImg.cols();
        for (int i=0;i<rows;i++){
            for (int j=0;j<cols;j++){
                xMapImg.put(i,j,(j-cols*0.25)*2);
                yMapImg.put(i,j,(i-rows*0.25)*2);
            }
        }

        Imgproc.remap(srcImg,resultImg,xMapImg,yMapImg,
                INTER_LINEAR,BORDER_CONSTANT,
                new Scalar(0,0,0));
        HighGui.imshow("图像缩放", resultImg);
        HighGui.waitKey(0);
    }

//基于C++中的函数warpAffine
public static void ImgProduce2(){
        Mat srcImg = Imgcodecs.imread("C:\\Users\\Administrator\\Desktop\\ll.jpg");
        HighGui.imshow("原图像", srcImg);
        Point center = new Point(srcImg.cols() / 2, srcImg.rows() / 2);
        Mat dest = Imgproc.getRotationMatrix2D(center, 0, 0.5);
        Mat resultImg = new Mat();
        Imgproc.warpAffine(srcImg, resultImg, dest, srcImg.size());
        HighGui.imshow("图像缩放", resultImg);
        HighGui.waitKey(0);
    }

镜像有变化时容器会变化吗 镜像改变什么意思_图像缩放_04

旋转

图像旋转就是按照某个位置转动一定的角度,旋转过程仍然保持着原始尺寸。它的实现还是比较简单的,可以直接借用C++中的函数

public static void ImgRotate(){
        Mat srcImg = Imgcodecs.imread("C:\\Users\\Administrator\\Desktop\\ll.jpg");
        HighGui.imshow("原图像", srcImg);
        Point center = new Point(srcImg.cols() / 2, srcImg.rows() / 2);
        Mat dest = Imgproc.getRotationMatrix2D(center, 45, 1);
        Mat resultImg = new Mat();
        Imgproc.warpAffine(srcImg, resultImg, dest, srcImg.size());
        HighGui.imshow("图像旋转", resultImg);
        HighGui.waitKey(0);
    }

镜像有变化时容器会变化吗 镜像改变什么意思_镜像有变化时容器会变化吗_05