图片插值

实现部分图片插值算法(最近邻,双线性,双立方)

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

struct MyMat
{
    u_char *data;
    int w, h, c;
    MyMat(){}
    MyMat(cv::Mat &A){
        w = A.cols, h = A.rows, c = A.channels();
        data = (u_char *) malloc(w * h * c * sizeof(u_char));
        memcpy(data, A.data, w * h * c * sizeof(u_char));
    }
    cv::Mat to_cvMat(){
        cv::Mat A(h, w, CV_8UC3, cv::Scalar(0, 0, 0));
        memcpy(A.data, data, w * h * c * sizeof(u_char));
        return A;
    }
};
double INTER_CUBIC_Fun(double x, double a = -0.5)
{
    x = abs(x);
    if(0 <= x && x <= 1){
        return 1 - (a + 3) * x * x + (a + 2) * x * x * x;
    }
    else if(1 < x && x <= 2){
        return 8 * a * x - 5 * a * x * x + a * x * x * x - 4 * a;
    }
    else return 0;
}
int dimtovec(MyMat &a, int i, int j,int k)
{
    //return k * a.w * a.h + j * a.w + i;
    return a.c * (a.w * j + i) + k;
}
/*
 * A:数据矩阵 nw,nh:宽和长 interpolation_type:插值的方式
 */
MyMat resize(MyMat A, int nw, int nh, std::string interpolation_type)
{
    MyMat B;
    B.w = nw, B.h = nh, B.c = A.c;
    B.data = (u_char *) malloc(sizeof(u_char) * B.w * B.h * B.c);
    double dw = (double)A.w / nw;
    double dh = (double)A.h / nh;
    if(interpolation_type == "INTER_NEAREST"){ //最近邻插值
        for(int i = 0; i < nw; i++){
            for(int j = 0; j < nh; j++){
                int nx = i * dw;
                int ny = j * dh;
                //B.data[i * nh + j] = A.data[nx * A.h + ny];
                for(int k = 0; k < B.c; k++){
                    int t1 = dimtovec(B, i, j, k), t2 = dimtovec(A, nx, ny, k);
                    B.data[t1] = A.data[t2];
                }
            }
        }
    }
    else if(interpolation_type == "INTER_LINEAR"){ //双线性插值
        for(int i = 0; i < nw; i++){
            for(int j = 0; j < nh; j++){
                double nx = i * dw, ny = j * dh;
                if(nx >= A.w - 1)
                    nx = A.w - 2;
                if(ny >= A.h - 1)
                    ny = A.h - 2;
                int x1 = floor(nx), x2 = floor(nx + 1), y1 = floor(ny + 1), y2 = floor(ny);
                double alpha = (x2 - nx) / (x2 - x1), beta = (nx - x1) / (x2 - x1);
                for(int k = 0; k < A.c; k++){
                    int Q11 = dimtovec(A, x1, y1 ,k);
                    int Q12 = dimtovec(A, x1, y2, k);
                    int Q21 = dimtovec(A, x2, y1, k);
                    int Q22 = dimtovec(A, x2, y2, k);
                    double R1 = alpha * A.data[Q11] + beta * A.data[Q21];
                    double R2 = alpha * A.data[Q12] + beta * A.data[Q22];
                    B.data[dimtovec(B, i, j, k)] = (y2 - ny) / (y2 -y1) * R1 + (ny - y1) / (y2 - y1) * R2;
                }
            }
        }
    }
    else if(interpolation_type == "INTER_CUBIC"){ //4x4像素点领域内的双立方插值
        for(int i = 0; i < nw; i++){
            for(int j = 0; j < nh; j++){
                int nx = i * dw, ny = j * dh;
                double dx = i * dw - nx, dy = j * dh - ny;
                for(int k = 0; k < B.c; k++){
                    double sum = 0;
                    for(int di = -1; di <= 2; di++){
                        for(int dj = -1; dj <= 2; dj++){
                            int x = nx + di, y = ny + dj;
                            if(x < 0) x = 0;
                            else if(x >= A.w){
                                x = A.w - 1;
                            }
                            if(y < 0 ) y = 0;
                            else if(y >= A.h){
                                y = A.h - 1;
                            }
                            sum += A.data[dimtovec(A, x, y, k)] * INTER_CUBIC_Fun(di - dx) * INTER_CUBIC_Fun(dy - dj);
                        }
                    }
                    if(sum > 255) sum = 255;
                    if(sum < 0) sum = 0;
                    B.data[dimtovec(B, i, j, k)] = sum;
                }
            }
        }
    }
    else if(interpolation_type == "INTER_LANCZOS4"){ //8x8像素领域内的Lanczos插值

    }
//    for(int i = 0; i < B.w * B.h; i++) std::cout << (int)B.data[i] << " ";
//    std::cout << std::endl;
    return B;
}
int main()
{
    //cv::Mat img(10, 10, CV_8UC3, cv::Scalar(255, 0, 0));
//    u_char *p = (u_char *)malloc(240 * 320 * sizeof(u_char));
//    memcpy(p, img.data, 5);
//    for(int i = 0; i < 11; i++) std::cout << (int)p[i] << " ";
    cv::Mat img = cv::imread("../test.jpg");
   // cv::imshow("123", img);
    //cv::waitKey(10);
    //std::cout << img.channels() << std::endl;
    MyMat A(img);

    //for(int i = 0; i < A.w * A.h * A.c; i++) std::cout << (int)A.data[i] <<" ";


    int x, y;
    std::cin >> x >> y;
    MyMat B = resize(A, x, y, "INTER_LINEAR");
    cv::Mat C = B.to_cvMat();
//    cv::Mat out;
//    cv::resize(img, out, cv::Size(500, 500) ,cv::INTER_NEAREST);
    cv::imshow("123",C);
//    cv::imwrite("../data.jpg", out);
    cv::waitKey();

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值