Adaptive Thresholding using Integral Image [source]

Adaptive Thresholding

I have to admit that built in Flash methods is really fast in processing time and I cant beat the speed of blurred adaptive thresholding versions provided by Mario and Saqoosha. I still think it could perform faster… ;) Talking about thresholding result I cant say which one is more accurate – try it yourself.

Demo application (you will need web camera and Flash 10 installed)
See my comparison of thresholded image results

Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
var w:int = 320;
var h:int = 240;
var size:int = w * h;
var S:int = w / 8;
var S2:int = S >> 1;
var T:Number = 0.15;
var IT:Number = 1.0 - T;
var integral:Vector.<int> = new Vector.<int>(size, true);
var threshold:Vector.<uint> = new Vector.<uint>(size, true);
 
/**
* @param bmp Input image (should be gray scaled)
* @param dst Result image
*/
 
function IntegralImageThresholding(bmp:BitmapData, dst:BitmapData):void
{
	var data:Vector.<uint> = bmp.getVector(bmp.rect);
	//data.fixed = true;
	var i:int, j:int, diff:int;
	var x1:int, y1:int, x2:int, y2:int, ind1:int, ind2:int, ind3:int;
	var sum:int = 0;
	var ind:int = 0;
 
	while( ind < size )
	{
		sum += data[ind] & 0xFF;
		integral[ind] = sum;
		ind += w;
	}
 
	x1 = 0;
	for( i = 1; i < w; ++i )
	{
		sum = 0;
		ind = i;
		ind3 = ind - S2;
 
		if( i > S ) x1 = i - S;
		diff = i - x1;
		for( j = 0; j < h; ++j )
		{
			sum += data[ind] & 0xFF;
			integral[ind] = integral[int(ind-1)] + sum;
			ind += w;
 
			if(i < S2) continue;
			if(j < S2) continue;
 
			y1 = (j < S ? 0 : j - S);
 
			ind1 = y1 * w;
			ind2 = j * w;
 
			if (((data[ind3]&0xFF)*(diff * (j - y1))) < ((integral[int(ind2 + i)] - integral[int(ind1 + i)] - integral[int(ind2 + x1)] + integral[int(ind1 + x1)])*IT))
			{
				threshold[ind3] = 0x00;
			} else {
				threshold[ind3] = 0xFFFFFF;
			}
			ind3 += w;
		}
	}
 
	y1 = 0;
	for( j = 0; j < h; ++j )
	{
		i = 0;
		y2 = h - 1;
		if( j < h - S2 ) 
		{
			i = w - S2;
			y2 = j + S2;
		}
 
		ind = j * w + i;
		if( j > S2 ) y1 = j - S2;
		ind1 = y1 * w;
		ind2 = y2 * w;
		diff = y2 - y1;
		for( ; i < w; ++i, ++ind )
		{
 
			x1 = ( i < S2 ? 0 : i - S2);
			x2 = i + S2;
 
			// check the border
			if (x2 >= w) x2 = w - 1;
 
			if (((data[ind]&0xFF)*((x2 - x1) * diff)) < ((integral[int(ind2 + x2)] - integral[int(ind1 + x2)] - integral[int(ind2 + x1)] + integral[int(ind1 + x1)])*IT))
			{
				threshold[ind] = 0x00;
			} else {
				threshold[ind] = 0xFFFFFF;
			}
		}
	}
 
	dst.setVector(dst.rect, threshold);
}