功能:对一幅二值图像进行旋转,旋转后图像是倾斜的,然后再把倾斜图像最小的外接矩形(边界是水平垂直)区域取出来。基于这样的需求,图像旋转的时候是取原图像左上、左下和右上三个点,然后根据旋转的角度计算这三个点在目标图像上对应的点。
#include<stdio.h>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main(int argc,char** argv)
{
Mat src = imread("t2.png",0);
double angle = -90;
int height = src.rows;
int width = src.cols;
Point2f srcTri[3],dstTri[3];
//取原图像上的三个点,左上、左下和右上,根据旋转角度计算出在目标图像上对应的点
srcTri[0] = Point2f(0,0);
srcTri[1] = Point2f(width-1,0);
srcTri[2] = Point2f(0,height-1);
//把角度化成弧度
double ang = fabs(angle)*CV_PI/180;
double sina = sin(ang);
double cosa = cos(ang);
int newH,newW;
//顺时针旋转的
if(angle < 0)
{
dstTri[0] = Point2f(height*sina,0);
dstTri[1] = Point2f(dstTri[0].x + width * cosa,width * sina);
dstTri[2] = Point2f(0,height * cosa);
newW = dstTri[1].x;
newH = dstTri[2].y + width*sina;
}
else
//逆时针旋转
{
dstTri[0] = Point2f(0,width * sina);
dstTri[1] = Point2f(width*cosa,0);
dstTri[2] = Point2f(height*sina,dstTri[0].y + height*cosa);
newH = dstTri[2].y;
newW = dstTri[1].x + height*sina;
}
printf("dstTri[0]:(%f,%f) dstTri[1]:(%f,%f) dstTri[2]:(%f,%f)\n",dstTri[0].x,dstTri[0].y,dstTri[1].x,dstTri[1].y,dstTri[2].x,dstTri[2].y);
//计算仿射变换矩阵
Mat warpMat = getAffineTransform(srcTri,dstTri);
//dst这里高和宽随意设了一个很大的值
Mat dst(500,500,CV_8U);
warpAffine(src,dst,warpMat,dst.size(),INTER_LINEAR,BORDER_CONSTANT,Scalar(255));
dst = dst(Rect(0,0,newW,newH));
//二值图像旋转后在黑白交界的地方由于插值会变成黑色,为了使旋转后的图像仍是二值图像,就把灰色像素置0
uchar *data = dst.data;
int num = dst.cols*dst.rows;
int i;
Mat test(dst.rows,dst.cols,CV_8U,Scalar(255));
uchar *data1 = test.data;
for(i=0;i<num;i++)
{
if(*(data+i) != 0 && *(data+i) != 255)
{
*(data1+i) = 0;
}
}
imshow("src",src);
imshow("dst",dst);
imshow("test",test);
waitKey(0);
return 0;
}
效果图: