warp[wɔːp] 经线,变形 affine [ˈæfaɪn]仿制 根据M矩阵进行变形
一、warpaffine函数原型
void cv::warpAffine(InputArray src, OutputArray dst, InputArray mat, Size dsize = Size(), int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar());
参数详解:
src:输入图像,必须是单通道或三通道的8位或32位浮点型图像。
dst:输出图像,其大小和类型与输入图像相同。
mat:2x3的变换矩阵。
dsize:输出图像的大小,如果这个参数为 Size() ,则输出图像的大小将与输入图像相同。
flags:用于指定插值的方法,默认为线性插值。可用的选项有 INTER_NEAREST, INTER_LINEAR, INTER_CUBIC 等。
borderMode:用于指定如何处理输出图像边缘的像素,默认为常量填充模式。可用的选项有 BORDER_CONSTANT, BORDER_REPLICATE, BORDER_WRAP 等。
borderValue:用于指定填充的边界值,默认为0
二、变换矩阵的获取
1、利用函数获取
Mat getRotationMatrix2D(Point2f center, double angle, double scale)
参数详解:
Point2f center:表示旋转的点 (可以任意指定)
double angle:表示旋转的角度(30°表示逆时针旋转,-30°表示顺时针旋转
double scale:图像缩放因子
2、手动指定变换矩阵
dst(𝑥, 𝑦) = src(𝑀11𝑥 + 𝑀12𝑦 + 𝑀13, 𝑀21𝑥 + 𝑀22𝑦 + 𝑀23)
A、平移 M13指定x平移的大小,M23指定y平移
B、缩放M11指定x方向的缩放,M22指定y方向的缩放
C、旋转:m11=cosα m12=-sinα m21=sinα m22=cosα;
//利用函数确定m的取值
Mat m1 = getRotationMatrix2D(Point2d(src.cols/2, src.rows/2), -30, 1.0);
int w = src.cols;
int h = src.rows;
cout << "w=" << w << endl;
cout << "h=" << h << endl;
double cosa = abs(m1.at<double>(0, 0));
double sina = abs(m1.at<double>(1, 0));
int nw = cosa * w + sina * h;
int nh = cosa * h + sina * w;
cout << "cos30°*w" << cosa * w << endl;
cout << "sin30°*w" << cosa * h << endl;
cout << "nw" << nw << endl;
cout << "nh" << nh << endl;
//将图像平移,避免右下有空地方而左上显示不全
m1.at<double>(0, 2) += (cosa * w + sina * h) / 2 - w / 2;
m1.at<double>(1, 2) += (cosa * h + sina * w) / 2 - h / 2;
warpAffine(src, dst, m1,Size(nw,nh ));
imshow("旋转", dst);
//也可以自己计算新宽度和高度,注意30/180不行,要加小数点。
/* nw = int(w * cos(30.0/ 180 * 3.1415926)+h*sin(30.0/180*3.1415926));
nh = int(w * sin(30.0/ 180 * 3.1415926)+h*cos(30.0/180*3.1415926));
*/
三、如何让物体大小不变
新宽度 neww=cosα*w+hsinα
新高度 newh=cosα*h+wsinα
三、更复杂的仿射变换
对于更复杂仿射变换,OpenCV 提供了
函数 cv2.getAffineTransform()来生成仿射函数 cv2.warpAffine()所使用的转换矩阵 M。该函数的语法格式为:getAffineTransform(Point2f src,Point2f dst)
src 代表输入图像的三个点坐标。
dst 代表输出图像的三个点坐标。
在该函数中,其参数值 src 和 dst 是包含三个二维数组(x, y)点的数组。上述参数通过函数
cv2.getAffineTransform()定义了两个平行四边形。src 和 dst 中的三个点分别对应平行四边形的
左上角、右上角、左下角三个点。函数 cv2.warpAffine()以函数 cv2.getAffineTransform()获取的
转换矩阵 M 为参数,将 src 中的点仿射到 dst 中。函数 cv2.getAffineTransform()
对所指定的点完成映射后,将所有其他点的映射关系按照指定点的关系计算确定。
首先构造了两个三分量的点集合 p1 和 p2,分别用来指代原始图像和目标图像内平行四边形的三个顶点(左上角、右上角、左下角)。
然后使用
M=cv2.getAffineTransform(p1,p2)
获取转换矩阵 M。接下来,
dst=cv2.warpAffine(img,M,(cols,rows))
完成了从原始图像到目标图像的仿射。