[OpenCV] Image Scaling

Introduce

This is a commonly useful function. Sometimes we don't want to integrate the whole OpenCV only due to the little requirement for Scaling.

插值类型 主观感受 图像轮廓 总体评价 处理耗时

最临近点插值

N earrst_ N eighbour

马赛克现象严重 不清晰 最差 5秒

双线性插值

B ilinear

图像模糊,不锐利 边缘不清晰,有锯齿现象 6秒

双立方插值

B icubic

图像较模糊,较锐利 锯齿现象有所改善 折中 8秒

自适应样条插值

S-S pline

图像相对清晰,锐利 边缘变得清晰,锯齿现象消失 18秒

自适应样条增强

S-S pline_ XL

图像清晰,锐利 边缘锐利,清晰 最好 20秒

 

附加题之智能缩放:https://github.com/esimov/caire

 

 

Effect Comparison

From: http://www.cnblogs.com/celerychen/archive/2010/11/25/3588222.html

 

模糊后其实也差不多。

 

Code Implement

https://github.com/yglukhov/bicubic-interpolation-image-processing/blob/master/libimage.c

IplImage * bilinear(IplImage *img, int newWidth, int newHeight)
{
    int w= newWidth;
    int h = newHeight;
    IplImage * img2 =0;
    img2 = cvCreateImage(cvSize(w,h),IPL_DEPTH_8U,3); 
    uchar * Data = img2->imageData;
    uchar * data = img->imageData;
    int a,b,c,d,x,y,index;
    float tx = (float)(img->width-1)/w;
    float ty = (float)(img->height-1)/h;
    float x_diff, y_diff;
    int i,j,k;

     for(i=0; i<h; i++)
     for(j=0; j<w; j++)
     {
              x = (int)(tx * j);
              y = (int)(ty * i);
              
              x_diff = ((tx * j) -x);
              y_diff = ((ty * i) -y );

              index = y*img->widthStep + x*img->nChannels;
              // cac diem lan can
              a = (int)index;
              b = (int)(index + img->nChannels);                  
              c = (int)(index + img->widthStep);
              d = (int)(index + img->widthStep + img->nChannels);
              
              for(k=0; k<3; k++)
              Data[i*img2->widthStep + j*img2->nChannels  +k] = 
              data[a+k]*(1-x_diff)*(1-y_diff)
              +data[b+k]*(1-y_diff)*(x_diff)
              +data[c+k]*(y_diff)*(1-x_diff)
              +data[d+k]*(y_diff)*(x_diff);
     }
     return img2;
}

 

https://github.com/Seo-Hyung/Bilinear-Interpolation

#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
#include <iostream>
#include <string>

using namespace cv;
using namespace std;

int main(int argc, char** argv) {

    Mat image = imread("C:/Users/westbro/Desktop/Lenna.png");

    double h_rate = 2.0;
    double w_rate = 2.0;

    int h = image.rows*h_rate;
    int w = image.cols*w_rate;

    Mat result_img(h, w, CV_8UC3, Scalar(0));

    for (int y = 0; y < result_img.rows - 1; y++) {
        for (int x = 0; x < result_img.cols - 1; x++) {
            int px = (int)(x / w_rate);
            int py = (int)(y / h_rate);

            if (px >= image.cols - 1 || py >= image.rows - 1) break;

            double fx1 = (double)x / (double)w_rate - (double)px;
            double fx2 = 1 - fx1;
            double fy1 = (double)y / (double)h_rate - (double)py;
            double fy2 = 1 - fy1;

            double w1 = fx2*fy2;
            double w2 = fx1*fy2;
            double w3 = fx2*fy1;
            double w4 = fx1*fy1;

            Vec3b p1 = image.at<Vec3b>(py, px);
            Vec3b p2 = image.at<Vec3b>(py, px + 1);
            Vec3b p3 = image.at<Vec3b>(py + 1, px);
            Vec3b p4 = image.at<Vec3b>(py + 1, px + 1);
            result_img.at<Vec3b>(y, x) = w1*p1 + w2*p2 + w3*p3 + w4*p4;
        }
    }

    /// Create Windows
    namedWindow("Original Image", WINDOW_AUTOSIZE);
    namedWindow("result Image", WINDOW_AUTOSIZE);

    /// Show stuff
    imshow("Original Image", image);
    imshow("result Image", result_img);

    /// Wait until user press some key
    waitKey(0);
    return 0;
}

 

 

End.

posted @ 2019-03-12 07:29  郝壹贰叁  阅读(587)  评论(0编辑  收藏  举报