图像处理中,除以255这个运算到底应该怎么办??

psic__ 2008-12-27 01:56:43


除以255这个运算在图像处理中很常见。因为颜色的值实际上是一个规格化的数,如果以字节整数来表示的话,范围是0-255。进行颜色的乘法运算之后就需要除以255保证值仍然在0-255之间。

但是这个除以255的运算始终找不到一个准确高效的优化方法。很多人都使用>>8来代替,显然这是完全错误的,>>8是除以256,而我们需要的是除以255。
正确一点的方法是这样:

C = A * B + 0x80;
C = ((C >> 8) + C) >> 8;

这样至少可以在整数部分得到正确的结果了,代价是额外的2次加法和2次位移

而且上面的方法并不能完全解决问题。它只能得到整数部分的结果,有些时候我们需要连续做两次乘法,也就是说需要连续除两次255,这个时候误差就会累积下来

举个列子

D=A*B*C A=165,B=86,C=203
A*B规格化后为 165*86/255=55.64706
(A*B)*C规格化后为 55.64706*203/255=44.2994
最后结果舍入到整数为44

而使用上面的优化方法后
A*B得到56
然后再*C得到45
最后因为误差累积而得到错误的结果……

可以看到,用整数运算的话,这个问题实在是没有很好的解决办法……

最后我想到的比较可行的办法,就是完全用浮点运算代替整数运算。效率上应该差不了太远,对于乘法运算的速度整数和浮点数都差不多,而加法运算的速度整数要快很多,但是整数乘法后的额外运算会大大的抵消这个优势。所以我想用浮点运算在效率上应该不会比整数运算差多少,而且可以保证绝对的运算精度。不知大家有何看法??
...全文
2857 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
njsjlx 2008-12-29
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 eblis88 的回复:]
所有的算法步骤,内部都用浮点计算
最后图像显示的时候取整数部分既可。

视觉不能分辨一个灰度级的差别。
[/Quote]

用浮点数?循环体内使用浮点效率很差。
我做过图片缩放的测试,用整型数只不到15ms,用浮点超过100ms
eblis88 2008-12-28
  • 打赏
  • 举报
回复
所有的算法步骤,内部都用浮点计算
最后图像显示的时候取整数部分既可。

视觉不能分辨一个灰度级的差别。
njsjlx 2008-12-27
  • 打赏
  • 举报
回复
我觉得大部分的情况下>>8可以接受,这在图像上看起来差异很小的
精确一点的话可以尝试(x+128)>>8这个值更合理一点
CodeProject-Jerry 2008-12-27
  • 打赏
  • 举报
回复
如要转换为灰度图像
使用

int gray=r*0.3+g*0.59+b*0.11;

记得运算的时候用float, 最后转换到int
CodeProject-Jerry 2008-12-27
  • 打赏
  • 举报
回复
给你一段 otsu 2值化 参考


/* otsu_th.c */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "mypgm.h"

void otsu_th( )
/* binarization by Otsu's method
based on maximization of inter-class variance */

{
int hist[GRAYLEVEL];
double prob[GRAYLEVEL], omega[GRAYLEVEL]; /* prob of graylevels */
double myu[GRAYLEVEL]; /* mean value for separation */
double max_sigma, sigma[GRAYLEVEL]; /* inter-class variance */
int i, x, y; /* Loop variable */
int threshold; /* threshold for binarization */

printf("Otsu's binarization process starts now.\n");

/* Histogram generation */
for (i = 0; i < GRAYLEVEL; i++) hist[i] = 0;
for (y = 0; y < y_size1; y++)
for (x = 0; x < x_size1; x++) {
hist[image1[y][x]]++;
}
/* calculation of probability density */
for ( i = 0; i < GRAYLEVEL; i ++ ) {
prob[i] = (double)hist[i] / (x_size1 * y_size1);
}

/* omega & myu generation */
omega[0] = prob[0];
myu[0] = 0.0; /* 0.0 times prob[0] equals zero */
for (i = 1; i < GRAYLEVEL; i++) {
omega[i] = omega[i-1] + prob[i];
myu[i] = myu[i-1] + i*prob[i];
}

/* sigma maximization
sigma stands for inter-class variance
and determines optimal threshold value */
threshold = 0;
max_sigma = 0.0;
for (i = 0; i < GRAYLEVEL-1; i++) {
if (omega[i] != 0.0 && omega[i] != 1.0)
sigma[i] = pow(myu[GRAYLEVEL-1]*omega[i] - myu[i], 2) /
(omega[i]*(1.0 - omega[i]));
else
sigma[i] = 0.0;
if (sigma[i] > max_sigma) {
max_sigma = sigma[i];
threshold = i;
}
}

printf("\nthreshold value = %d\n", threshold);

/* binarization output into image2 */
x_size2 = x_size1;
y_size2 = y_size1;
for (y = 0; y < y_size2; y++)
for (x = 0; x < x_size2; x++)
if (image1[y][x] > threshold)
image2[y][x] = MAX_BRIGHTNESS;
else
image2[y][x] = 0;

}


main( )
{
load_image_data( ); /* input image1 */
otsu_th( ); /* Otsu's binarization method is applied */
save_image_data( ); /* output image2 */
return 0;
}

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧