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