opencv学习28-31——图像平移,图像缩放,仿射旋转,仿射倾斜

Q:平移

在相同大小的范围内,原图像上下左右移动。

#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/opencv.hpp>
#include"iostream"
#include"math.h"
using namespace cv;
using namespace std;
Mat Affine_Translation(Mat img,double mx,double my)//向上向右为正,向下向左为负
{
	Mat out=Mat::zeros(img.rows,img.cols,CV_8UC3);
	double i_m,j_m;
	for(int i=0;i<img.rows;i++)
	{
		for(int j=0;j<img.cols;j++)
		{
			i_m=(int)(i+my);
			if(i_m<0||i_m>=img.rows)
				continue;
			j_m=(int)(j-mx);
			if(j_m<0||j_m>=img.cols)
				continue;
			for(int k=0;k<img.channels();k++)
			{
				out.at<Vec3b>(i,j)[k]=img.at<Vec3b>(i_m,j_m)[k];
			}
		}
	}
	return out;
}
void main()
{
	Mat img = imread("ck567.jpg");
	imshow("orignal jpg",img);
	Mat out = Affine_Translation(img,100,100);
	imshow("Affine_Translation",out);
	waitKey(0);
	destroyAllWindows();
}

效果如下

Q:缩放加平移

#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/opencv.hpp>
#include"iostream"
#include"math.h"
using namespace cv;
using namespace std;
Mat Affine(Mat img,double dx,double dy,double mx,double my)//向上向右为正,向下向左为负
{
	int h=img.rows*dx;
	int w=img.cols*dy;
	Mat out=Mat::zeros(h,w,CV_8UC3);
	double i_b,j_b,x,y,mi,mj;
	for(int i=0;i<h;i++)
	{
		i_b=(int)(i/dx);
		x=min((int)i_b,img.rows-1);
		mi=(int)(x+mx);
		if(mi<0||mi>=img.rows)
			continue;
		for(int j=0;j<w;j++)
		{
			j_b=(int)(j/dy);
			y=min((int)j_b,img.cols-1);
			mj=(int)(y-my);
			if(mj<0||mj>=img.cols)
				continue;
			for(int k=0;k<img.channels();k++)
			{
				out.at<Vec3b>(i,j)[k]=img.at<Vec3b>((int)mi,(int)mj)[k];
			}
		}
	}
	return out;
}
void main()
{
	Mat img = imread("ck567.jpg");
	imshow("orignal jpg",img);
	Mat out = Affine(img,1.5,0.8,50,50);
	imshow("Affine",out);
	waitKey(0);
	destroyAllWindows();
}

效果如下

仿射系列的操作不再是对于像素点单独赋值处理,而是通过矩阵运算得到响亮的结果,在统一赋值。

以下从旋转和倾斜来应用

旋转矩阵

初始化的tx和ty为0,在程序的中心定位那里,用变化前后的差值来赋给tx,ty。因为矩阵中用abcd来表示sin和cos函数且其他数值非0即1,是固定的,所以就直接在程序内部定义,没有当做调用函数的参数。

倾斜矩阵

关系式中的h和w是原图像的尺寸,在程序中还是用abcd来表示变换矩阵左上方的四个数值,关系式中都是用a表示,但在程序中在x方向和y方向的变换矩阵中分别由a和c表示,tx和ty都是0。

其中x撇y撇表示要生成图像的像素值,xy表示原图像的像素值,原图像已知,所以将上述的矩阵反过来求得xy,将已知的值带入程序赋值像素值。在运算的过程中要用到线性代数中矩阵的逆。具体体现在程序中det=ad-bc,(d * cx - b * cy) / det,

(- c * cx + a * cy) / det,这几行代码就是求得矩阵的逆。原型如下

Q:旋转

仿射旋转代码如下

#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/opencv.hpp>
#include"iostream"
#include"math.h"
#include <iostream>
#define M_PI 3.1415926
using namespace cv;
using namespace std;
Mat affine(Mat img,double theta)
{
	Mat out=Mat::zeros(img.rows,img.cols,CV_8UC3);
	if(theta==0)
		out=img;
	else
	{
		double rad=theta / 180. * M_PI;
		double a = cos(rad);
		double b = -sin(rad);
        double c = sin(rad);
        double d = cos(rad);
		double det = a * d - b * c;
		double cx = img.cols / 2.;
		double cy = img.rows / 2.;
		double new_cx = (d * cx - b * cy) / det;
		double new_cy = (- c * cx + a * cy) / det;
		double tx = new_cx - cx;
		double ty = new_cy - cy;
		int i_b,j_b;
		for(int i=0;i<img.rows;i++)
		{
			for(int j=0;j<img.cols;j++)
			{
				j_b=(int)((d*j-b*i)/det-tx);
				if(j_b<0||j_b>=img.cols)
					continue;
				i_b=(int)((-c*j+a*i)/det-ty);
				if(i_b<0||i_b>=img.rows)
					continue;
				for(int k=0;k<img.channels();k++)
				{
					out.at<Vec3b>(i,j)[k] = img.at<Vec3b>(i_b, j_b)[k];
				}
			}
		}
	}
	return out;
}
void main()
{
	Mat img = cv::imread("ck567.jpg");
	Mat out = affine(img,30);
	imshow("img",img);
	imshow("affine", out);
	waitKey(0);
	destroyAllWindows();
}

效果如下

Q:倾斜

x方向和y方向同时倾斜80度

代码如下

#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/opencv.hpp>
#include"iostream"
#include"math.h"
#include <iostream>
using namespace cv;
using namespace std;
Mat affine(Mat img,double dx,double dy)
{
		int width = (int)(img.cols + dx);
		int height = (int)(img.rows + dy);
		Mat out=Mat::zeros(height,width, CV_8UC3);
		double a = 1;
		double b = 0;
        double c = 0;
        double d = 1;
		if (dx != 0)
			b = dx / img.rows;
		if (dy != 0)
			c = dy / img.cols;
		double det = a * d - b * c;
		int i_b,j_b;
		for(int i=0;i<height;i++)
		{
			for(int j=0;j<width;j++)
			{
				j_b=(int)((d*j-b*i)/det);
				if(j_b<0||j_b>=img.cols)
					continue;
				i_b=(int)((-c*j+a*i)/det);
				if(i_b<0||i_b>=img.rows)
					continue;
				for(int k=0;k<img.channels();k++)
				{
					out.at<Vec3b>(i,j)[k] = img.at<Vec3b>(i_b, j_b)[k];
				}
			}
		}
	return out;
}
void main()
{
	Mat img = cv::imread("ck567.jpg");
	Mat out = affine(img,80,80);
	imshow("img",img);
	imshow("affine", out);
	waitKey(0);
	destroyAllWindows();
}

效果如下

猜你喜欢

转载自blog.csdn.net/yuan123890/article/details/108482141