本文利用三次样条插值算法,改变鱼眼扭曲程度。效果如下图所示:

源码下载地址:利用三次样条插值算法更改鱼眼特效的扭曲程度资源-CSDN文库
(说明:源码基于QT和opencv )
主要代码
鱼眼扭曲
void fisheye(const Mat &src, Mat &dst)
{
    dst.create(src.rows, src.cols, CV_8UC3);
    dst.setTo(0);
    if (srcX.size() == 0 || srcX.size() != dstY.size() || cubicCoeffs == nullptr)
        return;
    Point2f center;
    center.x = src.cols / 2.0;
    center.y = src.rows / 2.0;
    double rr = sqrt(center.x * center.x + center.y * center.y);
    for (int id = 1; id < src.rows - 1; id++) {
        for (int jd = 1; jd < src.cols - 1; jd++) {
            double xd = 1.0 * (jd - center.x) / rr;//nomalize to -1 --- 1
            double yd = 1.0 * (id - center.y) / rr;
            double rd = sqrt(xd * xd + yd * yd);
            double phid = atan2(yd, xd);
            //double xs = asin(rd) * 2 / PI * cos(phid) * rr * sqrt(2);
            //double ys = asin(rd) * 2 / PI * sin(phid) * rr * sqrt(2);
            double nr = 0;
            if (rd>0 && rd <= 1)
                cubicSpline.cubicSplineInterpolation2(cubicCoeffs, srcX, rd, nr);
            double xs = nr * cos(phid) * rr * sqrt(2);
            double ys = nr * sin(phid) * rr * sqrt(2);
            int is = round(ys +  center.y);
            int js = round(xs + center.x);
            if (is > dst.rows - 1 || is < 1 || js>dst.cols - 1 || js < 1){
                //is = id;
                //js = jd;
            }
            else{
                dst.at<Vec3b>(id, jd)[0] = src.at<Vec3b>(is, js)[0];
                dst.at<Vec3b>(id, jd)[1] = src.at<Vec3b>(is, js)[1];
                dst.at<Vec3b>(id, jd)[2] = src.at<Vec3b>(is, js)[2];
            }
        }
    }
}
其中cubicSpline.cubicSplineInterpolation2是调用三次样条插值函数计算某点的对应值,详情可查看源码。
三次样条插值算法
可以查看以下博文:
三次样条插值 https://mp.csdn.net/mp_blog/creation/editor/134171633插值初始化如下:
https://mp.csdn.net/mp_blog/creation/editor/134171633插值初始化如下:
    vector<double> dstY;
    vector<double> srcX;
    //srcX(not change after initialize)
    srcX.push_back(0.0f);
    srcX.push_back(0.2f);
    srcX.push_back(0.4f);
    srcX.push_back(0.6f);
    srcX.push_back(0.8f);
    srcX.push_back(1.0f);
    //dstY
    for (int i = 0;i < (int)srcX.size();i++)
    {
        float v = asin(srcX.at(i)) * 2 / PI;
        if (v > 1.0f)
            v = 1.0f;
     }将图片压缩成圆形
通过点击转化成圆形按钮可实现将图片转化成圆形:


















