GLImageProcessing ROI(感兴趣区域)

发布于 2025-01-01 00:04:04 字数 4702 浏览 1 评论 0原文

我目前正在尝试模糊图像的一部分。我使用苹果的示例代码此处

示例代码本身可以模糊整个图像并将其绘制到 EAGLView,我想要做的是通过提供 ROI 仅模糊部分图像。

我不知道如何为该功能提供投资回报率。

这是将图像绘制到视图的代码;

void drawGL(int wide, int high, float val, int mode)
{
static int prevmode = -1;
typedef void (*procfunc)(V2fT2f *, float);

typedef struct {
    procfunc func;
    procfunc degen;
} Filter;

const Filter filter[] = {
    { brightness             },
    { contrast               },
    { extrapolate, greyscale },
    { hue                    },
    { extrapolate, blur      }, // The blur could be exaggerated by downsampling to half size
};
#define NUM_FILTERS (sizeof(filter)/sizeof(filter[0]))
rt_assert(mode < NUM_FILTERS);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0, wide, 0, high, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(wide, high, 1);

glBindTexture(GL_TEXTURE_2D, Input.texID);

if (prevmode != mode)
{
    prevmode = mode;
    if (filter[mode].degen)
    {
        // Cache degenerate image, potentially a different size than the system framebuffer
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, DegenFBO);
        glViewport(0, 0, Degen.wide*Degen.s, Degen.high*Degen.t);
        // The entire framebuffer won't be written to if the image was padded to POT.
        // In this case, clearing is a performance win on TBDR systems.
        glClear(GL_COLOR_BUFFER_BIT);
        glDisable(GL_BLEND);
        filter[mode].degen(fullquad, 1.0);
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, SystemFBO);
    }
}

// Render filtered image to system framebuffer
glViewport(0, 0, wide, high);
filter[mode].func(flipquad, val);
glCheckError();
}

这就是模糊图像的功能;

static void blur(V2fT2f *quad, float t) // t = 1
{
GLint tex;
V2fT2f tmpquad[4];
float offw = t / Input.wide;
float offh = t / Input.high;
int i;

glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);

// Three pass small blur, using rotated pattern to sample 17 texels:
//
// .\/.. 
// ./\\/ 
// \/X/\   rotated samples filter across texel corners
// /\\/. 
// ../\. 

// Pass one: center nearest sample
glVertexPointer  (2, GL_FLOAT, sizeof(V2fT2f), &quad[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &quad[0].s);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f(1.0/5, 1.0/5, 1.0/5, 1.0);
validateTexEnv();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Pass two: accumulate two rotated linear samples
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
for (i = 0; i < 4; i++)
{
    tmpquad[i].x = quad[i].s + 1.5 * offw;
    tmpquad[i].y = quad[i].t + 0.5 * offh;
    tmpquad[i].s = quad[i].s - 1.5 * offw;
    tmpquad[i].t = quad[i].t - 0.5 * offh;
}
glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &tmpquad[0].x);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &tmpquad[0].s);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, tex);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,      GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB,         GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB,         GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB,         GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB,     GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,    GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA,       GL_PRIMARY_COLOR);

glColor4f(0.5, 0.5, 0.5, 2.0/5);
validateTexEnv();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Pass three: accumulate two rotated linear samples
for (i = 0; i < 4; i++)
{
    tmpquad[i].x = quad[i].s - 0.5 * offw;
    tmpquad[i].y = quad[i].t + 1.5 * offh;
    tmpquad[i].s = quad[i].s + 0.5 * offw;
    tmpquad[i].t = quad[i].t - 1.5 * offh;
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Restore state
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Half.texID);
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB,     GL_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glDisable(GL_BLEND);
}

我应该在哪里提供 ROI,或者是否有任何其他方式可以在没有 ROI 的情况下模糊图像的一部分,我也想知道。

谢谢。

I am currently trying to blur a part of an image. I use apple's example code here

The example code itself can blur whole image and draw it to the EAGLView, what I want to do is blur only part of the image by supplying an ROI.

I do not know how to supply an ROI to the function.

Here is the code which draws image to the view;

void drawGL(int wide, int high, float val, int mode)
{
static int prevmode = -1;
typedef void (*procfunc)(V2fT2f *, float);

typedef struct {
    procfunc func;
    procfunc degen;
} Filter;

const Filter filter[] = {
    { brightness             },
    { contrast               },
    { extrapolate, greyscale },
    { hue                    },
    { extrapolate, blur      }, // The blur could be exaggerated by downsampling to half size
};
#define NUM_FILTERS (sizeof(filter)/sizeof(filter[0]))
rt_assert(mode < NUM_FILTERS);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0, wide, 0, high, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(wide, high, 1);

glBindTexture(GL_TEXTURE_2D, Input.texID);

if (prevmode != mode)
{
    prevmode = mode;
    if (filter[mode].degen)
    {
        // Cache degenerate image, potentially a different size than the system framebuffer
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, DegenFBO);
        glViewport(0, 0, Degen.wide*Degen.s, Degen.high*Degen.t);
        // The entire framebuffer won't be written to if the image was padded to POT.
        // In this case, clearing is a performance win on TBDR systems.
        glClear(GL_COLOR_BUFFER_BIT);
        glDisable(GL_BLEND);
        filter[mode].degen(fullquad, 1.0);
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, SystemFBO);
    }
}

// Render filtered image to system framebuffer
glViewport(0, 0, wide, high);
filter[mode].func(flipquad, val);
glCheckError();
}

And this is the function which blurs the image;

static void blur(V2fT2f *quad, float t) // t = 1
{
GLint tex;
V2fT2f tmpquad[4];
float offw = t / Input.wide;
float offh = t / Input.high;
int i;

glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);

// Three pass small blur, using rotated pattern to sample 17 texels:
//
// .\/.. 
// ./\\/ 
// \/X/\   rotated samples filter across texel corners
// /\\/. 
// ../\. 

// Pass one: center nearest sample
glVertexPointer  (2, GL_FLOAT, sizeof(V2fT2f), &quad[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &quad[0].s);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f(1.0/5, 1.0/5, 1.0/5, 1.0);
validateTexEnv();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Pass two: accumulate two rotated linear samples
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
for (i = 0; i < 4; i++)
{
    tmpquad[i].x = quad[i].s + 1.5 * offw;
    tmpquad[i].y = quad[i].t + 0.5 * offh;
    tmpquad[i].s = quad[i].s - 1.5 * offw;
    tmpquad[i].t = quad[i].t - 0.5 * offh;
}
glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &tmpquad[0].x);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &tmpquad[0].s);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, tex);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,      GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB,         GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB,         GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB,         GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB,     GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,    GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA,       GL_PRIMARY_COLOR);

glColor4f(0.5, 0.5, 0.5, 2.0/5);
validateTexEnv();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Pass three: accumulate two rotated linear samples
for (i = 0; i < 4; i++)
{
    tmpquad[i].x = quad[i].s - 0.5 * offw;
    tmpquad[i].y = quad[i].t + 1.5 * offh;
    tmpquad[i].s = quad[i].s + 0.5 * offw;
    tmpquad[i].t = quad[i].t - 1.5 * offh;
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Restore state
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Half.texID);
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB,     GL_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glDisable(GL_BLEND);
}

Where should I supply an ROI or if any other way is possible to blur a part of an image without ROI, I would like to know as well.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

软糯酥胸 2025-01-08 00:04:05

我对 OpenGL ES 不太了解,但这段代码使用表面上的整个(不是 ROI)纹理进行操作。
我也用这个例子。

我认为,你应该:

  • 剪切图像的投资回报率
  • 创建新的纹理
  • 模糊整个新的纹理
  • 在原始纹理上设置新的纹理

还有几个链接:
如何在 iPhone 上实现方框模糊或高斯模糊,<一个href="https://stackoverflow.com/questions/6980402/blur-effect-wet-in-wet-effect-in-paint-application-using-opengl-es">画图中的模糊效果(湿中湿效果)使用OpenGL-ES的应用程序
如何在 iPhone 中锐化/模糊 uiimage?

Im not a big OpenGL ES knower, but this code operate with whole (not ROI) textures on surface.
I using this example too.

I think, you should:

  • cut ROI of your image
  • create new texture with this image
  • blur whole new texture
  • set new texture over your original texture

Also few links:
How to implement a box or gaussian blur on iPhone, Blur Effect (Wet in Wet effect) in Paint Application Using OpenGL-ES,
how to sharp/blur an uiimage in iphone?

嘴硬脾气大 2025-01-08 00:04:05

你尝试过 glScissor() 了吗?

来自 GLES1.1 规范:

glScissor 在 window 中定义一个矩形,称为剪刀框
坐标。前两个参数 x 和 y 指定左下角
盒子的一角。 width 和 height 指定宽度和高度
盒子。

要启用和禁用剪刀测试,请调用 glEnable 和 glDisable
带参数 GL_SCISSOR_TEST。剪刀测试最初被禁用。
当启用剪刀测试时,只有位于剪刀内的像素
盒子可以通过绘图命令修改。窗口坐标有
帧缓冲区像素共享角处的整数值。
glScissor(0, 0, 1, 1) 允许仅修改左下像素
在窗口中,glScissor(0, 0, 0, 0) 不允许修改
窗口中的任何像素。

您可能需要进行 2 次抽牌;首先是未过滤的图像;第二个是经过过滤的图像,但使用剪刀测试绘制。

Have you tried glScissor() yet?

from the GLES1.1 spec:

glScissor defines a rectangle, called the scissor box, in window
coordinates. The first two arguments, x and y, specify the lower left
corner of the box. width and height specify the width and height of
the box.

To enable and disable the scissor test, call glEnable and glDisable
with argument GL_SCISSOR_TEST. The scissor test is initially disabled.
While scissor test is enabled, only pixels that lie within the scissor
box can be modified by drawing commands. Window coordinates have
integer values at the shared corners of frame buffer pixels.
glScissor(0, 0, 1, 1) allows modification of only the lower left pixel
in the window,and glScissor(0, 0, 0, 0) doesn't allow modification of
any pixels in the window.

You might have to do 2 draw passes; first the unfiltered image; the second is the filtered image but drawn with the scissor test.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文