Opencv 几何变换<9>
一、resize()
该函数可以改变图像尺寸,原型:
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR );
src:输入,原图像,即待改变大小的图像;
dst:输出,改变大小之后的图像,这个图像和原图像具有相同的内容,只是大小和原图像不一样而已;
dsize:输出图像的大小。如果这个参数不为0,那么就代表将原图像缩放到这个Size(width,height)指定的大小;如果这个参数为0,那么原图像缩放之后的大小就要通过下面的公式来计算:
dsize = Size(round(fx*src.cols), round(fy*src.rows))
其中,fx和fy就是下面要说的两个参数,是图像width方向和height方向的缩放比例。
fx:width方向的缩放比例,如果它是0,那么它就会按照(double)dsize.width/src.cols来计算;
fy:height方向的缩放比例,如果它是0,那么它就会按照(double)dsize.height/src.rows来计算;
interpolation:这个是指定插值的方式,图像缩放之后,肯定像素要进行重新计算的,就靠这个参数来指定重新计算像素的方式,有以下几种:
INTER_NEAREST - 最邻近插值
INTER_LINEAR - 双线性插值,如果最后一个参数你不指定,默认使用这种方法
INTER_AREA - resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.
INTER_CUBIC - 4x4像素邻域内的双立方插值
INTER_LANCZOS4 - 8x8像素邻域内的Lanczos插值
使用注意事项:
1. dsize和fx/fy不能同时为0,要么你就指定好dsize的值,让fx和fy空置直接使用默认值,就像
resize(img, imgDst, Size(30,30));
要么你就让dsize为0,指定好fx和fy的值,比如fx=fy=0.5,那么就相当于把原图两个方向缩小一倍!
2. 至于最后的插值方法,正常情况下使用默认的双线性插值就够用了。
几种常用方法的效率是:最邻近插值>双线性插值>双立方插值>Lanczos插值;
但是效率和效果成反比,所以根据自己的情况酌情使用。
以上是来自别人博客抄袭过来的,如果想随意修改图片的大小,可以建立以Trankbar;
1 using namespace cv; 2 Mat sizeChange; 3 Mat src; 4 int g_nfxSize = 10; 5 double g_nfxMax = 20; 6 void onChange(int, void*); 7 void main() 8 { 9 src = imread("E:\\项目\\OPENCV\\GeomatricTransFormation\\1.jpg", 1); 10 imshow("原图", src); 11 namedWindow("修改图片"); 12 createTrackbar("缩放", "修改图片", &g_nfxSize, g_nfxMax, onChange); 13 onChange(g_nfxSize, 0); 14 //imshow("修改图片", sizeChange); 15 waitKey(); 16 } 17 void onChange(int, void*parmas) 18 { 19 double g_nfxSizeValue; 20 g_nfxSizeValue = (double)g_nfxSize *0.1; 21 resize(src, sizeChange, Size(0, 0), g_nfxSizeValue, g_nfxSizeValue, INTER_LINEAR); 22 imshow("修改图片", sizeChange); 23 }
二、 图像平移
图像平移:用0填充之前留下的空缺!
Mat imgTranslate(Mat& src, int x_off, int y_off); Mat imgTranslate1(Mat& src, int x_off, int y_off); void main() { Mat srcImage = imread("E:\\欣奕华\\项目\\OPENCV\\GeomatricTransFormation\\2.jpg", 1); imshow("原图", srcImage); int k = srcImage.channels(); Mat dstImage; dstImage = imgTranslate(srcImage,500,500); imshow("平移图", dstImage); waitKey(0); } //平移1 //平移注意X,Y代表行还是列,以及移动时别超出了图像的范围!!!!! Mat imgTranslate(Mat& src, int x_off, int y_off) { int rows = src.rows; int cols = src.cols; Mat dst = Mat::zeros(rows+ y_off,cols+ x_off, CV_8UC3); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { int x = j + x_off; int y = i + y_off; if (x >= 0 && y >= 0 && x <= (cols+ x_off) && y <= (rows + y_off)) { dst.at<Vec3b>(y, x) = src.at<Vec3b>(i, j); } } } return dst; } //平移2 Mat imgTranslate1(Mat& src, int x_off, int y_off) { int rows = src.rows+ y_off; int cols = src.cols+ x_off; Mat dst = Mat::zeros(rows, cols, CV_8UC3); for (int i = 0; i < src.rows; i++) { for (int j = 0; j < src.cols; j++) { int x = j + x_off; int y = i + y_off; if (x >= 0 && y >= 0 && x <= cols && y <= rows) { for (int k = 0; k < src.channels(); k++) { dst.at<Vec3b>(y, x)[k] = src.at<Vec3b>(i, j)[k]; } } } } return dst; }
三、仿射变换
仿射变换又称仿射变换,是指在几何中,一个向量空间进行一次线性变换并进行线性平移的过程,常见包括三种:旋转,平移,缩放。其实就是两幅图之间映射,找到这种映射关系是关键;
M 是2 X 3 矩阵;
Mat affinTranslate(Mat& src) { Point2f srcTrangle[3]; Point2f dstTrangle[3]; Mat warpMat(2, 3, CV_32FC1); Mat dst; dst.create(src.size(), src.type()); srcTrangle[0] = Point2f(0, 0); srcTrangle[1] = Point2f(static_cast<float>(src.rows-1), 0); srcTrangle[2] = Point2f(0,static_cast<float>( src.cols-1)); dstTrangle[0] = Point2f(static_cast<float>(src.rows - 1)*0.01, static_cast<float>(src.cols - 1)*0); dstTrangle[1] = Point2f(static_cast<float>(src.rows - 1)*0.9, static_cast<float>(src.cols - 1)*0); dstTrangle[2] = Point2f(static_cast<float>(src.rows - 1)*0, static_cast<float>(src.cols - 1)*0.9); warpMat = getAffineTransform(srcTrangle, dstTrangle); cout << warpMat<<endl; warpAffine(src, dst, warpMat, dst.size()); //imshow("AffineImage",dst); return dst; } Mat rotateTranslate(Mat& src) { Mat rotateMat = Mat(2, 3, CV_32FC1); Mat dst; dst.create(src.size(), src.type()); Point center = Point(src.rows / 2, src.cols / 2); double scale = 0.5; double angle = 30; rotateMat = getRotationMatrix2D(center, angle, scale); warpAffine(src, dst, rotateMat,dst.size()); cout << rotateMat; return dst; }
以上方法,可以创建trankbar,通过修改参数,可以更为直观的观察现象!!!!
此节的内容得出效果有点类似于重映射,将在下一节再进行学习。