图像升采样的实现详解

来源:互联网 发布:图片归类整理软件 编辑:程序博客网 时间:2024/06/04 18:13

此篇文章主要详细描述升采样的实现,基于OpenCV3.2.0&C++实现,升采样实现效果为将M*N的图像采样得到2M * 2N,算法的主要思想如下(图片截自UCF课件以及The Laplacian Pyramid as a Compact Image Code by PETER J. BURT and EDWARD H. ADELSON):
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

代码实现如下:

void myPyrUp(Mat img, Mat &dst){    // 高斯权重    double a = 0.6;    double w[5] = {1.0/4 - a/2.0, 1.0/4,  a,  1.0/4, 1.0/4 - a/2.0};    // 转换为double    Mat src = img.clone();    src.convertTo(src, CV_64FC1);    // 定义目标矩阵    dst = Mat(src.rows * 2, src.cols * 2, CV_64FC1, Scalar(0.0));    // 定义x方向扩展矩阵    Mat temp_x(src.rows, src.cols * 2, CV_64FC1, Scalar(0.0));    // 定义src的x方向边界扩充矩阵(左右两边复制一列)    Mat paddedImg_x(src.rows, src.cols + 2, CV_64FC1, Scalar(0.0));    // 填充paddedImg_x矩阵    for (int i = 0; i < paddedImg_x.rows; ++i)    {        for (int j = 0; j < paddedImg_x.cols; ++j)        {            if (j < 1)                paddedImg_x.at<double>(i, j) = src.at<double>(i, j);            else if (j >= 1 && j < paddedImg_x.cols - 1)                paddedImg_x.at<double>(i, j) = src.at<double>(i, j - 1);            else                paddedImg_x.at<double>(i, j) = paddedImg_x.at<double>(i, j - 1);        }    }    // x方向上采样    for (int i = 0; i < temp_x.rows; ++i)    {        for (int j = 0; j < temp_x.cols; ++j)        {            if (j % 2 == 0)            {                for (int m = -2; m <= 2; m += 2)                {                    temp_x.at<double>(i, j) += w[m + 2] * paddedImg_x.at<double>(i, (j - m) / 2 + 1);                }            }            else            {                for (int m = -1; m <= 1; m += 2)                {                    temp_x.at<double>(i, j) += w[m + 2] * paddedImg_x.at<double>(i, (j - m) / 2 + 1);                }            }        }    }    // 定义temp_x的y方向边界扩充矩阵(上下两边复制一行)    Mat paddedImg_y(temp_x.rows + 2, temp_x.cols, CV_64FC1, Scalar(0.0));    // 填充paddedImg_y矩阵    for (int i = 0; i < paddedImg_y.rows; ++i)    {        for (int j = 0; j < paddedImg_y.cols; ++j)        {            if (i < 1)                paddedImg_y.at<double>(i, j) = temp_x.at<double>(i, j);            else if (i >= 1 && i < paddedImg_y.rows - 1)                paddedImg_y.at<double>(i, j) = temp_x.at<double>(i - 1, j);            else                paddedImg_y.at<double>(i, j) = paddedImg_y.at<double>(i - 1, j);        }    }    // y方向上采样    for (int i = 0; i < dst.rows; ++i)    {        for (int j = 0; j < dst.cols; ++j)        {            if (i % 2 == 0)            {                for (int m = -2; m <= 2; m += 2)                {                    dst.at<double>(i, j) += w[m + 2] * paddedImg_y.at<double>((i - m) / 2 + 1, j);                }            }            else            {                for (int m = -1; m <= 1; m += 2)                {                    dst.at<double>(i, j) += w[m + 2] * paddedImg_y.at<double>((i - m) / 2 + 1, j);                }            }        }    }    dst = 4 * dst;    // 数据类型转换    dst.convertTo(dst, CV_8U);}

测试代码如下:

#include <iostream>#include <vector>#include <cmath>#include <opencv2/opencv.hpp>using namespace std;using namespace cv;void myPyrDown(Mat img, Mat &dst);void myPyrUp(Mat img, Mat &dst);int main(){    Mat img0 = imread("lena.tiff", IMREAD_GRAYSCALE);    Mat img1, img2;    myPyrDown(img0, img1);    myPyrDown(img1, img2);    Mat img1_ex, img2_ex;    myPyrUp(img1, img1_ex);    myPyrUp(img2, img2_ex);    imshow("img0", img0);    imshow("img1", img1);    imshow("img2", img2);    imshow("img1_ex", img1_ex);    imshow("img2_ex", img2_ex);    waitKey(0);    return 0;}

测试结果如下:
这里写图片描述