2

Bradley Adaptive しきい値処理を実装しようとしています。スタック オーバーフローの質問の 1 つに Python コードがあることは知っています。しかし、それに従ってJSで同じことを実装するのに苦労しています。誰でも私を助けてもらえますか?これまでのところ、私のコードは次のとおりです。

function computeAdaptiveThreshold (imagetest,imageWidth,imageHeight,callback) 
{

    var   size = imageWidth*imageHeight*4;
    var  s = imageWidth/8;
    var s2=s>>1;
    var t=0.15;
    var it=1.0-t;
    var i,j,diff,x1,y1,x2,y2,ind1,ind2,ind3;
    var sum=0;
    var ind=0;
    var integralImg = [];

    var canvas = document.createElement('canvas');
    var bin = canvas.getContext('2d').createImageData(imageWidth, imageHeight);

    for(i=0;i<imageWidth;i++)
    {
        sum = 0;

        for(j=0;j<imageHeight;j++)
        {
            index = i *imageHeight + j;
            sum += imagetest.data[index];

            if(i== 0)
            {
                integralImg[index] = sum;
            }
            else
            {
                //index = (i-1) * height + j;
                integralImg[index] = integralImg[(i-1) * imageHeight + j] + sum;
            }
        }
    }

    x1=0;

    for(i=1;i<imageWidth;++i)
    {
        sum=0;
        ind=i;
        ind3=ind-s2;
        if(i>s)
        {
            x1=i-s;
        }
        diff=i-x1;
        for(j=0;j<imageHeight;++j)
        {
            sum+=imagetest.data[ind];// & 0xFF;
            integralImg[ind] = integralImg[(ind-1)]+sum;
            ind+=imageWidth;
            if(i<s2)continue;
            if(j<s2)continue;
            y1=(j<s ? 0 : j-s);
            ind1=y1*imageWidth;
            ind2=j*imageWidth;

            if (((imagetest.data[ind3])*(diff * (j - y1))) < ((integralImg[(ind2 + i)] - integralImg[(ind1 + i)] - integralImg[(ind2 + x1)] + integralImg[(ind1 + x1)])*it)) {
                bin.data[ind3] = 0;
            } else {
                bin.data[ind3] = 255;
            }
            ind3 += imageWidth;
        }
    }


    y1 = 0;
    for( j = 0; j < imageHeight; ++j )
    {
        i = 0;
        y2 =imageHeight- 1;
        if( j <imageHeight- s2 )
        {
            i = imageWidth - s2;
            y2 = j + s2;
        }

        ind = j * imageWidth + i;
        if( j > s2 ) y1 = j - s2;
        ind1 = y1 * imageWidth;
        ind2 = y2 * imageWidth;
        diff = y2 - y1;
        for( ; i < imageWidth; ++i, ++ind )
        {

            x1 = ( i < s2 ? 0 : i - s2);
            x2 = i + s2;

            // check the border
            if (x2 >= imageWidth) x2 = imageWidth - 1;

            if (((imagetest.data[ind])*((x2 - x1) * diff)) < ((integralImg[(ind2 + x2)] - integralImg[(ind1 + x2)] - integralImg[(ind2 + x1)] + integralImg[(ind1 + x1)])*it)) {
                bin.data[ind] = 0;
            } else {
                bin.data[ind] = 255;
            }
        }
    }

    callback(bin);`

非常に悪いイメージを持っています。イメージとは言えません。

4

1 に答える 1

1

あなたの最初の努力はあなたのコードをリファクタリングすることであるべきだと思います:それはインデックスを扱うのがずっと簡単になるでしょう.
次に、インデックスに問題があることがわかります。画像は、グレーの画像であっても RGBA 配列であり、4 バイト = 32 ビット/ピクセルを意味します。
これは、変換 RGBA-> b&W 画像を実行してから、しきい値処理を行ってから、b&w -> RGBA を元に戻すことで処理できます。
...または、RGBA コンポーネントを処理します。ここでは、黒または白のみを出力したいので、配列に Int32 ビューを作成し、各ピクセルに対して R、G、B、A を一度に書き込むことができることに注意してください。

したがって、いくつかのコード(ここで作業:http://jsfiddle.net/gamealchemist/3zuopz19/8/):

function computeAdaptiveThreshold(sourceImageData, ratio, callback) {
    var integral = buildIntegral_Gray(sourceImageData);

    var width = sourceImageData.width;
    var height = sourceImageData.height;
    var s = width >> 4; // in fact it's s/2, but since we never use s...

    var sourceData = sourceImageData.data;
    var result = createImageData(width, height);
    var resultData = result.data;
    var resultData32 = new Uint32Array(resultData.buffer);

    var x = 0,
        y = 0,
        lineIndex = 0;

    for (y = 0; y < height; y++, lineIndex += width) {
        for (x = 0; x < width; x++) {

            var value = sourceData[(lineIndex + x) << 2];
            var x1 = Math.max(x - s, 0);
            var y1 = Math.max(y - s, 0);
            var x2 = Math.min(x + s, width - 1);
            var y2 = Math.min(y + s, height - 1);
            var area = (x2 - x1 + 1) * (y2 - y1 + 1);
            var localIntegral = getIntegralAt(integral, width, x1, y1, x2, y2);
            if (value * area > localIntegral * ratio) {
                resultData32[lineIndex + x] = 0xFFFFFFFF;
            } else {
                resultData32[lineIndex + x] = 0xFF000000;
            }
        }
    }
    return result;
}

function createImageData(width, height) {
    var canvas = document.createElement('canvas');
    return canvas.getContext('2d').createImageData(width, height);
}

function buildIntegral_Gray(sourceImageData) {
    var sourceData = sourceImageData.data;
    var width = sourceImageData.width;
    var height = sourceImageData.height;
    // should it be Int64 Array ??
    // Sure for big images 
    var integral = new Int32Array(width * height)
    // ... for loop
    var x = 0,
        y = 0,
        lineIndex = 0,
        sum = 0;
    for (x = 0; x < width; x++) {
        sum += sourceData[x << 2];
        integral[x] = sum;
    }

    for (y = 1, lineIndex = width; y < height; y++, lineIndex += width) {
        sum = 0;
        for (x = 0; x < width; x++) {
            sum += sourceData[(lineIndex + x) << 2];
            integral[lineIndex + x] = integral[lineIndex - width + x] + sum;
        }
    }
    return integral;
}

function getIntegralAt(integral, width, x1, y1, x2, y2) {
    var result = integral[x2 + y2 * width];
    if (y1 > 0) {
        result -= integral[x2 + (y1 - 1) * width];
        if (x1 > 0) {
            result += integral[(x1 - 1) + (y1 - 1) * width];
        }
    }
    if (x1 > 0) {
        result -= integral[(x1 - 1) + (y2) * width];
    }
    return result;
}
于 2015-08-12T11:56:36.403 に答える