三次和 catmull 样条对图像的影响

2021-12-17 00:00:00 image interpolation math c++

我正在尝试实现如下功能

I am trying to implement some function like below

为此,我尝试使用 三次插值Catmull 插值(分别检查两者以比较最佳结果),我不明白这些插值有什么影响在图像上显示以及我们如何在我们点击设置曲线的地方获得这些点值?以及我们需要单独定义图像上这些黑点的函数吗?

For this I am trying to use Cubic interpolation and Catmull interpolation ( check both separately to compare the best result) , what i am not understanding is what impact these interpolation show on image and how we can get these points values where we clicked to set that curve ? and do we need to define the function these black points on the image separately ?

我正在从这些资源中获得帮助

I am getting help from these resources

来源 1

来源 2

大致相同的焦点

编辑

int main (int argc, const char** argv)
{
Mat input = imread ("E:\img2.jpg");
for(int i=0 ; i<input.rows ; i++)
{
    for (int p=0;p<input.cols;p++)
    {
        //for(int t=0; t<input.channels(); t++)
    //{

        input.at<cv::Vec3b>(i,p)[0] = 255*correction(input.at<cv::Vec3b>(i,p)[0]/255.0,ctrl,N);  //B
        input.at<cv::Vec3b>(i,p)[1] = 255*correction(input.at<cv::Vec3b>(i,p)[1]/255.0,ctrl,N);  //G
        input.at<cv::Vec3b>(i,p)[2] = 255*correction(input.at<cv::Vec3b>(i,p)[2]/255.0,ctrl,N);  //R
    //}
    }
}

imshow("image" , input);
waitKey();
}

推荐答案

所以如果你的控制点总是在同一个 x 坐标上
并在整个范围内线性分散,那么你可以这样做:

So if your control points are always on the same x coordinate
and linearly dispersed along whole range then you can do it like this:

//---------------------------------------------------------------------------
const int N=5;      // number of control points (must be >= 4)
float ctrl[N]=      // control points y values initiated with linear function y=x
    {           // x value is index*1.0/(N-1)
    0.00,
    0.25,
    0.50,
    0.75,
    1.00,
    };
//---------------------------------------------------------------------------
float correction(float col,float *ctrl,int n)
    {
    float di=1.0/float(n-1);
    int i0,i1,i2,i3;
    float t,tt,ttt;
    float a0,a1,a2,a3,d1,d2;
    // find start control point
    col*=float(n-1);
    i1=col; col-=i1;
    i0=i1-1; if (i0< 0) i0=0;
    i2=i1+1; if (i2>=n) i2=n-1;
    i3=i1+2; if (i3>=n) i3=n-1;
    // compute interpolation coefficients
    d1=0.5*(ctrl[i2]-ctrl[i0]);
    d2=0.5*(ctrl[i3]-ctrl[i1]);
    a0=ctrl[i1];
    a1=d1;
    a2=(3.0*(ctrl[i2]-ctrl[i1]))-(2.0*d1)-d2;
    a3=d1+d2+(2.0*(-ctrl[i2]+ctrl[i1]));
    // now interpolate new colro intensity
    t=col; tt=t*t; ttt=tt*t;
    t=a0+(a1*t)+(a2*tt)+(a3*ttt);
    return t;
    }
//---------------------------------------------------------------------------

它使用 4 点 1D 插值三次(来自我上面评论中的链接)来获得新颜色,只需执行以下操作:

It uses 4-point 1D interpolation cubic (from that link in my comment above) to get new color just do this:

new_col = correction(old_col,ctrl,N);

这是它的样子:

绿色箭头表示推导错误(始终仅在整条曲线的起点和终点).可以通过在所有其他控制点之前和之后添加 2 个控制点来更正...

the green arrows shows derivation error (always only on start and end point of whole curve). It can be corrected by adding 2 more control points one before and one after all others ...

[注释]

颜色范围是 <0.0 , 1.0 > 所以如果你需要其他,那么只需将结果相乘并除以输入......

color range is < 0.0 , 1.0 > so if you need other then just multiply the result and divide the input ...

[edit1] 开始/结束推导修正了一点

float correction(float col,float *ctrl,int n)
    {
    float di=1.0/float(n-1);
    int i0,i1,i2,i3;
    float t,tt,ttt;
    float a0,a1,a2,a3,d1,d2;
    // find start control point
    col*=float(n-1);
    i1=col; col-=i1;
    i0=i1-1;
    i2=i1+1; if (i2>=n) i2=n-1;
    i3=i1+2;
    // compute interpolation coefficients
    if (i0>=0) d1=0.5*(ctrl[i2]-ctrl[i0]); else d1=ctrl[i2]-ctrl[i1];
    if (i3< n) d2=0.5*(ctrl[i3]-ctrl[i1]); else d2=ctrl[i2]-ctrl[i1];
    a0=ctrl[i1];
    a1=d1;
    a2=(3.0*(ctrl[i2]-ctrl[i1]))-(2.0*d1)-d2;
    a3=d1+d2+(2.0*(-ctrl[i2]+ctrl[i1]));
    // now interpolate new colro intensity
    t=col; tt=t*t; ttt=tt*t;
    t=a0+(a1*t)+(a2*tt)+(a3*ttt);
    return t;
    }

[edit2] 只是对系数的一些说明

它们都是从这个条件派生出来的:

they are all derived from this conditions:

y(t) = a0 + a1*t + a2*t*t + a3*t*t*t // direct value
y'(t) = a1 + 2*a2*t + 3*a3*t*t        // first derivation

现在你有了 y0,y1,y2,y3 所以我选择了 y(0)=y1y(1)=y2code> 提供 c0 连续性(曲线之间的连接点的值相同)
现在我需要 c1 连续性,所以我添加 y'(0) 必须与上一条曲线的 y'(1) 相同.
对于 y'(0) 我选择点 y0,y1,y2 之间的平均方向
对于 y'(1) 我选择点之间的平均方向 y1,y2,y3
这些对于下一个/上一个片段是相同的,所以就足够了.现在把它们放在一起:

now you have points y0,y1,y2,y3 so I chose that y(0)=y1 and y(1)=y2 which gives c0 continuity (value is the same in the joint points between curves)
now I need c1 continuity so i add y'(0) must be the same as y'(1) from previous curve.
for y'(0) I choose avg direction between points y0,y1,y2
for y'(1) I choose avg direction between points y1,y2,y3
These are the same for the next/previous segments so it is enough. Now put it all together:

y(0)  = y0           = a0 + a1*0 + a2*0*0 + a3*0*0*0
y(1)  = y1           = a0 + a1*1 + a2*1*1 + a3*1*1*1
y'(0) = 0.5*(y2-y0) = a1 + 2*a2*0 + 3*a3*0*0
y'(1) = 0.5*(y3-y1) = a1 + 2*a2*1 + 3*a3*1*1

并求解这个方程组(a0,a1,a2,a3 = ?).你会得到我在上面的源代码中所拥有的.如果您需要曲线的不同属性,那么只需制作不同的方程式...

And solve this system of equtions (a0,a1,a2,a3 = ?). You will get what I have in source code above. If you need different properties of the curve then just make different equations ...

[edit3] 用法

pic1=pic0; // copy source image to destination pic is mine image class ...
for (y=0;y<pic1.ys;y++) // go through all pixels
 for (x=0;x<pic1.xs;x++)
    {
    float i;
     //  read, convert, write pixel 
    i=pic1.p[y][x].db[0]; i=255.0*correction(i/255.0,red control points,5); pic1.p[y][x].db[0]=i;
    i=pic1.p[y][x].db[1]; i=255.0*correction(i/255.0,green control points,5); pic1.p[y][x].db[1]=i;
    i=pic1.p[y][x].db[2]; i=255.0*correction(i/255.0,blue control points,5); pic1.p[y][x].db[2]=i;
    }

顶部有每个 R,G,B 的控制点.左下角为原图,右下角为校正后的图像.

On top there are control points per R,G,B. On bottom left is original image and on bottom right is corrected image.

相关文章