我正忙于实现一种图像过滤算法,它的工作原理如下:过滤器是一个大小为N (N必须是奇数)的二维数组,因此具有N*N个元素。大小为3的示例过滤器为:
0.25 1 0.25
0.25 0 0.25
0.25 1 0.25对于图像数据中的每个无符号字符(像素),将滤镜数组的中心放置在当前工作像素处。然后,对于过滤器覆盖的图像中的每个像素,找到过滤器覆盖的所有像素的加权和(即每个过滤器值乘以当前覆盖的像素),并将当前工作图像的像素值设置为该加权和。对图像中的每个像素执行此操作。如果滤镜像素落在图像2D数组的范围之外(即离开左、右、上、下),那么它必须围绕图像的适当边缘。
所以我有以下代码:
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)将一维数组视为二维数组:
int Image::index(int x, int y) {
return width*y + x;
}..。并且图像数据由std::unique_ptr<unsigned char[]>保护。这段代码给了我一些奇怪的输出。生成的图像具有不同像素颜色的垂直条纹,有点类似于原始图像颜色。我不知道我做错了什么,因为这个方法是在纸上检验的,而不是在代码中检验的。如果需要的话,我很乐意添加任何额外的信息。:)
发布于 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通道,这样你就不用担心溢出了。这个魔术一般看起来像这样:
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);
}https://stackoverflow.com/questions/44099410
复制相似问题