我一直在努力实现Bradley自适应阈值处理。我知道其中一个堆栈溢出问题中有一个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);`
我的图像非常糟糕。我应该说我不能把它称为图像。
答案 0 :(得分:1)
我认为你的第一个努力应该是重构代码:处理索引要容易得多
然后你会发现你的索引有问题:一个图像 - 即使是灰色的 - 是一个RGBA数组,意思是4个字节=每个像素32位。
你可以通过转换RGBA->处理这个问题。 b&amp; W图像,然后进行阈值处理,然后进行b&amp; w - &gt; 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;
}