您的位置:首页 > 运维架构

opencv实现图像的缩放

2017-06-02 23:26 387 查看
图像的缩放是指将图像的尺寸变小或者变大的过程,也就是减少或者增加原图像数据的像素个数。图像缩放会在一定程度上面丢失图像的信息,因此需要考虑适宜的方法进行操作。如果数字图像中像素坐标为非负整数,图像缩放过程很可能回事的某些坐标为浮点数,因此需要用到图像插值方法、

1.基于等间隔提取图像缩放

等间隔图像缩放时通过对源图像进行均匀采样来完成的。对于源图像数据f(x,y),其分辨率为M*N,如果将其分辨率改成m*n,对于等间隔采样而言,其宽度缩放因子就是M/m,高度缩放因子就是N/n。如果宽度和高度缩放成都相等的话,那就代表源图像数据等比例缩放。如果不等,那就会照成图形扭曲现象。

2.基于区域子快提取图像缩放

区域子快提取图像缩放时通过对源图像进行区域子快划分。然后提取子块中的像素值作为采样像素已构成新的图像来实现。提取子快图像值常用的方法有计算子快像素的中值与计算子快的均值。对源图像进行区域划分同样也有很多种方法,常用的方法是根据缩放因子等比例的提取子快与自适应因子提取子快。

代码如下:

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>

using namespace std;

//基于等间隔提取图像缩放
cv::Mat imageReduction1(cv::Mat &srcImage, float kx, float ky)
{
    //获取输出图像分辨率
    int nRows = cvRound(srcImage.rows * kx);
    int nCols = cvRound(srcImage.cols * ky);

    cv::Mat resultImage(nRows, nCols, srcImage.type());

    for (int i = 0; i < nRows; i++)
    {
        for (int j = 0; j < nCols; j++)
        {
            //根据水平因子计算坐标,static_cast用于类型转换
            int x = static_cast<int>((i + 1) / kx + 0.5) - 1;
            //根据垂直因子计算坐标
            int y = static_cast<int>((j + 1) / ky + 0.5) - 1;

            resultImage.at<cv::Vec3b>(i, j) = srcImage.at<cv::Vec3b>(x, y);
        }
    }

    return resultImage;
}

cv::Vec3b areaAverage(const cv::Mat &srcImage, cv::Point_<int> leftPoint, cv::Point_<int> rightPoint)
{
    int temp1 = 0, temp2 = 0, temp3 = 0;
    
    //计算子快区域的像素点个数
    int nPix = (rightPoint.x - leftPoint.x + 1) * (rightPoint.y - leftPoint.y + 1);

    //对区域子快各个通道对像素值求和
    for (int i = leftPoint.x; i <= rightPoint.x; i++)
    {
        for (int j = leftPoint.y; j <= rightPoint.y; j++)
        {
            temp1 += srcImage.at<cv::Vec3b>(i, j)[0];
            temp2 += srcImage.at<cv::Vec3b>(i, j)[1];
            temp3 += srcImage.at<cv::Vec3b>(i, j)[2];
        }
    }

    //对每个通道求平均值
    cv::Vec3b vecTemp;
    vecTemp[0] = temp1 / nPix;
    vecTemp[1] = temp2 / nPix;
    vecTemp[2] = temp3 / nPix;

    return vecTemp;
}

cv::Mat imageReduction2(const cv::Mat &srcImage, double kx, double ky)
{
    //获取输出图像分辨率
    int nRows = cvRound(srcImage.rows * kx);
    int nCols = cvRound(srcImage.cols * ky);
    cv::Mat resultImage(nRows, nCols, srcImage.type());

    //区域子快的左上角行列坐标
    int leftRowCoordinate = 0;
    int leftColCoordinate = 0;
    for (int i = 0; i < nRows; ++i)
    {
        //根据水平因子计算坐标
        int x = static_cast<int>((i + 1) / kx + 0.5) - 1;

        for (int j = 0; j < nCols; ++j)
        {
            //根据垂直因子计算
            int y = static_cast<int>((j + 1) / ky + 0.5) - 1;

            //求区域子快的均值
            resultImage.at<cv::Vec3b>(i, j) = areaAverage(srcImage, cv::Point_<int>(leftRowCoordinate, leftColCoordinate), cv::Point_<int>(x, y));

            //更新下子快左上角的列坐标,行坐标不变
            leftColCoordinate = y + 1;
        }
        leftColCoordinate = 0;
        leftRowCoordinate = x + 1;
    }

    return resultImage;
}

int main()
{
    cv::Mat srcImage = cv::imread("C:\\Users\\LP\\Desktop\\C++\\ConsoleApplication4\\ConsoleApplication4\\1.jpg");
    if(srcImage.empty())
    {
        return -1;
    }
    cv::imshow("原图像", srcImage);
    cv::Mat resultImage1 = imageReduction1(srcImage, 0.5, 0.5);
    cv::imshow("res1", resultImage1);

    cv::Mat resultImage2 = imageReduction2(srcImage, 0.5, 0.5);
    cv::imshow("res2", resultImage2);
    
    cv::waitKey(0);

    return 0;
}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: