在不使用缓冲区的情况下对2个图像(加法,减法等)进行操作

时间:2014-01-14 10:24:36

标签: c++ visual-c++ image-processing pylons

我想知道有没有办法在两个图像上进行操作而不逐像素地分析它们。我尝试实时制作两台摄像机的混合视图。因此,必须至少以每秒10帧的速度进行操作。

我的程序的第一个版本如下所示:

                        CPylonImage im1;
                CPylonImage im2;

    uint32_t width = im2.GetWidth();
        uint32_t height = im2.GetHeight();
        uint8_t* buffer1 = static_cast<uint8_t*>( im1.GetBuffer());
        uint8_t* p1 = buffer1;
        uint8_t* buffer2 = static_cast<uint8_t*>( im2.GetBuffer());
        uint8_t* p2 = buffer2;
        for (uint32_t y = 0; y < height; ++y)
        {
            for (uint32_t x = 0; x < width; ++x, ++p1)
            {
                *p2 = (uint8_t)*p1+*p2;
                ++p2;
            }
        }
        ShowImage( im2, "Mixed image");

但这太慢了。

我将非常感谢任何答案。

2 个答案:

答案 0 :(得分:3)

您共享的代码有很多问题,在评论部分中您声明它甚至不起作用。我认为你应该专注于一次解决一个问题,当代码真正起作用时,尝试加快它是有意义的。

您的应用程序从一个图像中检索width,从另一个图像中检索height。这很少会带来好处。

    uint32_t width = im1.GetWidth();
    uint32_t height = im2.GetHeight();

好的,buffer1指向im1p1指向buffer1。我认为您并不真正需要p1,而只需使用buffer1

    uint8_t* buffer1 = static_cast<uint8_t*>( im1.GetBuffer());
    uint8_t* p1 = buffer1;

现在buffer2p2指向im1什么?!不应该是im2 ???你真的不需要p2

    uint8_t* buffer2 = static_cast<uint8_t*>( im1.GetBuffer());
    uint8_t* p2 = buffer2;


    for (uint32_t y = 0; y < height; ++y)
    {

下一个循环递增p,这是一个未声明的变量。我想你试图增加p1

        for (uint32_t x = 0; x < width; ++x, ++p)
        {
            *p2 = (uint8_t)*p1+*p2;
            ++p2;
        }
    }

现在显示im2是没有意义的,因为它没有被代码修改。

    ShowImage( im2, "Mixed image");

还有一件事,如果im1im2的尺寸不同,可能会导致崩溃。

我强烈建议您查看以下帖子,了解如何提出更好的问题并让人们帮助您:Short, Self Contained, Correct (Compilable), Example

有一些技术可以加速这些算术运算的处理:

答案 1 :(得分:0)

在开始优化之前,请确保输出正确无误!

表达式

*p2 = (uint8_t)*p1+*p2;

会溢出并给你错误的结果。演员(uint8_t)不会神奇 将您的值剪辑到有效范围,但只转换您的添加结果。 在这种情况下,强制转换不会执行任何操作,因为操作数是uint8_t。

const uint16_t a = *p1;
const uint16_t b = *p2;
const uint16_t sum = a+b;
*p2 = static_cast<uint8_t>( sum > 255 ? 255 : sum );

更好的是,添加结果并除以2,这样你就可以保持有效范围, 只松开LSB而且它是无分支的。

*p2 = static_cast<uint8_t>( sum >> 1 );

在必须使用其他技术之前,您可以尝试一些其他技巧。

  • 使用支持自动矢量化的编译器(vc&gt; = 2012,gcc&gt; = 4.7)并将其打开。
  • 如果您正在为Windows 32bit编译,请使用“/ arch:SSE2”
  • 使用constrestrict
  • 提供编译器提示
  • 如果您确定窗口大小始终相同,请使用固定宽度和高度

e.g。

void add( const CPylonImage& im1, CPylonImage& im2 )
{
    const int w = 1294; //im1.width();
    const int h = 964; //im1.height();

    const uint8_t* restrict buffer1 = static_cast<uint8_t*>( im1.getBuffer() );
    uint8_t* restrict buffer2 = static_cast<uint8_t*>( im2.getBuffer() );
    for( int i = 0; i < w*h; i++ )
    {
        const uint16_t a = buffer1[i];
        const uint16_t b = buffer2[i];
        const uint16_t sum = a+b >> 1;
        buffer2[i] = static_cast<uint8_t>( sum );
    }
}