gpt4 book ai didi

c++ - 用于极端图像缩小的快速、高质量像素插值

转载 作者:行者123 更新时间:2023-11-28 04:16:36 28 4
gpt4 key购买 nike

在我的程序中,我将 500px 或更大的图像缩小到大约 16px-32px 的极端水平。源图像是用户指定的,所以我无法控制它的大小。正如您所想象的,很少有像素插值能够成立,结果不可避免地会出现严重的锯齿。

我尝试过双线性、双三次和平方平均采样。平方平均采样实际上提供了最不错的结果,但它越小,采样半径就必须越大。结果,它变得相当慢——比其他插值方法慢。

我也试过自适应平方平均采样,越小采样半径越大,越接近原始大小采样半径越小。但是,它会产生问题,我不认为这是最好的方法。

所以问题是:推荐的像素插值类型是什么?这种像素插值既快又适用于这种极端的缩小水平?

我不想使用库,所以我需要一些我可以手写代码并且不太复杂的东西。我正在使用 VS 2012 使用 C++。

这是我按照要求尝试过的一些示例代码(希望我的伪代码剪切和粘贴没有错误)。这执行了 7x7 的平均缩小,虽然它比双线性或双三次插值的结果更好,但它也需要相当大的打击:

    // Sizing control
ctl(0): "Resize",Range=(0,800),Val=100

// Variables
float fracx,fracy;
int Xnew,Ynew,p,q,Calc;
int x,y,p1,q1,i,j;

//New image dimensions
Xnew=image->width*ctl(0)/100;
Ynew=image->height*ctl(0)/100;

for (y=0; y<image->height; y++){ // rows
for (x=0; x<image->width; x++){ // columns

p1=(int)x*image->width/Xnew;
q1=(int)y*image->height/Ynew;

for (z=0; z<3; z++){ // channels

for (i=-3;i<=3;i++) {
for (j=-3;j<=3;j++) {
Calc += (int)(src(p1-i,q1-j,z));
} //j
} //i

Calc /= 49;

pset(x, y, z, Calc);

} // channels


} // columns
} // rows

谢谢!

最佳答案

第一点是使用指向数据的指针。切勿在每个像素处使用索引。当您编写:src(p1-i,q1-j,z)pset(x, y, z, Calc) 时进行了多少计算?使用指向数据的指针并对其进行操作。

第二:你的算法是错误的。您不需要平均过滤器,但您希望在源图像上创建一个网格,并为每个网格单元计算平均值并将其放入输出图像的相应像素中。

具体的解决方案应该根据您的数据表示量身定制,但它可能是这样的:

    std::vector<uint32_t> accum(Xnew);
std::vector<uint32_t> count(Xnew);
uint32_t *paccum, *pcount;
uint8_t* pin = /*pointer to input data*/;
uint8_t* pout = /*pointer to output data*/;
for (int dr = 0, sr = 0, w = image->width, h = image->height; sr < h; ++dr) {
memset(paccum = accum.data(), 0, Xnew*4);
memset(pcount = count.data(), 0, Xnew*4);
while (sr * Ynew / h == dr) {
paccum = accum.data();
pcount = count.data();
for (int dc = 0, sc = 0; sc < w; ++sc) {
*paccum += *i;
*pcount += 1;
++pin;
if (sc * Xnew / w > dc) {
++dc;
++paccum;
++pcount;
}
}
sr++;
}
std::transform(begin(accum), end(accum), begin(count), pout, std::divides<uint32_t>());
pout += Xnew;
}

这是使用我自己的库(仍在开发中)编写的,它似乎可以工作,但后来我更改了变量名称以使其在这里更简单,所以我不保证任何事情!

想法是有一个 32 位整数的本地缓冲区,它可以保存落在输出图像一行中的行中所有像素的部分和。然后除以细胞计数并将输出保存到最终图像。

您应该做的第一件事是建立一个绩效评估系统来衡量任何变化对绩效的影响程度。

关于c++ - 用于极端图像缩小的快速、高质量像素插值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56450999/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com