寻找快速图像失真算法
我正在尝试实现一个使用 shpere 失真滤波器的应用程序。我正在使用 此处 中的算法,该算法通过 getPixel( ) 和 setpixel() 方法。我的问题是它对于 Android 设备来说太慢了,并且有些应用程序实现相同球体(和其他)过滤器的速度比我的方法更快。 (例如 Picsay Pro 应用程序)任何人都可以分享或指导寻找或实现快速失真算法。
实现该算法的实际过滤器:
public boolean sphereFilter(Bitmap b, boolean bSmoothing)
{
int nWidth = b.getWidth();
int nHeight = b.getHeight();
Point [][] pt = new Point[nWidth][nHeight];
Point mid = new Point();
mid.x = nWidth/2;
mid.y = nHeight/2;
double theta, radius;
double newX, newY;
for (int x = 0; x < nWidth; ++x)
for (int y = 0; y < nHeight; ++y)
{
pt[x][y]= new Point();
}
for (int x = 0; x < nWidth; ++x)
for (int y = 0; y < nHeight; ++y)
{
int trueX = x - mid.x;
int trueY = y - mid.y;
theta = Math.atan2((trueY),(trueX));
radius = Math.sqrt(trueX*trueX + trueY*trueY);
double newRadius = radius * radius/(Math.max(mid.x, mid.y));
newX = mid.x + (newRadius * Math.cos(theta));
if (newX > 0 && newX < nWidth)
{
pt[x][y].x = (int) newX;
}
else
{
pt[x][y].x = 0;
pt[x][y].y = 0;
}
newY = mid.y + (newRadius * Math.sin(theta));
if (newY > 0 && newY < nHeight && newX > 0 && newX < nWidth)
{
pt[x][ y].y = (int) newY;
}
else
{
pt[x][y].x = pt[x][y].y = 0;
}
}
offsetFilterAbs(b, pt);
return true;
}
替换计算像素位置的代码。
public boolean offsetFilterAbs(Bitmap b, Point[][] offset )
{
int nWidth = b.getWidth();
int nHeight = b.getHeight();
int xOffset, yOffset;
for(int y=0;y < nHeight;++y)
{
for(int x=0; x < nWidth; ++x )
{
xOffset = offset[x][y].x;
yOffset = offset[x][y].y;
if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth)
{
b.setPixel(x, y, b.getPixel(xOffset, yOffset));
}
}
}
return true;
}
I am trying to implement an application which uses shpere distortion filter. I am using an the algorithm from here which changes pixels location by getPixel() and setpixel() methods. My problem is it is too slow for Android devices and there are applications which implements same sphere(and others) filter way faster than my approach. ( for example Picsay Pro app) Could anyone share or give direction to find or implement fast distortion algorithms.
Actual filter that implements the algorithm:
public boolean sphereFilter(Bitmap b, boolean bSmoothing)
{
int nWidth = b.getWidth();
int nHeight = b.getHeight();
Point [][] pt = new Point[nWidth][nHeight];
Point mid = new Point();
mid.x = nWidth/2;
mid.y = nHeight/2;
double theta, radius;
double newX, newY;
for (int x = 0; x < nWidth; ++x)
for (int y = 0; y < nHeight; ++y)
{
pt[x][y]= new Point();
}
for (int x = 0; x < nWidth; ++x)
for (int y = 0; y < nHeight; ++y)
{
int trueX = x - mid.x;
int trueY = y - mid.y;
theta = Math.atan2((trueY),(trueX));
radius = Math.sqrt(trueX*trueX + trueY*trueY);
double newRadius = radius * radius/(Math.max(mid.x, mid.y));
newX = mid.x + (newRadius * Math.cos(theta));
if (newX > 0 && newX < nWidth)
{
pt[x][y].x = (int) newX;
}
else
{
pt[x][y].x = 0;
pt[x][y].y = 0;
}
newY = mid.y + (newRadius * Math.sin(theta));
if (newY > 0 && newY < nHeight && newX > 0 && newX < nWidth)
{
pt[x][ y].y = (int) newY;
}
else
{
pt[x][y].x = pt[x][y].y = 0;
}
}
offsetFilterAbs(b, pt);
return true;
}
The code that replaces the calculated pixels' positions.
public boolean offsetFilterAbs(Bitmap b, Point[][] offset )
{
int nWidth = b.getWidth();
int nHeight = b.getHeight();
int xOffset, yOffset;
for(int y=0;y < nHeight;++y)
{
for(int x=0; x < nWidth; ++x )
{
xOffset = offset[x][y].x;
yOffset = offset[x][y].y;
if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth)
{
b.setPixel(x, y, b.getPixel(xOffset, yOffset));
}
}
}
return true;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
来自我的 上面评论中的链接:
(请记住,在此等式中,
x
和y
的范围是从 0 到 1。如果您的尺寸范围从 0 到w
,请将0.5
替换为w/2
)使用 一点数学,我们可以看到
这使得最终得到的方程
(我删除了平方根,因为无论如何,我们将结果取为实数...因此,为了使其等效,我们应该使用
n/2
而不是n
,但因为我们是 定义“膨胀因子”,我们可以省略额外的除法)只需少量乘法和一个实数幂,这可能是您希望获得的最快速度。
From my link in the comments above:
(Remember that, in this equation,
x
andy
span from 0 to 1. If your dimensions span from 0 tow
, replace0.5
withw/2
)Using a bit of math, we can see that
This makes the final resulting equation
(I removed the square-root since we take the result to a real-power anyways... so really to make this equivalent we should use
n/2
instead ofn
, but since we are defining "bulge-factor," we can just leave out the extra division)With only a handful of multiplications and a single real-exponentiation, this is probably the fastest you can hope to get.