【问题标题】:Impact of cubic and catmull splines on image三次样条和 catmull 样条对图像的影响
【发布时间】:2014-05-12 16:18:24
【问题描述】:

我正在尝试实现如下所示的一些功能

为此,我尝试使用Cubic interpolationCatmull interpolation(分别检查以比较最佳结果),我不明白这些插值对图像的影响以及我们如何获得这些点值我们点击设置那条曲线?我们需要在图像上分别定义这些黑点的功能吗?

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

Source 1

Source 2

Approx the same focus

编辑

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();
}

【问题讨论】:

  • 我。立方有 4 个控制点而不是 5 !!!,II。我使用这个插值三次 stackoverflow.com/a/22582447/2521214 你的控制点总是在 x 网格线上吗?在这种情况下,您可以只使用一维插值,但必须相应地创建系数
  • 是的,我的点总是在同一个 x 坐标上
  • 我的功能在 0-1 范围内!!!尝试 new_col = 255.0*correction(colors[0]/255.0,ctrl,N);控制点也设置为一些值? (如果它们为零,则结果为零)。结知道在您的情况下拆分和合并做什么...您必须选择像素...重新计算RGB然后将像素设置回去...
  • 不是控制点值0.00, 0.25, 0.50, 0.75, 1.00,
  • 您的问题是 t 是实际通道强度而不是通道索引!删除最后一个刚刚离开的 3 个更正电话。并用 input.at<:vec3b>(i,p)[0,1 or 2]/255.0 改变 t/255

标签: c++ image math interpolation


【解决方案1】:

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

//---------------------------------------------------------------------------
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 插值三次(来自我上面评论中的那个链接)来获得新颜色,只需这样做:

new_col = correction(old_col,ctrl,N);

这就是它的样子:

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

[备注]

颜色范围是&lt; 0.0 , 1.0 &gt;,所以如果您需要其他颜色范围,只需将结果相乘并除以输入...

[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] 只是对系数的一些澄清

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

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

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 = ?)。你会在上面的源代码中得到我所拥有的。如果您需要曲线的不同属性,则只需制作不同的方程...

[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 的控制点。左下角是原图,右下角是修正图。

【讨论】:

  • 当我在曲线上移动给定点时,这会改变颜色值吗?我不想手动提供颜色,但是当我发现图像颜色更适合用于调整曲线时,我想知道该值,因为我想将相同的场景应用于不同的颜色,最后感谢您你的回答很好,我有一些我想学习的点。
  • 更正将单个值转换为修改后的单个值。要转换整个图像,您必须为每个像素执行 2 次嵌套 for 循环 (x,y) 获取像素 (x,y) 的 R,G,B 值调用 R=correction(R,...); G=correction(G,...),... 并将新的 R,G,B 值写入该像素。现在将其封装为一些函数,如 update_image(...) 并在每次更改任何控制点时调用它,...不要忘记在之后重绘窗口...而且每种颜色都有自己的控制点 ....
  • 你能告诉我这条线实际上在执行什么程序吗if (i0&gt;=0) d1=0.5*(ctrl[i2]-ctrl[i0]); else d1=ctrl[i2]-ctrl[i1];
  • d1,d2 是三次曲线起点和终点的推导(方向)。对于相邻的立方体,它们必须相同,以便它们顺利合并在一起。所以我将它们设置为相邻点推导的平均值。问题在于,对于第一个三次方,之前没有三次方,因此平均推导 d1 不正确,而是仅采用下一个点的全方向(不使用前一个点)。最后一个立方结束时的 d2 也是如此。
  • @AHF 是的,只需在某处打印控制点或将它们保存到文件中......并在需要时重新加载
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-29
  • 2016-08-07
相关资源
最近更新 更多