行远-自迩

导航

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,通过修改参数,可以更为直观的观察现象!!!!

此节的内容得出效果有点类似于重映射,将在下一节再进行学习。

posted on 2019-10-11 22:26  行远-自迩  阅读(284)  评论(0编辑  收藏  举报