Census Transform in HLSL
The census transform is a filter that represents the pixel’s neighborhood relationship in a binary string. The binary string will be 0000000
if the center pixel is lesser than all of its neighbors. The binary string will be 11111111
if the center pixel is greater than or equal to all of its neighbors.
The filter does not depend on the image’s actual intensity. As a result, the filter is robust to illumination.
Source Code
float GetGreyScale(float3 Color)
{
return max(max(Color.r, Color.g), Color.b);
}
float GetCensusTransform(sampler SampleImage, float2 Tex, float2 PixelSize)
{
float OutputColor = 0.0;
float4 ColumnTex[3];
ColumnTex[0] = Tex.xyyy + (float4(-1.0, +1.0, 0.0, -1.0) * PixelSize.xyyy);
ColumnTex[1] = Tex.xyyy + (float4( 0.0, +1.0, 0.0, -1.0) * PixelSize.xyyy);
ColumnTex[2] = Tex.xyyy + (float4(+1.0, +1.0, 0.0, -1.0) * PixelSize.xyyy);
const int Neighbors = 8;
float SampleNeighbor[Neighbors];
SampleNeighbor[0] = GetGreyScale(tex2D(SampleImage, ColumnTex[0].xy).rgb);
SampleNeighbor[1] = GetGreyScale(tex2D(SampleImage, ColumnTex[1].xy).rgb);
SampleNeighbor[2] = GetGreyScale(tex2D(SampleImage, ColumnTex[2].xy).rgb);
SampleNeighbor[3] = GetGreyScale(tex2D(SampleImage, ColumnTex[0].xz).rgb);
SampleNeighbor[4] = GetGreyScale(tex2D(SampleImage, ColumnTex[2].xz).rgb);
SampleNeighbor[5] = GetGreyScale(tex2D(SampleImage, ColumnTex[0].xw).rgb);
SampleNeighbor[6] = GetGreyScale(tex2D(SampleImage, ColumnTex[1].xw).rgb);
SampleNeighbor[7] = GetGreyScale(tex2D(SampleImage, ColumnTex[2].xw).rgb);
float CenterSample = GetGreyScale(tex2D(SampleImage, ColumnTex[1].xz).rgb);
// Generate 8-bit integer from the 8-pixel neighborhood
for(int i = 0; i < Neighbors; i++)
{
float Comparison = step(SampleNeighbor[i], CenterSample);
OutputColor += ldexp(Comparison, i);
}
// Convert the 8-bit integer to float, and average the results from each channel
return OutputColor * (1.0 / (exp2(8) - 1));
}