私は画像操作ルーチンのライブラリをJavaからCに移植しています。結果を比較すると、少しの違いがあります。これらの違いが異なる言語の浮動小数点値の扱いにあるのは合理的ですか、それとも私はまだやるべきことがありますか?畳み込みフィルタ - Float Precision C Vs Java
このルーチンは、3 x 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は、たとえばカーネル要素のxOffsetを提供します。
主なポイントは、私の結果はせいぜい1ビット外です。以下はピクセル値です。
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さん
「クランプ」の適切な単語は、実際には「飽和」です。あなたが誰かと話している場合、彼らは「飽和している」ということをすぐに知るでしょうが、必ずしも「クランプ」する必要はありません。 –
@トレヴァー:それは本当に人の背景に依存します。 –