使用双三次方法的 C++ 图像插值
Posted
技术标签:
【中文标题】使用双三次方法的 C++ 图像插值【英文标题】:C++ Image interpolation with Bicubic method 【发布时间】:2016-04-07 07:24:07 【问题描述】:我只是想通过 BiCubic 插值来平滑图像。我得到了一些用于插入 RGB 图像的代码。我已更改代码以适用于灰度图像。但结果我只得到了全黑的图像。考虑的输入和输出图像大小相同。代码粘贴在下面。请帮我。提前致谢。
inline Uint16 saturate(float x, unsigned max_pixel)
return x > max_pixel ? max_pixel
: x < 0.0f ? 0
: Uint16(x);
inline float get_subpixel(const Uint16* in, std::size_t dest_width, std::size_t dest_height, unsigned x, unsigned y)
if (x < dest_width && y < dest_height)
return in[(y * dest_width) + x];
return 0;
void interpolate(unsigned dest_width, unsigned dest_height, unsigned bits_allocated, const Uint16* src, Uint16** dest)
const double tx = 1;
const double ty = 1;
float C[5] = 0 ;
unsigned max_bit = pow(2, bits_allocated);
for (unsigned i = 0; i < dest_height; ++i)
for (unsigned j = 0; j < dest_width; ++j)
const float x = float(tx * j);
const float y = float(ty * i);
const float dx = tx * j - x, dx2 = dx * dx, dx3 = dx2 * dx;
const float dy = ty * i - y, dy2 = dy * dy, dy3 = dy2 * dy;
for (int jj = 0; jj < 4; ++jj)
const int idx = y - 1 + jj;
float a0 = get_subpixel(src, dest_width, dest_height, x, idx);
float d0 = get_subpixel(src, dest_width, dest_height, x - 1, idx) - a0;
float d2 = get_subpixel(src, dest_width, dest_height, x + 1, idx) - a0;
float d3 = get_subpixel(src, dest_width, dest_height, x + 2, idx) - a0;
float a1 = -(1.0f / 3.0f) * d0 + d2 - (1.0f / 6.0f) * d3;
float a2 = 0.5f * d0 + 0.5f * d2;
float a3 = -(1.0f / 6.0f) * d0 - 0.5f * d2 + (1.0f / 6.0f) * d3;
C[jj] = a0 + a1 * dx + a2 * dx2 + a3 * dx3;
d0 = C[0] - C[1];
d2 = C[2] - C[1];
d3 = C[3] - C[1];
a0 = C[1];
a1 = -(1.0f / 3.0f) * d0 + d2 - (1.0f / 6.0f) * d3;
a2 = 0.5f * d0 + 0.5f * d2;
a3 = -(1.0f / 6.0f) * d0 - 0.5f * d2 + (1.0f / 6.0f) * d3;
(*dest)[i * dest_width + j] = saturate(a0 + a1 * dy + a2 * dy2 + a3 * dy3, max_bit);
【问题讨论】:
get_subpixel 调用期间是否有任何越界访问?当您越界时,它将返回 0 ( black )。调试器可以在这里为您提供帮助。只是我的第一个想法。 感谢您的回复...有一些越界访问,但并非所有呼叫都可以访问 我检查了结果像素值。它们大多低于 100。 只是一个旁注:你不能通过插值来提高图像质量。你的问题:我没有通读你所有的代码,但我看到了很多 float 和 uint16 的东西。您是否有可能有 8 位输入和更大的输出?如果您在 16 位图像中的值低于 100,您会看到黑色。只是一个快速的猜测.. 我看到很多像素偏移计算看起来像[y * height + x]
。我不熟悉这段代码,但通常将y
乘以步幅或像素宽度,然后加上 x。这是因为每个y
单元代表一整行像素,而一行通常包含width
像素。
【参考方案1】:
你怎么会有这个?直到 jj 循环结束才计算 c,大括号应该在 d 之上 - 我不考虑该方法是否正确。
for (int jj = 0; jj < 4; ++jj)
const int idx = y - 1 + jj;
float a0 = get_subpixel(src, dest_width, dest_height, x, idx);
float d0 = get_subpixel(src, dest_width, dest_height, x - 1, idx) - a0;
float d2 = get_subpixel(src, dest_width, dest_height, x + 1, idx) - a0;
float d3 = get_subpixel(src, dest_width, dest_height, x + 2, idx) - a0;
float a1 = -(1.0f / 3.0f) * d0 + d2 - (1.0f / 6.0f) * d3;
float a2 = 0.5f * d0 + 0.5f * d2;
float a3 = -(1.0f / 6.0f) * d0 - 0.5f * d2 + (1.0f / 6.0f) * d3;
C[jj] = a0 + a1 * dx + a2 * dx2 + a3 * dx3;
// // end jj
d0 = C[0] - C[1];
d2 = C[2] - C[1];
d3 = C[3] - C[1];
a0 = C[1];
a1 = -(1.0f / 3.0f) * d0 + d2 - (1.0f / 6.0f) * d3;
a2 = 0.5f * d0 + 0.5f * d2;
a3 = -(1.0f / 6.0f) * d0 - 0.5f * d2 + (1.0f / 6.0f) * d3;
(*dest)[i * dest_height + j] = saturate(a0 + a1 * dy + a2 * dy2 + a3 * dy3, max_bit);
// end jj move his above
【讨论】:
你给了我一个有效的观点。谢谢你。但是回答你的问题,循环结束括号不会影响,因为 C 数组已经用 0 初始化,所以不会出现索引问题。 (*dest) 上的相同索引也将分配 4 次,直到 jj 循环结束。所以我们需要的最后一个值将在 jj 循环的最后一次迭代中分配到该索引中。但从逻辑上讲,我所做的并不正确。但从技术上讲,它的工作原理:) 我不知道为什么要浪费这个计算——你能指出你得到的原始代码吗?【参考方案2】:我想分享很棒的链接 cubic splines
【讨论】:
以上是关于使用双三次方法的 C++ 图像插值的主要内容,如果未能解决你的问题,请参考以下文章