本文利用三次样条插值算法,改变鱼眼扭曲程度。效果如下图所示:
源码下载地址:利用三次样条插值算法更改鱼眼特效的扭曲程度资源-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插值初始化如下:
- 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;
- }
通过点击转化成圆形按钮可实现将图片转化成圆形: