我移植图像处理例程从Java库为C和我得到一些非常小的差异时,我比较结果。它是合理的,这些差异是在不同的语言处理浮点值的还是我还有很多工作要做!

该例程卷积用3×3的内核,它是由像素的线性阵列,宽度和深度表示的位图操作。你不必知道这个代码完全回答我的问题,它只是在这里以供参考。

Java代码;

for (int x = 0; x < width; x++){
            for (int y = 0; y < height; y++){
                int offset = (y*width)+x;
                if(x % (width-1) == 0 || y % (height-1) == 0){
                    input.setPixel(x, y, 0xFF000000); // Alpha channel only for border
                } else {
                    float r = 0;
                    float g = 0;
                    float b = 0;
                    for(int kx = -1 ; kx <= 1; kx++ ){
                        for(int ky = -1 ; ky <= 1; ky++ ){
                            int pixel = pix[offset+(width*ky)+kx];
                            int t1 = Color.red(pixel);
                            int t2 = Color.green(pixel);
                            int t3 = Color.blue(pixel);

                            float m = kernel[((ky+1)*3)+kx+1];

                            r += Color.red(pixel) * m;
                            g += Color.green(pixel) * m;
                            b += Color.blue(pixel) * m;                     
                        }
                    }
                    input.setPixel(x, y, Color.rgb(clamp((int)r), clamp((int)g), clamp((int)b)));
                }
            }
        }
        return input; 

钳位限制频带的值在范围[0..255]和Color.red相当于(像素&0x00FF0000)>> 16。

在C代码是这样的;

for(x=1;x<width-1;x++){
        for(y=1; y<height-1; y++){
            offset = x + (y*width);
            rAcc=0;
            gAcc=0;
            bAcc=0;
            for(z=0;z<kernelLength;z++){
                xk = x + xOffsets[z];
                yk = y + yOffsets[z];
                kOffset = xk + (yk * width);

                rAcc += kernel[z] * ((b1[kOffset] & rMask)>>16);
                gAcc += kernel[z] * ((b1[kOffset] & gMask)>>8);
                bAcc += kernel[z] * (b1[kOffset] & bMask);
            }

            // Clamp values
            rAcc = rAcc > 255 ? 255 : rAcc < 0 ? 0 : rAcc;
            gAcc = gAcc > 255 ? 255 : gAcc < 0 ? 0 : gAcc;
            bAcc = bAcc > 255 ? 255 : bAcc < 0 ? 0 : bAcc;


            // Round the floats
                    r = (int)(rAcc + 0.5);
            g = (int)(gAcc + 0.5);
            b = (int)(bAcc + 0.5);

            output[offset] = (a|r<<16|g<<8|b) ;
        }
    }

这是一个小不同xOffsets提供用于例如内核元件的X偏移。

主要的一点是,我的结果超出最多由一个比特。以下是像素值;

FF205448 expected
FF215449 returned
44 wrong
FF56977E expected
FF56977F returned
45 wrong
FF4A9A7D expected
FF4B9B7E returned
54 wrong
FF3F9478 expected
FF3F9578 returned
74 wrong
FF004A12 expected
FF004A13 returned

你相信这是我的代码有问题或者说在语言的差异?

此致

GAV株系

有帮助吗?

解决方案

快速查看后:

你意识到(INT)R将地板上的r值,而不是通常四舍五入呢? 在C代码,就好像使用(INT)(R + 0.5)

其他提示

继Fortega的回答,尝试从C数学的函数roundf()

Java的浮点性能是相当精确。我希望在这里发生的事情是,当值被保留在扩展精度寄存器。 IIRC,Java要求的精确度四舍五入到合适的类型。这是为了尽量确保你总是得到相同的结果(在JLS全部细节)。 C编译器将趋向于留下任何额外的精度在那里,直到结果在存储到主存储器中。

我会建议你使用双,而不是浮动。浮几乎都不是最好的选择。

这可能是由于两种语言不同的默认轮。我不是说他们(你需要阅读高达确定),但它是一个想法。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top