📄 yuvmedianfilter.c
字号:
memcpy(&output[y* row_stride], &input[y*row_stride], width); inpix = &input[0]; outpix = &output[0]; for(y=0; y < height; ++y) { a = 0; while(a<radius) { outpix[a] = inpix[a]; ++a; outpix[width-a] = inpix[width-a]; } inpix += row_stride; outpix += row_stride; } count = 0; offset = radius*row_stride+radius; /* Offset top-left of processing */ /* Window to its centre */ refpix = &input[offset]; outpix = &output[offset]; for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { reference = *refpix; total = 0; count = 0; pixel = refpix-offset; b = radius_count; while( b > 0 ) { a = radius_count; --b; while( a > 0 ) { diff = reference - *pixel; --a; if (diff < threshold && diff > -threshold) { total += *pixel; count++; } ++pixel; } pixel += (row_stride - radius_count); } ++avg_replace[count]; /* * If we don't have enough samples to make a decent * pseudo-median use a simple mean */ if (count <= min_count) { *outpix = ( ( (refpix[-row_stride-1] + refpix[-row_stride]) + (refpix[-row_stride+1] + refpix[-1]) ) + ( ((refpix[0]<<3) + 8 + refpix[1]) + (refpix[row_stride-1] + refpix[row_stride]) + refpix[row_stride+1] ) ) >> 4; } else { *outpix = (total + count/2) / count; } ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); }}voidfilter_buffer_fast(int width, int height, int row_stride, int radius, int threshold, uint8_t * const input, uint8_t * const output){ int a; int b; uint8_t *pixel; int total; int count; int radius_count; int x; int y; int offset; uint8_t *refpix; uint8_t *outpix; int fasttype; /* If no filtering should be done, just copy data and leave. */ if (threshold == 0) { for (y = 0; y < height; y++) memcpy(&output[y * row_stride], &input[y * row_stride], width); return; } /* Calculate the number of pixels from one extreme of the radius to the other extreme. */ radius_count = radius + radius + 1; /* Figure out which optimized filtering algorithm to use, if any. */ if (radius == 1 && param_weight_type == 2) fasttype = 1; else if (radius == 1 && param_weight_type == 1) fasttype = 2; else if (radius == 2 && param_weight_type == 1) fasttype = 3; else if (radius == 1 && param_weight_type == 3) fasttype = 4; else if (radius == 1 && param_weight_type == 4) fasttype = 5; else fasttype = 0; /* Copy top rows of picture, without filtering. */ for(y=0; y < radius; y++) memcpy(&output[y * row_stride], &input[y * row_stride], width); /* Copy bottom rows of picture, without filtering. */ for(y=height - radius; y < height; y++) memcpy(&output[y* row_stride], &input[y*row_stride], width); /* Copy leftmost/righmost columns of picture, without filtering. */ refpix = &input[0]; outpix = &output[0]; for(y=0; y < height; ++y) { a = 0; while(a<radius) { outpix[a] = refpix[a]; ++a; outpix[width-a] = refpix[width-a]; } refpix += row_stride; outpix += row_stride; } /* Find the top-left corner of the portion of the image that will be filtered. */ offset = radius*row_stride+radius; refpix = &input[offset]; outpix = &output[offset]; /* Loop through the portion of the image to be filtered. Use a simple mean, but process certain combinations of radius/weight pairs more efficiently. Note that adding half the pixel count to the pixel value accomplishes rounding the pixel value to the nearest whole value. */ switch (fasttype) { case 1: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Radius 1, weight 2.667. The 8 pixels surrounding the current one have a weight of 3, the current pixel has a weight of 8, for a total weight of 8*3+8 = 32. */ *outpix = ((3 * ((int)refpix[-row_stride-1] + (int)refpix[-row_stride] + ((int)refpix[-row_stride+1] + (int)refpix[-1]) + (int)refpix[1] + (int)refpix[row_stride-1] + (int)refpix[row_stride] + (int)refpix[row_stride+1])) + (((int)refpix[0])<<3) + 16) >> 5; ++avg_replace[9]; ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; case 2: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Radius 1, weight 8. The 8 pixels surrounding the current one have a weight of 1, the current pixel has a weight of 8, for a total weight of 8*1+8 = 16. */ *outpix = (((int)refpix[-row_stride-1] + (int)refpix[-row_stride] + (int)refpix[-row_stride+1] + (int)refpix[-1] + (int)refpix[1] + (int)refpix[row_stride-1] + (int)refpix[row_stride] + (int)refpix[row_stride+1]) + (((int)refpix[0])<<3) + 8) >> 4; ++avg_replace[9]; ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; case 3: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Radius 2, weight 8. The 24 pixels surrounding the current one have a weight of 1, the current pixel has a weight of 8, for a total weight of 24*1+8 = 32. */ *outpix = (((int)refpix[-row_stride-row_stride-2] + (int)refpix[-row_stride-row_stride-1] + (int)refpix[-row_stride-row_stride] + (int)refpix[-row_stride-row_stride+1] + (int)refpix[-row_stride-row_stride+2] + (int)refpix[-row_stride-2] + (int)refpix[-row_stride-1] + (int)refpix[-row_stride] + (int)refpix[-row_stride+1] + (int)refpix[-row_stride+2] + (int)refpix[-2] + (int)refpix[-1] + (int)refpix[1] + (int)refpix[2] + (int)refpix[row_stride-2] + (int)refpix[row_stride-1] + (int)refpix[row_stride] + (int)refpix[row_stride+1] + (int)refpix[row_stride+2] + (int)refpix[row_stride+row_stride-2] + (int)refpix[row_stride+row_stride-1] + (int)refpix[row_stride+row_stride] + (int)refpix[row_stride+row_stride+1] + (int)refpix[row_stride+row_stride+2]) + (((int)refpix[0])<<3) + 16) >> 5; ++avg_replace[25]; ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; case 4: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Radius 1, weight 13.333. The 8 pixels surrounding the current one have a weight of 3, the current pixel has a weight of 40, for a total weight of 8*3+40 = 64. */ *outpix = ((3 * ((int)refpix[-row_stride-1] + (int)refpix[-row_stride] + ((int)refpix[-row_stride+1] + (int)refpix[-1]) + (int)refpix[1] + (int)refpix[row_stride-1] + (int)refpix[row_stride] + (int)refpix[row_stride+1])) + (((int)refpix[0])*40) + 32) >> 6; ++avg_replace[9]; ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; case 5: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Radius 1, weight 24. The 8 pixels surrounding the current one have a weight of 1, the current pixel has a weight of 24, for a total weight of 8*1+24 = 32. */ *outpix = (((int)refpix[-row_stride-1] + (int)refpix[-row_stride] + (int)refpix[-row_stride+1] + (int)refpix[-1] + (int)refpix[1] + (int)refpix[row_stride-1] + (int)refpix[row_stride] + (int)refpix[row_stride+1]) + (((int)refpix[0])*24) + 16) >> 5; ++avg_replace[9]; ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; default: for(y=radius; y < height-radius; y++) { for(x=radius; x < width - radius; x++) { /* Reset the total pixel value and the count of pixels found in the given radius. */ total = 0; count = 0; /* Now loop through all pixels in a radius around the current one, and add up their values, skipping the current pixel. */ pixel = refpix-offset; b = radius_count; while( b > 0 ) { a = radius_count; --b; while( a > 0 ) { --a; if (pixel != refpix) { total += *pixel; count++; } ++pixel; } pixel += (row_stride - radius_count); } ++avg_replace[count]; /* Finally, calculate the pixel's new value. */ *outpix = (total + (refpix[0] * param_weight) + (count >> 1)) / (count + param_weight); ++refpix; ++outpix; } refpix += (row_stride-width+(radius*2)); outpix += (row_stride-width+(radius*2)); } break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -