2015-08-11 3 views
2

Я пытаюсь реализовать Bradley Adaptive thresholding. Я знаю, что в одном из вопросов переполнения стека есть код python. Но я изо всех сил пытаюсь реализовать то же самое в JS, следуя этому. Кто-нибудь может мне помочь, пожалуйста! Пока что мой код:Javascript Bradley адаптивная реализация порога

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);` 

Я получаю очень плохие изображения. Я должен сказать, что я не могу назвать это образ.

+0

Вы лечение RGBA изображения, как если бы это было ч/б изображения. Это корень вашей проблемы. – GameAlchemist

+0

Привет GameAlchemist спасибо за комментарий. Но мой тест изображения - это серое изображение. Вы говорите, что мне нужно использовать изображение без учета альфа-компонента, такого как Android RGB_565? Я также добавил свой обновленный код. Заранее спасибо – thegeek

ответ

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; 
} 
+0

Спасибо, что нашли время и помогли мне. Я тестировал ваш код как есть, и я не вижу выходного изображения. Я вижу, что он помещает белые и черные в буфер resultData32, но когда я ничего не возвращаю. Должен ли я установить этот буфер в imagedata перед возвратом из этого метода. Извините, я относительно новичок. – thegeek

+0

Да, была проблема с Alpha, которую я не задавал для черных пикселей. Я обновил свой ответ, и вот рабочая скрипка: http: //jsfiddle.net/gamealchemist/3zuopz19/8/ – GameAlchemist

+0

Отлично! спасибо ... очень ценю вашу помощь – thegeek

Смежные вопросы