带有三次插值的正弦图像失真
Posted
技术标签:
【中文标题】带有三次插值的正弦图像失真【英文标题】:Image distortion with sine with cubic interpolation 【发布时间】:2015-03-30 11:44:32 【问题描述】:我正在尝试使用下一个代码的三次插值在 y 轴上使用正弦/余弦进行失真,我将新图像的大小与旧图像保持相同。而且结果看起来不太好。我只在 y 轴上进行插值。我根据Math 进行了计算
Mat cubic(Mat old, int freq)
int height = old.size().height;
int width = old.size().width;
int p0,p1,p2,p3;
int Bp0,Bp1,Bp2,Bp3;
int Gp0,Gp1,Gp2,Gp3;
int Rp0,Rp1,Rp2,Rp3;
unsigned char B,G,R;
double Ba,Bb,Bc,Bd;
double Ga,Gb,Gc,Gd;
double Ra,Rb,Rc,Rd;
double fi,fj;
Mat res(height,width,CV_8UC3,cv::Scalar(100));
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
fi = i;
fj = (j - (((height/30)*(sin((M_PI*i)/(freq/2)))))) + sqrt(height) ;
//Get the indexes of the for neighbors
if(fj > 20 & fj < height)
p1 = floor(fj);
p2 = ceil(fj);
p0 = p1-1;
p3 = p2+1;
//get the color values
Vec3b p0Color = old.at<Vec3b>(Point(floor(fi),p0));
Vec3b p1Color = old.at<Vec3b>(Point(floor(fi),p1));
Vec3b p2Color = old.at<Vec3b>(Point(floor(fi),p2));
Vec3b p3Color = old.at<Vec3b>(Point(floor(fi),p3));
//cout <<" fj:" <<fj<< " p0: " << p0 <<" p1: "<< p1 << " p2: "<<p2 <<" p3:" <<p3;
Bp0 = p0Color.val[0]; Bp1 = p1Color.val[0]; Bp2 = p2Color.val[0]; Bp3 = p3Color.val[0];
Ba = -0.5*Bp0 + 1.5*Bp1 - 1.5*Bp2 + 0.5*Bp3;
Bb = Bp0 - 2.5*Bp1 + 2*Bp2 -0.5*Bp3;
Bc = -0.5*Bp0 + 0.5*Bp2;
Bd = Bp1;
Gp0 = p0Color.val[1]; Gp1 = p1Color.val[1]; Gp2 = p2Color.val[1]; Gp3 = p3Color.val[1];
Ga = -0.5*Gp0 + 1.5*Gp1 - 1.5*Gp2 + 0.5*Gp3;
Gb = Gp0 - 2.5*Gp1 + 2*Gp2 -0.5*Gp3;
Gc = -0.5*Gp0 + 0.5*Gp2;
Gd = Gp1;
Rp0 = p0Color.val[2]; Rp1 = p1Color.val[2]; Rp2 = p2Color.val[2]; Rp3 = p3Color.val[2];
Ra = -0.5*Rp0 + 1.5*Rp1 - 1.5*Rp2 + 0.5*Rp3;
Rb = Rp0 - 2.5*Rp1 + 2*Rp2 -0.5*Rp3;
Rc = -0.5*Rp0 + 0.5*Rp2;
Rd = Rp1;
B = floor(Ba*pow(fj,3) + Bb*pow(fj,2) + Bc*fj + Bd);
G = floor(Ga*pow(fj,3) + Gb*pow(fj,2) + Gc*fj + Gd);
R = floor(Ra*pow(fj,3) + Rb*pow(fj,2) + Rc*fj + Rd);
if(B==0)
cout <<"list:" << Ba <<" " << Bb <<" "<< Bc <<" " << Bd;
Vec3b finalColor(B,G,R);
res.at<Vec3b>(j,i) = finalColor;
namedWindow( "cubic", CV_WINDOW_AUTOSIZE );
imshow( "cubic", res);
return res;
出处照片
双线性插值
三次插值
谢谢
【问题讨论】:
可能是整数溢出? 确实在段的边缘存在整数溢出。不知道怎么解决。 也许可以通过某种因素改变量化范围?您可以在计算之前将每个像素除以 2(或某个常数),然后再将它们全部乘以 2。 【参考方案1】:问题解决了。
Mat cubic(Mat old, int freq)
int height = old.size().height;
int width = old.size().width;
int p0,p1,p2,p3;
int Bp0,Bp1,Bp2,Bp3;
int Gp0,Gp1,Gp2,Gp3;
int Rp0,Rp1,Rp2,Rp3;
double B,G,R;
double fi,fj;
Mat res(height,width,CV_8UC3,cv::Scalar(100));
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
fi = i;
fj = (j - (((height/30)*(sin((M_PI*i)/(freq/2)))))) + sqrt(height) ;
//Get the indexes of the for neighbors
if(fj > 20 & fj < height)
p1 = floor(fj);
p2 = ceil(fj);
p0 = p1-1;
p3 = p2+1;
//get the color values
Vec3b p0Color = old.at<Vec3b>(Point(floor(fi),p0));
Vec3b p1Color = old.at<Vec3b>(Point(floor(fi),p1));
Vec3b p2Color = old.at<Vec3b>(Point(floor(fi),p2));
Vec3b p3Color = old.at<Vec3b>(Point(floor(fi),p3));
if(i == 258 && j==59)
Bp0 = p0Color.val[0]; Bp1 = p1Color.val[0]; Bp2 = p2Color.val[0]; Bp3 = p3Color.val[0];
Gp0 = p0Color.val[1]; Gp1 = p1Color.val[1]; Gp2 = p2Color.val[1]; Gp3 = p3Color.val[1];
Rp0 = p0Color.val[2]; Rp1 = p1Color.val[2]; Rp2 = p2Color.val[2]; Rp3 = p3Color.val[2];
//Normalize the fj
fj = (fj - floor(fj));
B= Bp1 + 0.5 * fj*(Bp2 - Bp0 + fj*(2.0*Bp0 - 5.0*Bp1 + 4.0*Bp2 - Bp3 + fj*(3.0*(Bp1 - Bp2) + Bp3 - Bp0)));
G= Gp1 + 0.5 * fj*(Gp2 - Gp0 + fj*(2.0*Gp0 - 5.0*Gp1 + 4.0*Gp2 - Gp3 + fj*(3.0*(Gp1 - Gp2) + Gp3 - Gp0)));
R= Rp1 + 0.5 * fj*(Rp2 - Rp0 + fj*(2.0*Rp0 - 5.0*Rp1 + 4.0*Rp2 - Rp3 + fj*(3.0*(Rp1 - Rp2) + Rp3 - Rp0)));
if(B > 255)
B=255;
if(G>255)
G=255;
if(R>255)
R=255;
if(B < 0)
B=0;
if(G<0)
G=0;
if(R<0)
R=0;
Vec3b finalColor(B,G,R);
res.at<Vec3b>(j,i) = finalColor;
namedWindow( "cubic", CV_WINDOW_AUTOSIZE );
imshow( "cubic", res);
return res;
我忘记在将 fj 放入最终三次函数之前对其进行归一化
新结果:
【讨论】:
以上是关于带有三次插值的正弦图像失真的主要内容,如果未能解决你的问题,请参考以下文章