首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++图像滤波算法

C++图像滤波算法
EN

Stack Overflow用户
提问于 2017-05-22 00:49:57
回答 1查看 3.1K关注 0票数 3

我正忙于实现一种图像过滤算法,它的工作原理如下:过滤器是一个大小为N (N必须是奇数)的二维数组,因此具有N*N个元素。大小为3的示例过滤器为:

代码语言:javascript
复制
0.25 1 0.25
0.25 0 0.25
0.25 1 0.25

对于图像数据中的每个无符号字符(像素),将滤镜数组的中心放置在当前工作像素处。然后,对于过滤器覆盖的图像中的每个像素,找到过滤器覆盖的所有像素的加权和(即每个过滤器值乘以当前覆盖的像素),并将当前工作图像的像素值设置为该加权和。对图像中的每个像素执行此操作。如果滤镜像素落在图像2D数组的范围之外(即离开左、右、上、下),那么它必须围绕图像的适当边缘。

所以我有以下代码:

代码语言:javascript
复制
Image Image::operator%(const Filter & g) {
    Image filtered = *this;
    std::vector<std::vector<float>> filter = g.get_filter();
    Image::iterator beg = filtered.begin();
    Image::iterator end = filtered.end();
    unsigned char* pixel_data = filtered.data.get();
    int pixel_index = 0;

    while(beg != end) {
        // current working pixel value
        unsigned char* c_pixel = *beg;

        float weight = 0;

        // starting x and y position (top left) relative to the centre
        // of the filter at index 'pixel'
        int start_y = pixel_index - (g.get_size()-1) / 2;
        int start_x = pixel_index - (g.get_size()-1) / 2;

        for(int row = 0; row < g.get_size(); ++row) {
            std::vector<float> r = filter.at(row);
            int c_row = start_y + row;

            if(c_row >= height) {
                c_row %= height;
            } else if(c_row < 0) {
                c_row += height;
            }

            for(int col = 0; col < g.get_size(); ++col) {
                // current column of filter relative
                // to the image pixel
                int c_col = start_x + col;

                if(c_col >= width) {
                    c_col %= width;
                } else if(c_col < 0) {
                    c_col += width;
                }
                weight += pixel_data[this->index(c_col, c_row)]*r.at(col);
            }
        }
        *c_pixel = weight;
        ++beg;
        ++pixel_index;
    }
    return filtered;
}

如果你想知道,this->index(c_col, c_row)将一维数组视为二维数组:

代码语言:javascript
复制
int Image::index(int x, int y) {
    return width*y + x;
}

..。并且图像数据由std::unique_ptr<unsigned char[]>保护。这段代码给了我一些奇怪的输出。生成的图像具有不同像素颜色的垂直条纹,有点类似于原始图像颜色。我不知道我做错了什么,因为这个方法是在纸上检验的,而不是在代码中检验的。如果需要的话,我很乐意添加任何额外的信息。:)

EN

回答 1

Stack Overflow用户

发布于 2017-05-22 02:25:28

我首先关心的是图像像素格式。您说输出是std::unique_ptr<unsigned char[]>,但是权重是使用浮点数计算和编写的。您的index方法返回一个索引,而不考虑像素数据大小{ 1_BYTE (单色),3_BYTE (RGB8),4_Byte(RGBA8) }。pixel_data是字符(字节),所以我不确定你是否正确地索引了像素数据,没有考虑像素大小,也没有忽略alpha (如果需要)。

另一个问题是,如果您使用的是RGB(a)数据,那么从INT->Float的转换将无法正确缩放。乘以浮点数会将像素缩放为实数,而不是单独缩放通道。这将导致通道相互溢出,通常是不正确的。

下一步是创建一个滤镜,该滤镜以具有RGB通道(忽略alpha)的像素的形式读取和写入数据,以确保您的滤镜是直通的。然后,您将编写一个过滤器,通过将RGB通道设置为0或255来删除该通道。(红色通道、蓝色通道、绿色通道)

一旦确定可以单独且正确地操纵RGB,则可以开始应用权重。

第一次尝试会很慢。最终你会发现,你可以使用掩码从G通道中抓取R_B通道,这样你就不用担心溢出了。这个魔术一般看起来像这样:

代码语言:javascript
复制
    UInt32 WeightPixel(UInt32 value, float weight)
    {
        const UInt32 MASK1 = (UInt32)0x00ff00ff; // _R_B
        const UInt32 MASK2 = (UInt32)0xff00ff00; // A_G_

        int f2 = (int)(256 * weight); // Scale weight into char range

        // >> 8 is just divide by 256
        return (UInt32)(((((value & MASK1) * f2)) >> 8) & MASK1)
               | (UInt32)(((((value & MASK2) * f2)) >> 8) & MASK2);
    }
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44099410

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档