【问题标题】:Downsample an Image对图像进行下采样
【发布时间】:2013-03-14 10:44:14
【问题描述】:

我正在尝试将图像下采样 2,我假设它是灰度图像,所以我将只使用一个通道,我尝试平均 4 个像素,然后将结果放入 destImage。我不知道如何正确填充 destImage。请在此处找到代码:

void downsizeRow(unsigned char *srcImage, unsigned char *dstImage, int srcWidth )
{

    unsigned char *srcPtr = srcImage;
    unsigned char *dstPtr = dstImage;

    int stride = srcWidth;
    int b;
    for (int i = 0; i< 4; i++)
    {

        b  = srcPtr[0]+srcPtr[1] + srcPtr[stride + 0] + srcPtr[stride + 1] ;

        srcPtr++;
        dstPtr[0] = (uint8_t)((b + 2)/4);;
        dstPtr++;
    }

}

void downscaleImage( unsigned char *srcImage, unsigned char *dstImage, int srcWidth, int dstHeight, int dstWidth)
{

    unsigned char *srcPtr=srcImage;
    unsigned char *dstPtr=dstImage;

    int in_stride = dstWidth;
    int out_stride = dstHeight;

    for (int j=0;j<dstHeight;j++)
    {
        downsizeRow(srcPtr, dstPtr, srcWidth);  // in_stride is needed
        // as the function requires access to iptr+in_stride
        srcPtr+=in_stride * 2;
        dstImage+=out_stride;
    }
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    unsigned char srcimage[4*4];
    unsigned char dstimage[2*2];


    for (int i = 0; i<4*4; i++)
    {
        srcimage[i] = 25;
    }
    std::cout<<"source Image \n"<<std::endl;
    for (int i = 0; i<4*4; i++)
    {

        std::cout<<srcimage[i];
    }

    downscaleImage(srcimage, dstimage, 4,4,2);
    std::cout<<"dest Image"<<std::endl;
    for (int i = 0; i<2*2; i++)
    {

    //    std::cout<<dstimage[i];
    }

    return a.exec();
}

【问题讨论】:

  • 是否必须手动执行?
  • 你阅读的图片是什么类型的?
  • 尝试更具体。结果到底有什么问题?
  • @ddriver 我想优化它,对于大图像,ARM 上的 opencv resize 非常慢。
  • 如果平均超过 4 个像素,是否应该在投射之前将 dstPtr[0] 中的值除以 4(而不是 2)?

标签: c++ c image-processing imagefilter


【解决方案1】:

您的代码并没有太大的错误——基本上只需正确跟踪读/写指针的位置(记得用步幅进行更新)。这需要以一种或另一种方式使用 2 个嵌套循环。 (+ 将分隔线固定为 4)。

我发现以下方法很有用:一次处理一行并没有太大的速度损失,但可以更轻松地集成各种内核

iptr=input_image;  in_stride = in_width;
optr=output_image; out_stride = out_width;
for (j=0;j<out_height;j++) {
    process_row(iptr, optr, in_width);  // in_stride is needed
    // as the function requires access to iptr+in_stride
    iptr+=in_stride * 2;
    optr+=out_stride;
}

【讨论】:

  • 我已经根据你的更新了代码。现在这一切都正确吗?
  • 不——我也有一个错误,你设法找出来了。 optr=output_image; 自然而然。缺少的两件事是输入/输出图像的步幅不同。而且,在 process_row 函数中,您必须每一步都前进到iptr += 2;。这与外循环中有iptr += in_stride * 2; 的原因相同。
【解决方案2】:

我看到你正在使用 Qt,所以为了防止你不需要重新发明轮子,QImage 有一个方便的功能,可以为你调整大小(有效地进行下采样)。

QImage smallImage = bigImage.scaled(bigImage.width() / 2, bigImage.heigth() / 2, Qt::KeepAspectRatio, Qt::SmoothTransformation);

如果 QImage 对您来说太慢,您也可以尝试使用通常更快的 QPixmap。

省略Qt::SmoothTransformation 将退回到使用默认的Qt::FastTransformation,这样会更快。

【讨论】:

  • @Mahmoud - 你说的慢是什么意思?你测试了吗?有结果吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-04
  • 2015-08-08
  • 1970-01-01
  • 2017-09-29
  • 2012-05-12
  • 2014-04-26
  • 2012-03-18
相关资源
最近更新 更多