矩阵旋转和翻转相关运算和逆

opencv库中的直接旋转函数rotate和翻转函数flip给我们带来了极大的便利。然而图片中的矩阵经过旋转和翻转之后如何变换应该有一个函数让我们可以快速得到这个变换之后的矩阵。
同时当我们也希望得到原来的矩阵时应该有一个逆运算可以让我们得回这个矩阵。

#include<iostream>
#include<opencv.hpp>


//using namespace std;
//using namespace cv;


int rotateandfliprect(cv::Rect &rect, cv::Size& size, int rotate, int flipflag, cv::Rect dstrect, cv::Rect srcrect);
int rotateandflipImg(cv::Mat &src, cv::Mat& dst, int rotate, int flipflag);
void reSizeRect(const cv::Size srcSize, const cv::Size dstSize, const cv::Rect srcRect, cv::Rect &dstRect);

int main()
{
	cv::Size size(5098, 10895);//图片大小
	cv::Rect rect(101, 203, 39, 48);//矩形大小,原矩形
	cv::Mat Img = cv::Mat::zeros(size, CV_8UC1);
	cv::rectangle(Img, rect, cv::Scalar(255), -1);


	int rotate = 0;//旋转参数-1:不旋转,0:顺时针90,1:顺时针180,2:顺时针270
	int flipflag = 0;//镜像参数-1:不镜像,0:垂直翻转(镜像),1水平翻转(镜像)
	//先旋转再镜像

	cv::Mat dst;
	rotateandflipImg(Img, dst, rotate, flipflag);
	std::vector<std::vector<cv::Point>> contours;
	cv::findContours(dst, contours, 0, 2);
	cv::Rect dstrect = cv::boundingRect(contours[0]);//利用opencv函数可以得到的旋转和翻转之后的矩形的信息,然而,如果在图片尺寸较大的时候,这样的操作无疑会花费较多的时间

	cv::Rect chrect = rect;//旋转和翻转之后的矩形
	rotateandfliprect(chrect, size, rotate, flipflag, dstrect, rect);

	//旋转镜像逆运算
	if (rotate == 0) {
		if (flipflag == 0) {
		}
		else if (flipflag == 1) {
		}
		else {
			rotate = 2;
		}
	}
	else if (rotate == 1) {
		if (flipflag == 0) {
			rotate = -1;
			flipflag = 1;
		}
		else if (flipflag == 1) {
			rotate = -1;
			flipflag = 0;
		}
		else {
		}
	}
	else if (rotate == 2) {
		if (flipflag == 0) {
			rotate = 0;
			flipflag = 1;
		}
		else if (flipflag == 1) {
			rotate = 0;
			flipflag = 0;
		}
		else {
			rotate = 0;
		}
	}
	else if (rotate == -1) {
	}
	else {
		std::cout << "?????";
		return -1;
	}


	cv::Rect nirect = chrect;//经过旋转和翻转之后的矩形逆运算之后的矩形
	rotateandfliprect(nirect, size, rotate, flipflag, rect, chrect);


	cv::waitKey(0);
	return 0;
}

//图形旋转和翻转的函数
int rotateandflipImg(cv::Mat &src, cv::Mat &dst, int rotate, int flipflag) {
	dst = src.clone();

	switch (rotate) {
	case 0:cv::rotate(dst, dst, cv::ROTATE_90_CLOCKWISE); break;
	case 1:cv::rotate(dst, dst, cv::ROTATE_180); break;
	case 2:cv::rotate(dst, dst, cv::ROTATE_90_COUNTERCLOCKWISE); break;
	default:break;
	}

	switch (flipflag) {
	case 0:cv::flip(dst, dst, 0); break;
	case 1:cv::flip(dst, dst, 1); break;
	default:break;
	}
	return 0;
}

//旋转180度为旋转两次90度,旋转270度为三次旋转270度//太low
//对矩形的翻转和镜像
//************************************
// Method:    rotateandfliprect
// FullName:  MakeTemp::rotateandfliprect
// Access:    private 
// Returns:   int
// Qualifier:
// Parameter: cv::Rect & rect			待旋转和翻转的矩形
// Parameter: cv::Size size				原矩形所在原图的尺寸
// Parameter: int rotate				旋转参数-1:不旋转,0:顺时针90,1:顺时针180,2:顺时针270
// Parameter: int flipflag				镜像参数-1:不镜像,0:垂直翻转(镜像),1水平翻转(镜像)
//************************************
int rotateandfliprect(cv::Rect &rect, cv::Size& size, int rotate, int flipflag,cv::Rect dstrect,cv::Rect srcrect) {
	int x = 0, y = 0;
	switch (rotate) {
	case 0: std::swap(rect.width, rect.height);
		x = size.height - rect.y - rect.width;
		y = rect.x;
		rect.x = x;
		rect.y = y;
		std::swap(size.width, size.height);
		break;
	case 1: std::swap(rect.width, rect.height);
		x = size.height - rect.y - rect.width;
		y = rect.x;
		rect.x = x;
		rect.y = y;

		std::swap(size.width, size.height);
		std::swap(rect.width, rect.height);
		x = size.height - rect.y - rect.width;
		y = rect.x;
		rect.x = x;
		rect.y = y;
		std::swap(size.width, size.height);
		break;
	case 2:
		std::swap(rect.width, rect.height);
		x = size.height - rect.y - rect.width;
		y = rect.x;
		rect.x = x;
		rect.y = y;

		std::swap(size.width, size.height);
		std::swap(rect.width, rect.height);
		x = size.height - rect.y - rect.width;
		y = rect.x;
		rect.x = x;
		rect.y = y;

		std::swap(size.width, size.height);
		std::swap(rect.width, rect.height);
		x = size.height - rect.y - rect.width;
		y = rect.x;
		rect.x = x;
		rect.y = y;
		std::swap(size.width, size.height);
		break;
	default:break;
	}

	switch (flipflag) {
	case 0: 
		rect.y = size.height - rect.y - rect.height; 
		break;
	case 1: 
		rect.x = size.width - rect.x - rect.width; 
		break;
	default:break;
	}

	return 0;
}

//旋转优化
int rotateandfliprect(cv::Rect &rect, cv::Size& size, int rotate, int flipflag, cv::Rect dstrect, cv::Rect srcrect) {
	int x = rect.x, y = rect.y;
	switch (rotate) {
	case 0: 
		std::swap(rect.width, rect.height);
		std::swap(size.width, size.height);
		rect.x = size.width - y - rect.width;
		rect.y = x;
		break;
	case 1: 
		rect.x = size.width - x - rect.width;
		rect.y = size.height - y - rect.height;
		break;
	case 2:
		std::swap(rect.width, rect.height);
		std::swap(size.width, size.height);
		rect.x = y;
		rect.y = size.height - x - rect.height;
		break;
	default:break;
	}

	switch (flipflag) {
	case 0:
		rect.y = size.height - rect.y - rect.height;
		break;
	case 1:
		rect.x = size.width - rect.x - rect.width;
		break;
	default:break;
	}

	return 0;
}




void reSizeRect(const cv::Size srcSize, const cv::Size dstSize, const cv::Rect srcRect, cv::Rect &dstRect) {
	double widthRate = 0, heightRate = 0;
	widthRate = 1.0*dstSize.width / srcSize.width;
	heightRate = 1.0*dstSize.height / srcSize.height;

	dstRect.x = srcRect.x*widthRate;
	dstRect.width = srcRect.width*widthRate;
	dstRect.y = srcRect.y*heightRate;
	dstRect.height = srcRect.height*heightRate;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值