Skip to content
鼓励作者:欢迎打赏犒劳

图像的几何变换

图片的平移,旋转,缩放,翻转都属于仿射变换!

仿射变换

核心是给出任意三个点,注意不能在一条线上的三个点,然后经过getAffineTransform函数计算得到仿射变换矩阵,然后再通过warpAffine 函数实现仿射变换

java
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
 
public class WarpAffine {
 
	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
         
		//读取图像
		Mat src=Imgcodecs.imread("C:\\Users\\Think\\Desktop\\TestCV\\leaf.png");

		//定义原图像中三个点的坐标
		Point[] pt1 = new Point[3]; //输入图像点集
		pt1[0] = new Point(136, 56);
		pt1[1] = new Point(45, 160);
		pt1[2] = new Point(215, 150);

		//定义目标图像中三个点的坐标
		Point[] pt2 = new Point[3];	//输出图像点集
		pt2[0] = new Point(50, 80);
		pt2[1] = new Point(50, 180);
		pt2[2] = new Point(200, 100);

		//getAffineTransform()函数用到的数据类型
		MatOfPoint2f mop1 = new MatOfPoint2f(pt1); 
		MatOfPoint2f mop2 = new MatOfPoint2f(pt2);

		//计算仿射变换矩阵并进行仿射变换
		Mat dst=new Mat();
		Mat mat=Imgproc.getAffineTransform(mop1, mop2); 
		Imgproc.warpAffine(src, dst, mat, src.size());

		//在原图像中标记三个点的坐标
		Scalar color=new Scalar(255,255,255);
		for (int n=0; n<3; n++) {
			Imgproc.circle(src, pt1[n], 2, color, 2);
			Imgproc.putText(src, n + 1 + "", pt1[n] , 0 , 1, color,3);
		}

		//在目标图像中标记三个点的坐标
		for (int n=0; n<3; n++) {
			Imgproc.circle(dst, pt2[n], 2, color, 2);              
			Imgproc.putText(dst, n + 1 + "", pt2[n] , 0 , 1, color,3);
		}
		
		//在屏幕上显示变换前后的图像
		HighGui.imshow("src", src); 
		HighGui.waitKey(0);				
		HighGui.imshow("warped", dst); 
		HighGui.waitKey(0);
		
		//在控制台输出仿射变换矩阵
		System.out.println(mat.dump());
		System.exit(0);
		
	}
}

透视变换

java
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
 
public class PerspectiveTransform  {

	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

		//读取图像
		Mat src=Imgcodecs.imread("C:\\Users\\Think\\Desktop\\TestCV\\book.png");

		//定义原图像中4个点的坐标
		Point[] pt1 = new Point[4]; 
		pt1[0] = new Point(95, 129);
		pt1[1] = new Point(260, 157);
		pt1[2] = new Point(57, 469);
		pt1[3] = new Point(248, 454);

		//定义目标图像中4个点的坐标
		Point[] pt2 = new Point[4];
		pt2[0] = new Point(0, 0);
		pt2[1] = new Point(300, 0);
		pt2[2] = new Point(0,600);
		pt2[3] = new Point(300,600);
        
		//getPerspectiveTransform()函数用到的数据类型
		MatOfPoint2f mop1 = new MatOfPoint2f(pt1); 
		MatOfPoint2f mop2 = new MatOfPoint2f(pt2);

		//计算透视变换矩阵并进行仿射变换
		Mat dst=new Mat();
		Mat matrix=Imgproc.getPerspectiveTransform(mop1, mop2); //获取转换矩阵
		Imgproc.warpPerspective(src, dst, matrix, new Size(300,600));

		//在屏幕上显示变换前后的图像
		HighGui.imshow("src", src); 
		HighGui.waitKey(0); 
		HighGui.imshow("dst", dst); 
		HighGui.waitKey(0); 
		System.exit(0);
	}
}

平移

平移就是将原图的每个像素的坐标都平移x,y的距离,比如下面的就是 向x轴平移30,向y轴平移50。其中只有30和50是变量

java
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class Translate {

	public static void main(String[] args) {
		System.loadLibrary( Core.NATIVE_LIBRARY_NAME );

		//构建用于平移的矩阵
		Mat mat = new Mat(2, 3, CvType.CV_64F);  	
		double [] Data=new double[] {1,0,30,0,1,50};  
		mat.put(0, 0, Data);  
		
		//读取图像并在屏幕上显示
		Mat src=Imgcodecs.imread("C:\\Users\\Think\\Desktop\\TestCV\\pond.png");
		HighGui.imshow("src", src); 
		HighGui.waitKey(0); 
		
		//进行平移并在屏幕上显示平移后的图像
		Mat dst=new Mat();
		Imgproc.warpAffine(src, dst, mat, src.size());
		HighGui.imshow("translate", dst); 
		HighGui.waitKey(0); 
		System.exit(0);	

	}
}

旋转

以图像为中心,旋转角度为33°,正数表示逆时针

java
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
 
public class Rotate {
 
	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

		//读入图像并在屏幕上显示                      
		Mat src=Imgcodecs.imread("C:\\Users\\Think\\Desktop\\TestCV\\fish.png");
		HighGui.imshow("src", src); 
		HighGui.waitKey(0); 
           		
		//计算旋转用的仿射矩阵
		Mat dst=new Mat();
		Point center =new Point(src.width()/2.0, src.height()/2.0);
		Mat matrix =Imgproc.getRotationMatrix2D(center, 33.0, 1.0);             
		
		//旋转图像并在屏幕上显示
		Imgproc.warpAffine(src, dst, matrix, src.size(),Imgproc.INTER_LINEAR);
		HighGui.imshow("Rotated", dst); 
		HighGui.waitKey(0); 
		System.exit(0);	
	}
}

缩放

java
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
 
public class Scale {
 
    public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		
		//读入图像并在屏幕上显示
		Mat src=Imgcodecs.imread("C:\\Users\\Think\\Desktop\\TestCV\\church.png");
		HighGui.imshow("src", src); 
		HighGui.waitKey(0);
 
		//获取原图像尺寸
		float width=src.width();
		float height=src.height();
		
		//将原图像放大至1.2倍
		Mat dst1=new Mat(); 
		float scale1=1.2f;  //缩放比例1
		Imgproc.resize(src, dst1, new Size(width*scale1,height*scale1));

		//将原图像缩小至0.8倍
		Mat dst2=new Mat(); 
		float scale2=0.8f;  //缩放比例2
		Imgproc.resize(src, dst2, new Size(width*scale2,height*scale2));

		//在屏幕上显示放大和缩小后的图像
		HighGui.imshow("Bigger", dst1);
		HighGui.waitKey(0); 
		HighGui.imshow("Smaller", dst2);
		HighGui.waitKey(0); 
		
		System.exit(0);
	}
}

翻转

java
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;

import java.util.ArrayList;
import java.util.List;

public class Flip {
 
	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		
		//读取图像文件并在屏幕上显示
		Mat src=Imgcodecs.imread("C:\\Users\\Think\\Desktop\\TestCV\\leaf.png");
		HighGui.imshow("src", src);
		HighGui.waitKey(0);

		//绕y轴翻转
		Mat f1=new Mat();
		Core.flip(src, f1, 1);

		//将两幅图像进行水平拼接
		List<Mat> mats = new ArrayList<Mat>();
		mats.add(src);  
		mats.add(f1);  
		Mat d1 = new Mat();  
		Core.hconcat(mats, d1);  //水平拼接
		
		//绕x轴翻转
		Mat f2=new Mat();
		Core.flip(src, f2, 0);
		
		//绕x,y两个轴翻转		
		Mat f3=new Mat();
		Core.flip(src, f3, -1);
		
		//移除mats中元素
		mats.remove(1); 
		mats.remove(0); 
		
		//将x轴翻转图像和两个轴翻转图像进行水平拼接
		mats.add(f2);
		mats.add(f3);
		Mat d2 = new Mat();
		Core.hconcat(mats, d2);
		
		//将两幅拼接后的图像垂直再拼接		
		mats.remove(1); 
		mats.remove(0); 
		mats.add(d1);
		mats.add(d2);		
		Mat d3 = new Mat();
		Core.vconcat(mats, d3);		
		
		//在屏幕上显示最后结果
		HighGui.imshow("All", d3);
		HighGui.waitKey(0);
		
		System.exit(0);
    }
 }

图像拼接

hconcat 水平拼接

vconcat 垂直拼接

java
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;

import java.util.ArrayList;
import java.util.List;

public class Concat {
 
	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);        

		//读取图像文件 并克隆
		Mat src1=Imgcodecs.imread("C:\\Users\\Think\\Desktop\\TestCV\\church.png");
		Mat src2=src1.clone();  
			
		//hConcat函数需要的参数类型准备
		List<Mat> mat1 = new ArrayList<Mat>();
		mat1.add(src1);  
		mat1.add(src2);  
		
		//将2幅图像进行水平拼接
		Mat dst = new Mat();  
		Core.hconcat(mat1, dst);  

		//在屏幕上显示水平拼接后的图像	
		HighGui.imshow("hconcat", dst);   
		HighGui.waitKey(0);  
		
		//读取图像文件 
		Mat src3=Imgcodecs.imread("C:\\Users\\Think\\Desktop\\TestCV\\leaf.png");
		Mat src4=src3.clone();
			
		//vConcat函数需要的参数类型准备
		List<Mat> mat2 = new ArrayList<Mat>();
		mat2.add(src3);  
		mat2.add(src4);  
		
		//将2幅图像进行垂直拼接
		Mat dst2 = new Mat();  
		Core.vconcat(mat2, dst2);  

		//在屏幕上显示垂直拼接后的图像	
		HighGui.imshow("vconcat", dst2);   
		HighGui.waitKey(0);  		
		System.exit(0);  
	}
	
 }

如有转载或 CV 的请标注本站原文地址